《AI for Game Developers》第七章 A*路径寻找算法 (二)(skiplow翻译)

7.3计分

    最终,我们将要根据路径的得分来判断一条路径是否是起点到终点间的最佳路径。为了给每个节点计分,我们引入了两个部分,第一我们将制定并计算从起始节点移动到其他任意节点的代价。接下来我们还要制定并计算从任意节点到终点的代价。第一部分应该是非常简单的,我们从起始位置不断的发散出去,我们只要把该点回溯到起点所要经过的步数来当做其代价就可以了。还记不记得,我们已经对各个节点保存了它的parent节点,所以回溯是非常方便的。这一步解决了,那么我怎么来计算到终点的代价呢?此时我们能做的就只要去猜测了,这个被称为heuristic(探试法)。为了做出最好的猜测,我们将给出我们所有的信息。图7-7给出给任意节点计分的公式。

Figure 7-7. Calculating the path score

 

 

 

 

    我们通过把从起始点到该点的代价加上heuristic的值来得到该点的分数。这是猜测出的经过该点的路径的代价。

我们通过计算节点的分数来判断接下来要检测open表中的那个节点。我们首先要检测的是代价最小的节点。图7-8显示了目前我们检测的所有点的分数,代价以及heuristic.

Figure 7-8. Initial tile path scores

 

 

 

(此图有点不清楚,我来说明下,起点周围的图的s=1因为回溯到起点只需一步。上3格的h=3则c=4,中间2格的h=4则c=5,下3格的h=5则c=6.箭头是指向该节点的parent节点。)

这里s值表示的是该点回溯到起始点的代价,每个节点该值都等于1,表示只需一步就能回溯到起始节点。h值表示的是heuristic。Heuristic是该点到达终点估计的步数。比如上方最右边的那个节点h=3,这是因为不考虑其他的情况比如障碍什么的它到终点只需3步。我们不考障碍等情况是因为这些点我们还没检测过只是对其的一种猜测,我们不知道它与终点之间还存在着障碍物。c是一个最终的得分,由s和h相加得到,它是一个节点的最终得分。

前面我们还有一个问题没解决,就是在A*算在中,我们在open表中先选择哪一个节点进行检测。现在我们有了答案,答案就是c最小的那个。如图7-9所示,c值最小为4,但是有3个点的c值都是4,这种情况我们应该选择哪个节点呢?这个其实无所谓,先选择哪个都是一样的,这里我们就先选择顶行最右的那个点。如果建立如图的坐标的话,该点就是(5,6)。

Figure 7-9. Examining tile (5, 6)

 

 

    当前我们关心的点是(5,6),它在其实点上方的左边。现在我们重复进行前面算法中已经展示的点的发散。在算法的第一次迭代中,与起始点连接的每个点都是有效的,但是在这次的迭代中情况就不一样了,在找相邻的点时我们不考虑在open表或closed表中的点以及那些被标记为障碍的点。由此此轮我们只找到了如图7-9所示的2个点,这2个点都被放进open表中,这两个节点包括指向parent节点的指针,还有本身对应的s,h,c的值。最后我们把当前节点也就是(5,6)放进closed表中,表示我们不必再去检测该点了。

现在我们来重复这个过程,我们把2个新节点放入了open表中,然后我们把1个节点放入了closed表中。我们再次去查找open表中最低代价的点。跟上一轮迭代一样,最小的c值仍是4,只是现在只有2个点的c值为4罢了。像刚才一样,我们可以随意的选择这个两个点中的一个,比如图7-10,我们选择了(5,5)进行下一轮的迭代。

Figure 7-10. Examining tile (5, 5)

 

 

     跟前面的做法一样,我们检测当前节点所有的相邻点,但是我们没有找到有效的节点,因为当前点的相邻点不是在open表中就是在closed表中,或者干脆就是障碍。如图7-10表示,我们把当前点放入closed表然后继续我们的工作。

现在在open表中我们只有一个c为4的节点了。它的坐标是(5,4)在起始节点的左上角,如图7-11所示,我们要检测该点。

Figure 7-11. Examining tile (5, 4)

 

     如图7-11所示,在我们检查了当前节点所有的相邻节点后,我们发现了3个有效节点,一个在当前的的左上,一个在左边,一个在左下。我们将这3个点放入open表并分别计算s,h,c,最后把当前节点放入closed表,然后继续我们的寻路过程。

现在我们发现自open表中最小的c值变成了5,而这样的点有3个分别是(5,7)(6,6)(6,4)。图7-12显示检测这些点后的结果。在A*算法中一次只能检测一个点,但是为了节省时间,我们同时检测了具有最小c值得所有点。

Figure 7-12. Examining all tiles with a cost of 5

 

 

     与前面的迭代相同,我们把找到的有效的新节点放入open表,把检测完的点放入closed表。接下来再去检查open表我们发现现在c的最小值变成了6。跟前面一样,先找那个点都一样,图7-13显示了检测完所有c为6的点后的结果。

Figure 7-13. Examining all tiles with a cost of 6

 

 

 

    如果7-13所示,我们检测了所有c值为6的点,检测出的新的有效点被放入open表,检测完的点放入closed表。我们发现到现在节点的heuristic边的越来越可靠。h值越来越接近总的c值。这样下去就能够找出一条好的路径。但现在我们仍将进行选择。现在在open表中有一个节点的c值为6,这个节点是(3,4),图7-14显示了检测完这个节点的结果。

 Figure 7-14. Examining tile (3, 4)

 

 

 

     检测完(3,4)后我们找到了3个新的有效节点,毫无意义为我们要把他们放进open表,并把(3,4)这个节点放进closed表。如图7-14所示,在open表中,大部分节点的c值为8,非常幸运的是,有两个我们新找到的节点的c值为更小的6。这是我们接下来要关注的两个节点。图7-15显示了检测完这两个节点后的结果。

Figure 7-15. Examining tiles (2, 5) and (3, 5)

 

 

 如图7-15所示,我们已经非常接近终点了。在上一轮的迭代中我们找到了5个新的有效节点,其中3个节点的c值为6,图7-16显示了检测完这3个节点后的结果。

Figure 7-16. Examining tiles (1, 6), (2, 6), and (3, 6)

 

 

     如图7-16所示,我们已经到达了终点。但是我们是怎么判断是否到达终点的呢?这个问题其实非常简单,只要终点被放进了open表我们就认为我们已经到达了终点。现在我们只要从终点开始一直回溯到起点就可以得到我们的路径了(回溯就是找到其parent节点)。图7-17显示了构建这条路径的所有节点。

Figure 7-17. The completed path

 

 

     构建这条路径的节点坐标分别为(2,7)(2,6)(2,5)(3,4)(4,3)(5,4)和(6,5)。这是一条最短的路径。肯定存在其他的很多条路径,但只有这条是最短的。

原文地址:https://www.cnblogs.com/skiplow/p/2014133.html