A*寻路算法(曼哈顿距离)
前一些天,在群有人问到A*算法的问题。
之前我已经有实现过,并将之放到github上(https://github.com/XJM2013/A_Star)。有兴趣的能够下载下来看看。
这里上传了一个相当好的A*算法演示程序,大家能够下载下来看看效果:http://download.csdn.net/detail/a374826954/8781185。
以下描写叙述是摘自清华大学出版社《人工智能》一书:
评价函数的形式例如以下:
f(n) = g(n) + h(n)
当中,n是被评价的结点。
g*(n):表示从初始结点s到结点n的最短的耗散值。
h*(n):表示从结点n到目标结点g的最短的耗散值;
f*(n)=g*(n)+h*(n):表示从结点s经过结点n到目标结点g的最短路径的耗散值。
而f(n)、g(n)和h(n)则分别表示是对f*(n)、g*(n)和h*(n)3个函数值的预计值,的一种预測。
A算法就是利用这样的预測,来达到搜索的目的。
当在算法A的评价函数中,使用的启示函数h(n)是处于h*(n)的下界范围。即满足h(n)≤h*(n)时,则把这个算法称为算法A*。
须要说明的是。程序因为添加了一些调试信息。略微会比实际慢一些。
以下看一下程序演示界面:
白格子表示通路。黑格子表示阻挡。
这里的黑格子是随机生成。在下面代码产生:
(function(){
map.init(0.3);
map.createUI();
})();
随机数为0.3。当设置为0时,则所有都是通路。
说说3个button:
“设置阻挡”:按下这个button后能够通过鼠标左键自己定义阻挡区域。方便測试。
“closed”:显示已经被扩展并放到closed表的节点信息。
显示信息以C:开头。显示4个数据各自是f,g,h和扩展索引。须要注意的是扩展索引不一定是连续的,由于同一个节点可能被多次扩展。
“open”:显示剩余剩余的open表节点信息。
显示信息以O:开头。显示3个数据各自是f,g和h。
事实上一些人搞不懂A*算法。主要是搞不懂f,g。h是如何取值的。
以下举个样例:
从广州到北京(最好打开百度地图对照着看,下面距离不等于实际城市间的距离)
换言之,广州就是起始点,北京就是目标点。
广州到广州的距离是0。也就是g=0;广州到北京的直线距离是5000。也就是h=5000。f=g+h,f=5000。
将广州放进open表,扩展广州这个节点。并将广州从open表删除,放进closed表。得到重庆和上海。
广州到重庆的距离是2500,也就是重庆这个节点的g=2500。重庆到北京的直线距离是4500。也就是h=4500。f=7000。
将重庆放进open表。
广州到上海的距离是3000。也就是上海这个节点的g=3000;上海到北京的直线距离是3000,也就是h=3000;f=6000。
将上海放进open表;因为上海的f小于重庆的f,在open表中上海节点在重庆节点前面。
扩展上海这个节点,发现找到了北京。于是搜索结束。最后的路径就是广州-上海-北京。
本程序的核心代码是:
search : function(){
while(1){
if (map.openTable.length == 0){
break;
}
var _fMinNode = map.openTable.shift();
if (_fMinNode.place == 2){
continue;
} map.searchAround(_fMinNode);
_fMinNode.index = globalIndex;
globalIndex++;
_fMinNode.place = 2;
closedTable.push(_fMinNode);
if (map.endNode == _fMinNode){
break;
}
}
}, searchAround : function(node){
var nodeX;
var nodeY; for (var x = -1; x <= 1; x++)
{
nodeX = node.x + x;
for (var y = -1, mapNode, _obj, tmpNode; y <= 1; y++)
{
nodeY = node.y + y;
//剔除本身
if (x === 0 && y === 0) continue;
if (nodeX >= 0 && nodeY >= 0 && nodeX < map.gridWidth && nodeY < map.gridHeight)
{
mapNode = map.data[nodeX][nodeY];
if (mapNode.isRoadBlock){
continue;
}
_obj = map.getFGH(node, mapNode);
do
{
if (mapNode.place == 2){
if (_obj.G >= mapNode.obj.G){
break;
}
}
else if (mapNode.place == 1){
// 单调限制
if (mapNode.obj.G <= _obj.G){
continue;
}
} mapNode.obj = _obj;
mapNode.front = node;
mapNode.place = 1;
map.insertOpenTable(mapNode);
}while(0)
};
};
};
},
工作流程就是循环顺序遍历open表(依据f值进行排序),扩展读取出来的节点,直到找到目标点。
当中getFGH就是计算该节点的f,g,h信息。
你能够看到代码里面有写着// 单调限制的凝视。再举同一个样例说明一下。
广州还扩展出一个节点:武汉。
武汉的f=5900。g=2400,h=3500。这时候是先扩展武汉,于是又找到了上海。
武汉到上海的距离是1900。
这时候经过武汉到上海的节点信息是g=2400+1900=4300。h是不变的也是3000。
上海节点mapNode之前保存的g=3000。如今算出经过武汉到上海的距离是g=4300。
因此经过武汉到上海比直接到上海的距离远,因此不将f,g,h替换放到open表。
这就是单调限制。
以下是本篇文章代码及演示程序的效果图:
A*算法的不足:
当目标点是位于死路区域,则A*算法会遍历整个地图。
这明显是低效率的。
A*寻路算法(曼哈顿距离)的更多相关文章
- Atitti knn实现的具体四个距离算法 欧氏距离、余弦距离、汉明距离、曼哈顿距离
Atitti knn实现的具体四个距离算法 欧氏距离.余弦距离.汉明距离.曼哈顿距离 1. Knn算法实质就是相似度的关系1 1.1. 文本相似度计算在信息检索.数据挖掘.机器翻译.文档复制检测等领 ...
- A星寻路算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- A*寻路算法探究
A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...
- 用简单直白的方式讲解A星寻路算法原理
很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...
- A星寻路算法
A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...
- 【转】A*寻路算法 C++实现
头文件:AStarPathFinding #ifndef ASTARPATHFINDING_H #define ASTARPATHFINDING_H #include <queue>//为 ...
- A*寻路算法的探寻与改良(三)
A*寻路算法的探寻与改良(三) by:田宇轩 第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细 ...
- A*寻路算法的探寻与改良(二)
A*寻路算法的探寻与改良(二) by:田宇轩 第二部分:这部分内容主要是使用C语言编程实现A*, ...
- A星寻路算法(A* Search Algorithm)
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- JS算法之A*(A星)寻路算法
今天写一个连连看的游戏的时候,接触到了一些寻路算法,我就大概讲讲其中的A*算法. 这个是我学习后的一点个人理解,有错误欢迎各位看官指正. 寻路模式主要有三种:广度游戏搜索.深度优先搜索和启发式搜索. ...
随机推荐
- 推荐算法——非负矩阵分解(NMF)
一.矩阵分解回想 在博文推荐算法--基于矩阵分解的推荐算法中,提到了将用户-商品矩阵进行分解.从而实现对未打分项进行打分. 矩阵分解是指将一个矩阵分解成两个或者多个矩阵的乘积.对于上述的用户-商品矩阵 ...
- NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9802)
本篇文章由:http://xinpure.com/nsurlsessionnsurlconnection-http-load-failed-kcfstreamerrordomainssl-9802/ ...
- Solr 4.0部署
http://www.blogjava.net/xiaohuzi2008/archive/2012/12/03/392373.html
- python --文本文件的输入输出
转自:http://www.cnblogs.com/vamei/archive/2012/06/06/2537868.html Python具有基本的文本文件读写功能.Python的标准库提供有更丰富 ...
- C++:SQLServer字段赋值
大前提: 1. 初始化环境 2. 创建连接实例 3. 创建记录集实例 注意点: 1.AddNews失败问题: (1)是否将CursorTypeEnum cursorType, LockTypeEnum ...
- Windows路由表配置:双网卡同时上内外网
管理员模式CMD 路由表解释 route print -4 删除默认设置 route delete 0.0.0.0 外网路由,全走无线,192.168.0.1为无线网关 route add 0.0.0 ...
- 逆向project第005篇:跨越CM4验证机制的鸿沟(下)
一.前言 本文是逆向分析CM4系列的最后一篇,我会将该游戏的序列号验证机制分析完成,进而编写出注冊码生成器. 二.分析第二个验证循环 延续上一篇文章的内容,来到例如以下代码处: 图1 上述代码并没有特 ...
- Atitit.基于时间戳的农历日历历法日期计算
Atitit.基于时间戳的农历日历历法日期计算 1. 农历xx年的大小月份根据万年历查询1 2. 农历xx年1月1日的时间戳获取1 3. 计算当年的时间戳与农历日期的对应表,时间戳为key,日期为va ...
- 改善用户体验,用图片的自身变化以及进度通知摆脱传统的进度条,okhttp,Canvas,Paint实现
转载请注明出处:王亟亟的大牛之路 从最開始的白页面等待,到后来的进度条告知用户.到如今的WebBO/微信这样的先下缩略图点击才又一次下大图的方式,我们开发人员对用户感知的注意度越来越高.昨天刷微博的时 ...
- C++重载IO操作符
操作符的重载有一定的规则,而IO操作符必须重载为普通函数,且应该声明为类的友元函数.我试了,非友元也可以,但是必须提供访问成员变量的函数,所以,出于效率的考虑还是应该定义为友元. 规则如下: 1. ...