前两天重新学习了下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. (贪心5.2.6)URAL 1014 Product of Digits(利用数据有序化进行贪心选择)

    /* * URAL_1014.cpp * * Created on: 2013年10月11日 * Author: Administrator */ #include <iostream> ...

  2. Jsp中的pageContext对象

    这个对象代表页面上下文.组要用于访问页面共享数据.使用pageContext可以直接访问request,session,application范围的属性,看看这些jsp的页面: JSP 页面使用 pa ...

  3. 【推荐】对 Linux 用户非常有用的 60 个命令(由浅入深)

    对 Linux 新手非常有用的 20 个命令 http://www.oschina.net/translate/useful-linux-commands-for-newbies 对 Linux 中级 ...

  4. UITextView光标在中间的问题

    if ([self respondsToSelector:@selector(setAutomaticallyAdjustsScrollViewInsets:)]) { self.automatica ...

  5. hdu 5442 Favorite Donut 后缀数组

    Favorite Donut Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid ...

  6. httpclient模拟浏览器訪问站点

    HttpClient 是 Apache Jakarta Common 下的子项目.能够用来提供高效的.最新的.功能丰富的支持 HTTP 协议的client编程工具包.而且它支持 HTTP 协议最新的版 ...

  7. java String 两种不同的赋值 比较

    原文:http://blog.163.com/woshihezhonghua@126/blog/static/1271436362012101214031911/ 首先明确一点,String是一个类. ...

  8. CentOS安装Nginx安装详解

    一.准备工作,安装依赖包,缺一不可!(推荐先用命令查看自己是否已经安装一下软件,确认没有再安装) --------------------------------------------------- ...

  9. Java读取文本文件中文乱码问题 .转载

    最近遇到一个问题,Java读取文本文件(例如csv文件.txt文件等),遇到中文就变成乱码.读取代码如下: List<String> lines=new ArrayList<Stri ...

  10. iOS 开发中你是否遇到这些经验问题(二)

    前言: 1.在Block中一起使用weakSelf与strongSelf的含义 我们都会声明一个弱引用在block中使用, 目的就是防止循环引用, 那么weakSelf与strongSelf一起使用目 ...