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个按钮:

“设置阻挡”:按下这个按钮后可以通过鼠标左键自定义阻挡区域,方便测试。

“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*算法会遍历整个地图。这明显是低效率的。

时间: 2024-12-22 10:43:51

A*寻路算法(曼哈顿距离)的相关文章

Atitti knn实现的具体四个距离算法 欧氏距离、余弦距离、汉明距离、曼哈顿距离

Atitti knn实现的具体四个距离算法  欧氏距离.余弦距离.汉明距离.曼哈顿距离 1. Knn算法实质就是相似度的关系1 1.1. 文本相似度计算在信息检索.数据挖掘.机器翻译.文档复制检测等领域有着广泛的应用1 2. 汉明距离1 2.1. 历史及应用1 3. 曼哈顿距离2 3.1. SimHash + 汉明距离3 3.2. .简单共有词4 1. Knn算法实质就是相似度的关系 1.1. 文本相似度计算在信息检索.数据挖掘.机器翻译.文档复制检测等领域有着广泛的应用 数据挖掘的过程中,只用

曼哈顿距离算法

首先介绍一下曼哈顿,曼哈顿是一个极为繁华的街区,高楼林立,街道纵横,从A地点到达B地点没有直线路径,必须绕道,而且至少要经C地点,走AC和 CB才能到达,由于街道很规则,ACB就像一个直角3角形,AB是斜边,AC和CB是直角边,根据毕达格拉斯(勾股)定理,或者向量理论,都可以知道用AC和CB 可以表达AB的长度. 在早期的计算机图形学中,屏幕是由像素构成,是整数,点的坐标也一般是整数,原因是浮点运算很昂贵,很慢而且有误差,如果直接使用AB的距离,则必须要进 行浮点运算,如果使用AC和CB,则只要

A星寻路算法以及C++实现

A星寻路算法真是我一生接触的第一个人工智能算法了... A星寻路算法显然是用来寻路的,应用也很普遍,比如梦幻西游...算法的思路很简单,就是在bfs的基础上加了估值函数. 它的核心是 F(x) = G(x) + H(x) 和open.close列表: G(x)表示从起点到X点的消耗(或者叫移动量什么的),H(X)表示X点到终点的消耗的估值,F(x)就是两者的和值.open列表记录了可能要走的区域,close列表记录了不会再考虑的区域.我们每次都选F值最小的区域搜索,就能搜到一条到终点的最短路径,

用简单直白的方式讲解A星寻路算法原理

很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中最常用的寻路算法. 直入正题: 在游戏设计中,地图可以划分为若干大小相同的方块区域(方格),这些方格就是寻路的基本单元. 在确定了寻路的开始点,结束点的情况下,假定每个方块都有一个F值,该值代表了在当前路线下选择走该方块的代价.而A星寻路的思路很简单:从开始点,每走一步都选择代价最小的格子走,直到达

A星寻路算法-(入门级)

你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法的文章,但是大部分都是提供给已经了解基本原理的高级开发者的. 本篇教程将从最基本的原理讲起.我们会一步步讲解A星寻路算法,幷配有很多图解和例子. 不管你使用的是什么编程语言或者操作平台,你会发现本篇教程很有帮助,因为它在非编程语言的层面上解释了算法的原理. 现在找下到达一杯咖啡因饮料和美味的零食的最

A*寻路算法的探寻与改良(三)

A*寻路算法的探寻与改良(三) by:田宇轩                                        第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细化后的A*算法和变种A*算法内容的朋友们可以跳过这部分并阅读稍后更新的其他内容 3.1 回顾 在我的上一篇文章中,我们探讨了如何用编程实现A*算法,并给出了C语言的算法实现,这一章内容中我们主要研究如何提高A*算法的执行效率.抛开时间复杂度的复杂计算,我们大概可以知道,函数对数据的操作次数越少,达成

A*寻路算法的探寻与改良(二)

A*寻路算法的探寻与改良(二) by:田宇轩                                                     第二部分:这部分内容主要是使用C语言编程实现A*,想了解A*算法的优化内容的朋友们可以跳过这部分并阅读稍后更新的其他内容 2.1 回顾 在我的上一篇文章中,我们通过抽象的思维方式得出了A*算法的概念和原理,这一章内容中主要探讨如何用编程实现A*算法. 在数据结构与算法的学习中,每个算法都应该结合一定的数据结构在计算机中存储,然后用对应的函数操控这些

C#实现简单的AStar寻路算法

1.算法实施模型 在我看来,最简单最基础的寻路环境是:在一片二维网格区域中存在一些围墙(Block),在起始点和终点之间保持连通的前提下寻找一条最佳路径. 2.算法原理 详细介绍有很多,可参考网址:http://www.policyalmanac.org/games/aStarTutorial.htm,浅显易懂,重点是理解"启发式搜索"的概念.下面谈谈我自己的理解,如果是第一次接触A*寻路算法,还是先老老实实看完给出的参考网址吧(当然也可以参考相关的中文介绍资料). 在一片二维网格中,

菜鸟福利 A星寻路算法 cocos2d-x实现

这篇blog是翻译自iOS Tutorial Team的成员 Johann Fradj,他目前是一位全职的资深iOS开发工程师.他是HotApps Factory的创始人,该公司开发了AppCooker 你是否在做一款游戏的时候想实现一种寻路算法,让一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用著名的A星寻路算法来实现它! 公式表示为: f(n)=g(n)+h(n), 其中 f(n)是从初始点经由节点n到目标点的估价函数, g(n

A星寻路算法-Mind&amp;Hand(C++)

//注1:Mind & Hand,MIT校训,这里指的理解与实现(动脑也动手) //注2:博文分为两部分:(1)理解部分,为参考其他优秀博文的摘要梳理:(2)代码部分,是C++代码实现的,源码来源GitHub开源代码. 一.理解部分 我一名2018级的Postgraduate新生,路径规划算法的初学者,这里的理解主要参照资深IT博主"莫水千流"的博客原文(链接附在本部分内容的结尾处),做一些梳理和笔记摘要,加深对于A星寻路算法的理解.学习从模仿开始. (1)建立模型,简化问题