前两天重新学习了下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 实现的更多相关文章

  1. 启发式搜索A*算法

    A* 寻路算法 (2011-02-15 10:53:11) 转载▼ 标签: 游戏 分类: 算法 概述 虽然掌握了 A* 算法的人认为它容易,但是对于初学者来说, A* 算法还是很复杂的. 搜索区域(T ...

  2. 启发式搜索——A*算法

    启发式搜索 启发式搜索是一种对搜索到的每一个位置进行评估,然后从评估的最优位置进行搜索直到目的地, 由于搜索时对每一个位置的评估是基于直观或经验的所有叫启发式搜索 A*算法 历史: 1964年Nils ...

  3. 启发式搜索A-Star算法 【寻找 最短路径 算法】【地理几何位置 可利用的情况】

    在处理最短路径问题时,有一种启发式算法是我们应该了解的,由于其有着优秀的探索效率在各自现实项目中多有应用,它就是 A-star 算法,或  A*  算法. 个人观点: A*  算法并不保证找到的路径一 ...

  4. A*搜寻算法(A星算法)

    A*搜寻算法[编辑] 维基百科,自由的百科全书 本条目需要补充更多来源.(2015年6月30日) 请协助添加多方面可靠来源以改善这篇条目,无法查证的内容可能会被提出异议而移除. A*搜索算法,俗称A星 ...

  5. LeetCode学习_day1:原地算法

    原地算法:是一种使用小的,固定数量的额外之空间来转换资料的算法.当算法执行时,输入的资料通常会被要输出的部份覆盖掉. 范例:冒泡排序.选择排序.插入排序.希尔排序 (1)冒泡排序: 冒泡排序算法的原理 ...

  6. 【算法入门】深度优先搜索(DFS)

    深度优先搜索(DFS) [算法入门] 1.前言深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解 ...

  7. 深度优先搜索(DFS)

    [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一 ...

  8. POJ 2449 Remmarguts' Date --K短路

    题意就是要求第K短的路的长度(S->T). 对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度. 但是这种方法效率太低,会扩展出很多状态,所以 ...

  9. dfs介绍

    深度优先搜索(DFS) [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/05/12 1.前言 深度优先搜索(缩写DFS)有点类似广度优先搜索,也是对一个连通图进行遍 ...

随机推荐

  1. 转载总结一些关于Google chart api的知识

    <script type="text/javascript">      google.setOnLoadCallback(drawChartLine);      f ...

  2. Ios学习

    http://www.cnblogs.com/superhappy/archive/2013/04/23/3038493.html http://www.360doc.com/content/14/0 ...

  3. mysql之索引

    一.索引是什么? 比如我们要在字典中找某一字,如何才能快速找到呢?那就是通过字典的目录. 对数据库来说,索引的作用就是给‘数据’加目录. 二.索引算法 设有N条随机记录,不用索引,平均查找N/2次,那 ...

  4. eclipse创建maven模块工程

    创建maven模块项目,可以使用eclipse工具来完成. 1.创建父工程,注意,要选择maven-archetype-site-simple new --> maven project 填写项 ...

  5. iOS开发-相关文档

    关于调试,查看Xcode Overview文档相关部分:http://developer.apple.com/library/ios/documentation/ToolsLanguages/Conc ...

  6. Android内存中的图片

    图片在内存中的大小 Android.graphics.Bitmap类里有一个内部类Bitmap.Config类,在Bitmap类里createBitmap(intwidth, int height, ...

  7. Android虚拟环境的工具集Genymotion完整安装教程

    Genymotion提供Android虚拟环境的工具集.相信很多Android开发者一定受够了速度慢.体验差效率及其地下的官方模拟器了.如果你没有物理机器,又不想忍受官方模拟器的折磨,Genymoti ...

  8. xcode6.4 7.2下载地址

    XCode 7.2 :ht tp://adcdownload.apple.com/Developer_Tools/Xcode_7.2/Xcode_7.2.dmgXCode7.1.1:ht tp://a ...

  9. Scribefire发CSDN博客

    历史 在非常久非常久曾经,CSDN是支持外部工具来写文章的,但是在还有一个非常久非常久曾经就不行了. 突然看到CSDN有能够用外部工具来写博客了(CSDN的公告),一直以来都纠结这个问题,CSDN的编 ...

  10. C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部【转载】

    这是最近在做的一个项目中提到的需求,把一个现有的窗体应用程序界面嵌入到自己开发的窗体中来,看起来就像自己开发的一样(实际上……跟自己开发的还是有一点点区别的,就是内嵌程序和宿主程序的窗口激活状态问题) ...