启发式搜索 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)有点类似广度优先搜索,也是对一个连通图进行遍 ...
随机推荐
- hibernate分页实现
1.创建分页实体类 public class PageBean { private int page; // 页码 private int rows; // 每页显示行数 private int st ...
- http 需要掌握的知识点(一)
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.HTTP 也属于 TCP/IP 协议族的子集,想要学习 HTTP ,先需要了解 ...
- Python FTP多线程爆破脚本
初学python, 自己编写了个FTP多线爆破小脚本代码很丑= = #!usr/bin/env python #!coding=utf-8 __author__='zhengjim' from ftp ...
- spring aop 的一个demo(未完,待完善)
假设我们有这样的一个场景 : 对于一个类的众多方法,有些方法需要从缓存读取数据,有些则需要直接从数据库读取数据.怎样实现呢? 实现方案有多种.下面我说下常见的几种实现方案 : 1.直接采用spring ...
- NUMBER_GET_NEXT
1. SNRO /SNUM创建一个流水号对象 CALL FUNCTION 'NUMBER_RANGE_ENQUEUE' EXPORTING OBJECT = '' EXCEPTIONS FOREIGN ...
- DP练习(初级):ZigZag
题目来源:http://community.topcoder.com/stat?c=problem_statement&pm=1259&rd=4493 类似于求最长子串的方法.dp[0 ...
- ios开发——实用技术OC-Swift篇&本地通知与远程通知详解
本地通知与远程通知详解 一:本地通知 Local Notification的作用 Local Notification(本地通知) :是根据本机状态做出的通知行为,因此,凡是仅需依赖本机状态即可判 ...
- php一些技术要点连接地址
http基本认证: http://www.php.net/manual/zh/features.http-auth.php
- extremeComponents(ec)源码分析
eXtremeComponents(简称ec)是一系列提供高级显示的开源JSP定制标签,当前的包含的组件为eXtremeTable,用于以表形式显示数据. 其本质是jsp的自定义标签,抓住这一点就抓住 ...
- C# 之 获取文件名及拓展名
1.用Path类的方法(最常用) string fullPath = @"\WebSite\Default.aspx"; string filename = System.IO.P ...