启发式搜索 A*算法的OC 实现
前两天重新学习了下A*算法,上次学习A*算法已经是5年前了,看到网上铺天盖地的A*算法都是C、C++等等其他语言的,就是没有OC 的,所以抽空写了一份。今天太晚了就不说明A*算法的细节了,大家如果想学习的话建议大家看一下这篇博客http://blog.csdn.net/b2b160/article/details/4057781 。下面我就把代码贴出来吧,喜欢的可以拿去。代码中有些地方用到了一些自定义的类或者属性,大家可以在阅读代码的基础上进行修改,我自己做了一个小游戏用到了这个类,所以有些地方有改动。不过整体思路没有改动。代码的一些关键地方已经加了注释。祝晚安~
//
// Search.m
// A*算法
//
// Created by 邓竹立 on 15-5-8.
// Copyright (c) 2015年 GiveMeFive. All rights reserved.
// #import "Search.h"
#import "NodeView.h" #define kStright 10 //走直线的话 花费为10
#define kSlant 14 // 走斜线 花费为14 (1.414)
#define kMaxF 100000 //最大花费 @interface Search () @property(nonatomic,strong)NSMutableArray *colsedTable; @end @implementation Search +(instancetype)sharedSearch
{
static id instance; static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance=[[self alloc] init];
});
return instance;
} #pragma mark 搜索
/**
* 搜索的主方法
*
* @param srcNode srcNode description
* @param descNode descNode description
*/
-(void)searchPathFrom:(NodeView*)srcNode to:(NodeView*)descNode complete:(void(^)(NodeView*)) nextPathNode
{
NodeView *currentNode=srcNode; __block NodeView *nextNode; //这里定义为__block 是因为在下面的代码块中要使用 NSArray *array=[self nearNodes:currentNode]; //获取到当前节点的所有可访问节点(已访问过的和不可达的去除) __block NSInteger minF=kMaxF; for (NodeView *tmpNode in array)
{
NSInteger tmpGx=currentNode.g+[self gxFromNode:currentNode toNode:tmpNode]; //算出从当前节点到其邻接节点的gx
if (tmpNode.isInOpentable) // 判断节点是否已经再open中
{
if (tmpNode.g>tmpGx)// 如果再open 中其gx 比现在的gx大的话 说明从当前节点出发到达该节点更划算
{
tmpNode.g=tmpGx;
tmpNode.parentNode=currentNode;
}
}else//如果不在open中则加入open
{
tmpNode.g=tmpGx;
[self.openTable addObject:tmpNode];
tmpNode.inOpenTable=YES;
}
tmpNode.h=[self ManHWithNode:tmpNode descNode:descNode];
tmpNode.f=tmpNode.g+tmpNode.h;
if (tmpNode.f<minF && tmpNode.parentNode==currentNode)//如果该节点的f 在当前节点的所有邻接节点中是最小的,并且该节点的父节点是当前节点 则把该节点当做下一个要访问的节点
{
minF=tmpNode.f;
nextNode=tmpNode;
}
} [self.openTable removeObject:currentNode];
currentNode.inOpenTable=NO;
[self.colsedTable addObject:currentNode];
currentNode.inClosedTable=YES; if (nextNode==nil)//在某些情况下,以当前节点作为父节点的邻接节点都不适合作为下一个要访问的节点。
{
[self.openTable enumerateObjectsUsingBlock:^(NodeView * obj, NSUInteger idx, BOOL *stop) {
if (obj.f<minF)
{
minF=obj.f;
nextNode=obj;//找到open 表中f值最小的节点作为下一个访问的节点
}
}];
} if ([self.colsedTable containsObject:descNode])//抵达目标接地啊
{
NodeView *node=descNode;
while (node.parentNode.parentNode)
{
//这里的每个节点都是路径上的点
node=node.parentNode;
}
if (node)
{
nextPathNode(node);
}
self.openTable=nil;
self.colsedTable=nil;
return;
}else if(self.openTable.count==)
{
self.openTable=nil;
self.colsedTable=nil;
NSLog(@"不存在路径");
}else
{
currentNode=nextNode;
[self searchPathFrom:currentNode to:descNode complete:^(NodeView *node) { nextPathNode(node);
}];//递归搜索
}
} /**
* 计算两个相邻节点的gx
*
* @param node0 node0 description
* @param node1 node1 description
*
* @return return value description
*/
-(NSInteger)gxFromNode:(NodeView*)node0 toNode:(NodeView*)node1
{
NSAssert( node0 && node1, @"node 不能为空");
NSAssert([self isnNodes:node0 nearsNode:node1], @"两个节点不相邻 能计算gx");
BOOL isSlant=NO;
if ((ABS( node0.indexX-node1.indexX) + ABS(node0.indexY-node1.indexY))==)
{
isSlant=YES;
}
if (isSlant)
{
return kSlant;
} return kStright;
} /**
* 求出该节点的邻接节点 去除不可达的 和已经加入到close 表的
*
* @param node node description
*/
-(NSArray*)nearNodes:(NodeView*)node
{
NSArray *array=[self findNearNode:node];
NSMutableArray *mutable=[NSMutableArray array]; for (NodeView *tmpNode in array)
{
if (tmpNode.isAccess && !tmpNode.isInClosedTable)
{
if (!tmpNode.isInOpentable)
{
tmpNode.parentNode=node;
} [mutable addObject:tmpNode];
}
}
return mutable.copy;
} /**
* 判断两个节点是否相邻
*
* @param node0 node0 description
* @param node1 node1 description
*
* @return return value description
*/
-(BOOL)isnNodes:(NodeView*)node0 nearsNode:(NodeView*)node1
{
return [[self findNearNode:node0] containsObject:node1];
} /**
* 返回某个节点周围存在的节点,不论是否已添加或者是不可达
*
* @param node node description
*
* @return
*/
-(NSArray *)findNearNode:(NodeView *)node
{
NSMutableArray *mutable=[NSMutableArray array]; for (int i=-; i<; i++)
{
for (int j=-; j<; j++)
{ NSInteger indexX=node.indexX+i;
NSInteger indexY=node.indexY+j;
if (indexX< || indexY< || indexY>self.colCount- || indexX>self.rowCount- || (i== &&j==))
{
continue;
}
NodeView *nearNode=self.nodes[indexX][indexY];
[mutable addObject:nearNode];
}
} return mutable.copy;
} /**
* 曼哈顿估算函数
*
* @param node node description
* @param descNode descNode description
*
* @return return value description
*/
-(NSInteger)ManHWithNode:(NodeView*)node descNode:(NodeView*)descNode
{
NSInteger x= descNode.indexX- node.indexX;
NSInteger y= descNode.indexY- node.indexY; return (ABS(x*kStright)+ABS(y*kStright));
} -(NSMutableArray*)openTable
{
if (_openTable==nil)
{
_openTable=[NSMutableArray array];
}
return _openTable;
} -(NSMutableArray*)colsedTable
{
if (_colsedTable==nil)
{
_colsedTable=[NSMutableArray array];
}
return _colsedTable;
} @end
//
// Search.h
// A*算法
//
// Created by 邓竹立 on 15-5-8.
// Copyright (c) 2015年 GiveMeFive. All rights reserved.
// #import <Foundation/Foundation.h> @class NodeView;
@interface Search : NSObject @property(nonatomic,assign)NSInteger rowCount;
@property(nonatomic,assign)NSInteger colCount; @property(nonatomic,strong)NSArray *nodes;
@property(nonatomic,strong)NodeView *currentNode;
@property(nonatomic,strong)NodeView* descNode;
@property(nonatomic,strong)NSMutableArray * openTable; -(void)searchPathFrom:(NodeView*)srcNode to:(NodeView*)descNode complete:(void(^)(NodeView*)) nextPathNode; +(instancetype)sharedSearch; @end
启发式搜索 A*算法的OC 实现的更多相关文章
- 启发式搜索A*算法
A* 寻路算法 (2011-02-15 10:53:11) 转载▼ 标签: 游戏 分类: 算法 概述 虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很复杂的. 搜索区域(T ...
- 启发式搜索——A*算法
启发式搜索 启发式搜索是一种对搜索到的每一个位置进行评估,然后从评估的最优位置进行搜索直到目的地, 由于搜索时对每一个位置的评估是基于直观或经验的所有叫启发式搜索 A*算法 历史: 1964年Nils ...
- 启发式搜索A-Star算法 【寻找 最短路径 算法】【地理几何位置 可利用的情况】
在处理最短路径问题时,有一种启发式算法是我们应该了解的,由于其有着优秀的探索效率在各自现实项目中多有应用,它就是 A-star 算法,或 A* 算法. 个人观点: A* 算法并不保证找到的路径一 ...
- A*搜寻算法(A星算法)
A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...
- LeetCode学习_day1:原地算法
原地算法:是一种使用小的,固定数量的额外之空间来转换资料的算法.当算法执行时,输入的资料通常会被要输出的部份覆盖掉. 范例:冒泡排序.选择排序.插入排序.希尔排序 (1)冒泡排序: 冒泡排序算法的原理 ...
- 【算法入门】深度优先搜索(DFS)
深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...
- 深度优先搜索(DFS)
[算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一 ...
- POJ 2449 Remmarguts' Date --K短路
题意就是要求第K短的路的长度(S->T). 对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度. 但是这种方法效率太低,会扩展出很多状态,所以 ...
- dfs介绍
深度优先搜索(DFS) [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍 ...
随机推荐
- [OC Foundation框架 - 14] NSNull
在NSDictionary中,nil代表结束,允许存入 使用NSNull代替 int main(int argc, const char * argv[]) { @autoreleasepool ...
- 转载Entity Framework 4.1 DbContext使用记之三——如何玩转实体的属性值?
Entity Framework 4.1 DbContext使用记之一——如何查找实体? DbSet.Find函数的使用与实现 Entity Framework 4.1 DbContext使用记之二— ...
- USACO Feb. 2012
Moo 找规律 吧 第一个是很久以前自己写的递归 #include<stdio.h> __int64 n; __int64 dfs(__int64 l,__int64 r,__int64 ...
- cocos2d-x ScrollView、TableView
转自:http://codingnow.cn/cocos2d-x/1024.html 在游戏和应用中经常要实现左右滑动展示游戏帮助.以列表显示内容的UI效果,就像android中的Gallery和Li ...
- hdu 5495 LCS 水题
LCS Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5495 Descr ...
- hdu 5432 Pyramid Split 二分
Pyramid Split Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://bestcoder.hdu.edu.cn/contests/conte ...
- Codeforces Round #261 (Div. 2) D 树状数组应用
看着题意:[1,i]中等于a[i]的个数要大于[,jn]中等于a[j]的个数 且i<j,求有多少对这种(i,j) ,i<j可是 i前面的合法个数 要大于j后面的 看起来非常像逆序数的样子 ...
- PKU Online Judge 1054:Cube (设置根节点)
1054:Cube 总时间限制: 1000ms 内存限制: 131072kB 描述 Delayyy君很喜欢玩某个由Picks编写的方块游戏,游戏在一个由单位格组成的棋盘上进行. 游戏的主角是一 ...
- (原)nginx 源码编译
要在nginx上开发,所以先了解下这个是干嘛的..百度一下很多 编译源码需要的组件 1.zlib 2.pcre 3.openssl 使用ubuntu的话.可以直接使用 sudo apt-get ins ...
- centos6.5 安装jdk7和tomcat7
JDK安装: 安装说明 系统环境:centos-6.5安装方式:rpm安装软件:jdk-7-linux-x64.rpm下载地址:http://www.oracle.com/technetwork/ja ...