1
头图

在贪吃蛇游戏比赛里,计算蛇吃食物路径时要用到寻路算法,以下是我的算法演化过程。

1、简单寻路--按图索骥

我一开始想到的方法就是最简单的:目标在哪个方位就往哪个方位走,就和平时看地图寻路一样。这时候算法的基本思想为:
image

即以起点终点连线方向为正方向,与正方向越接近的方法给予更小的权值,当搜索路径时总以总权值和最小为目的进行搜索,直到搜索到终点。

但在地图上有障碍物时会发生:
image
所以要对地图上的点做一些处理,即把障碍物从可以搜索的地图点集合中去除。

以下是此算法的搜索结果,蓝色点为搜索过的地图点,黑色为障碍物:
image
可以看见在简单情况下此算法可以很好的工作并找到一条最短路径,耗费的资源也不多。

但在复杂情况下可能会发生:
image
为了解决这种复杂情况下可能出现的找不到最短路径的问题,我又想了一种解决办法。

2、简单寻路--投石问路

这种算法的基本思想和蝙蝠的超声波导航类似:
image
即一圈一圈向外查找,直到找到终点。

这种方法能很好地解决复杂情况下找到最短路径的问题:
image
但也正如图中显示的,蓝色的格点(查找点)太多,对于资源的消耗太大,尤其在地图很大很复杂或对实时性要求较高的情况下用此算法基本不可能。

于是为了弥补以上两者的缺点并取其优点就产生了A*寻路算法。

3、A*寻路--融汇贯通

以上两种算法中,第一种算法以终点为导向,追求起点到终点的最近,但可能舍近求远;第二种算法以起点为导向,最求终点到起点的位置最近,但因为无法确定终点位置导致了资源消耗过大。于是A*算法同时考虑起点和终点,它的基本思想如下:
image
其中蓝色为起点,黄色为中继点,黑色为障碍,X为终点。

即选取要检查的地图点,以此地图点为中继点,分别计算距离起点和终点的位置,并把二者加和作为这一点的权值,寻路的路径就是总权值和最小的点的集合。

由于贪吃蛇游戏中只有水平和垂直两个方向,于是上图也可以演变成下图:
image
可以的出距离F = G’+H’。

下面分步骤说明A*寻路的具体流程:

1、将当前节点(蓝色节点)的周围节点加入待检测集合openList(黄色节点)中,并计算F值;将障碍节点加入abandonList。
image
2、选取一个在openList中F值最小的节点,放入检测完毕集合closeList(绿色节点)中。若此节点为终点,算法结束。
image
3、计算当前节点(绿色节点)周围节点,并进行处理:

1 如果节点在closeList中则丢弃节点(加入abandonList)。

2 如果节点在openList中则重新计算这一点的F值。

3 如果节点不在openList中,重复步骤2。

n、重复步骤2、3

下图是复杂情况下A*寻路的结果:
image
既找到了最短路径,也没有搜索很多格子,是一种比较优秀的算法。

当然其实A star寻路在众多寻路算法中也算比较基础的寻路算法。如今比较常用的算法有D star算法(主要用于动态未知环境下的寻路,用于机器人寻路)和JPS(Jump Point Search)算法(用于格子地图的寻路,速度快且资源消耗少)等A*算法的优化算法以及Dijkstra算法(上述简单寻路的优化,主要用于静态地图下的寻路,最优可达线性时间复杂度)。

还有更进一步的寻路就是通过神经网络训练AI,但这种方法的缺点就在于算法不受控,开发人员不知道寻路的实现规则。一般而言很少会用这种方式做寻路。

在寻路算法背后也有地图的优化算法,常用的是划分navigation mesh(导航网格),其中的mesh为一个个凸多边形,划分完成后能大大减少地图点的数目。当然这就是另外一个故事了。


控维通信
11 声望1 粉丝

专业从事卫星通信产品研发、生产制造及服务的高科技企业。