A*, A Star A星算法详解( 四 )


那我们就选择起始格右下方的格子 , 如图 。
[图5]
这次 , 当我们检查相邻格的时候 , 发现右侧是墙 , 于是略过 。上面一格也被略过 。我们也略过了墙下面的格子 。为什么呢?因为你不能在不穿越墙角的情况下直接到达那个格子 。你的确需要先往下走然后到达那一格 , 按部就班的走过那个拐角 。(注解:穿越拐角的规则是可选的 。它取决于你的节点是如何放置的 。)
这样一来 , 就剩下了其他5格 。当前格下面的另外两个格子目前不在开启列表中 , 于是我们添加他们 , 并且把当前格指定为他们的父节点 。其余3格 , 两个已经在关闭列表中(起始格 , 和当前格上方的格子 , 在表格中蓝色高亮显示),于是我们略过它们 。最后一格 , 在当前格的左侧 , 将被检查通过这条路径 , G值是否更低 。不必担心 , 我们已经准备好检查开启列表中的下一格了 。
我们重复这个过程 , 直到目标格被添加进关闭列表(注解) , 就如在下面的图中所看到的 。
[图6]
注意 , 起始格下方格子的父节点已经和前面不同的 。之前它的G值是28 , 并且指向右上方的格子 。现在它的G值是20 , 指向它上方的格子 。这在寻路过程中的某处发生 , 当应用新路径时 , G值经过检查变得低了-于是父节点被重新指定 , G和F值被重新计算 。尽管这一变化在这个例子中并不重要 , 在很多场合 , 这种变化会导致寻路结果的巨大变化 。
那么 , 我们怎么确定这条路径呢?很简单 , 从红色的目标格开始 , 按箭头的方向朝父节点移动 。这最终会引导你回到起始格 , 这就是你的路径!看起来应该像图中那样 。从起始格A移动到目标格B只是简单的从每个格子(节点)的中点沿路径移动到下一个 , 直到你到达目标点 。就这么简单 。
[图7]
A*方法总结
好 , 现在你已经看完了整个说明 , 让我们把每一步的操作写在一起:
1 , 把起始格添加到开启列表 。
2 , 重复如下的工作:
a) 寻找开启列表中F值最低的格子 。我们称它为当前格 。
b) 把它切换到关闭列表 。
c) 对相邻的8格中的每一个?
* 如果它不可通过或者已经在关闭列表中 , 略过它 。反之如下 。
* 如果它不在开启列表中 , 把它添加进去 。把当前格作为这一格的父节点 。记录这一格的F,G,和H值 。
* 如果它已经在开启列表中 , 用G值为参考检查新的路径是否更好 。更低的G值意味着更好的路径 。如果是这样 , 就把这一格的父节点改成当前格 , 并且重新计算这一格的G和F值 。如果你保持你的开启列表按F值排序 , 改变之后你可能需要重新对开启列表排序 。
d) 停止 , 当你
* 把目标格添加进了关闭列表(注解) , 这时候路径被找到 , 或者
* 没有找到目标格 , 开启列表已经空了 。这时候 , 路径不存在 。
3.保存路径 。从目标格开始 , 沿着每一格的父节点移动直到回到起始格 。这就是你的路径 。
(:在这篇文章的较早版本中 , 建议的做法是当目标格(或节点)被加入到开启列表 , 而不是关闭列表的时候停止寻路 。这么做会更迅速 , 而且几乎总是能找到最短的路径 , 但不是绝对的 。当从倒数第二个节点到最后一个(目标节点)之间的移动耗费悬殊很大时-例如刚好有一条河穿越两个节点中间 , 这时候旧的做法和新的做法就会有显著不同 。)