在网上看了几篇关于A*的文章,都没怎么看懂,其中包括翻译国外作者写的这篇。于是打算直接看原文了,看了后发现有的并没有很仔细地翻译。为了能便于自己理解,打算再翻译一遍,有些地方就简单翻译了。
---------------------------------------------------------------------------------------------------------------------
先给出一个原文连接http://www.policyalmanac.org/games/aStarTutorial.htm。接下来翻译。
A*(读作A-start)算法对初学者来说比较复杂。但是网上也有很多介绍该算法的,然而大多数都是写给那些有基础的人看的。这篇文章是写给真正的初学者的(就是我了)。
这篇文章并不是该主题的权威探讨。相反,它描述了一些基本原理使得你具备阅读其他材料并能理解其他材料的能力。文章末尾提供了一些比较好的链接,以供进一步阅读。
最后,这篇文章并不是讲编程的,你应该能够根据这篇文章所讲的用其他任何编程语言来实现。然而,正如你期望的一样,我在文章末尾也提供了一个示例程序。该程序包括两个版本:C++和Blitz Basic。如果你只想看看它是怎么运行的,也有可执行的程序。
有点言之过早了,让我们开始吧。。。
Introduction: The Search Area
假设有个人想从A点到达B点,并假设A和B之间有道墙。如下图所示,绿色的是起始点A,红色的是终点B,蓝色区域就是墙。
图一
你需要知道的第一件事是我们已经把搜索区域划分成了单元格。简化搜索区域是路径查找的第一步。这个特殊的方法把搜索区域简化成了一个简单的二维数组。数组中的每个条目代表了表格中的一个单元,单元的状态被标为walkable或者unwalkable。我们要找的路径就是表格中从A到B所经过的单元格的集合。一旦找到了路径,我们就可以从一个单元的中心点到达下一个单元的中心点,直到到达目的单元。
这些中心点被称为“nodes”,为什么不叫squares呢?因为我们可以把区域分成其他形状,可以是长方形、三角形、六边形或其他形状。nodes可以放在这些形状中的任意一个位置--在中心或者在边缘或者其他地方。简单起见,这里我们使用square来描述。
Starting the Search
一旦我们简化了搜索区域为一些易处理的nodes,如前面一幅图所示,下一步就是寻找最短路径了。我们从起始点A开始,检查相邻squares,往外查找直到找到目标。
我们以如下步骤开始查找:
1、从A开始并将它添加到“open list”。这个就像一个shopping list。目前为止只有一个条目在列表中,以后还会有很多。总的来说,这个列表需要被进一步的检查。
2、查看与起始点相邻的所有reachable或者walkable的squares,把他们加入到open list,忽略墙、水或者其他illegal terrain。对于刚加入的每个square,把A点保存为他们的“parent square”。这个对回溯路径的时候很有用。
3、从open list中删除starting square A,并加入到“closed list”中,里面的squares暂时不会被查找。
目前为止,你脑子中应该有如下图的描绘了。深绿色的square是starting square。外层一圈描蓝表示该单元已经被加入到closed list中了。该单元周围8个squares(被绿色边框描着的)也被加入到了open list中待以后查找,其中每一个都有一个指向parent square的指针,这个parent square就是starting square。
图2
接下来,我们从open list中选择一个相邻square,差不多重复之前的过程。但是选哪个呢?当然是F值最小的啦。
Path Scoring
选哪些square的关键在于以下公式:
F=G+H
G:从starting point A开始移动到一个指定square的代价。
H:从一个给定square移动到最终目的square B的估计代价。这就是所谓的启发式。之所以这么称呼是因为那个值只是个猜想。在找到路径之前我们还不知道实际的距离,因为路上会有各种障碍(比如墙,水之类的)。这篇文章给了一个计算该值的方法,但是网上也有很多用其他方法计算该值的文章。
通过遍历open list并选择最小F值的square来生成路径。这之前需要计算G和H值,计算一个square的G值的方法是根据它是处于parent square的水平、垂直或者对角线位置来相应加上10或者14,并且还要加上parent square的G值。我们的例子中使用10来表示水平和垂直移动一格的代价,用14来表示对角线移动一个的代价。因为对角线是边的根号2倍,所以我们取这样的值,同时也便于计算。
H可以用多种方法来估计,我们这里用曼哈顿方法(Manhattan method)来计算。用该方法计算的时候是沿着水平和垂直距离的,并且忽略沿途的障碍物。计算结果为走过的步数乘以10。
从技术上来说,曼哈顿方法是一个inadmissible heuristic,因为它有点高估了剩余距离,但这便于理解。关于这个问题可以看这里。
搜索的第一步的结果如下图所示。F、G、H的值也标上了。
图三
我们来看,绿色square的水平、垂直方向上的squares的G都是10,对角线上的都为14。H值则是当前square到红色square的水平加垂直距离。