Artificial intelligence 我如何找到最“;自然地;使用A星(A*)的直达路线

Artificial intelligence 我如何找到最“;自然地;使用A星(A*)的直达路线,artificial-intelligence,path-finding,a-star,Artificial Intelligence,Path Finding,A Star,我已经在AS3中实现了A*算法,除了一件事之外,它工作得非常好。 通常,生成的路径不会采用最“自然”或最平滑的路径到达目标。 在我的环境中,对象可以像水平或垂直移动一样便宜地沿对角线移动。 这里有一个非常简单的例子;起点用S标记,终点(或终点)用F标记 | | | | | | | | | | |S| | | | | | | | | x| | | | | | | | | | x| | | | | | | | | | x| | | | | | | | | | x| | | | | | | | |

我已经在AS3中实现了A*算法,除了一件事之外,它工作得非常好。 通常,生成的路径不会采用最“自然”或最平滑的路径到达目标。 在我的环境中,对象可以像水平或垂直移动一样便宜地沿对角线移动。 这里有一个非常简单的例子;起点用S标记,终点(或终点)用F标记

 | | | | | | | | | |
 |S| | | | | | | | |
x| | | | | | | | | |
x| | | | | | | | | |
x| | | | | | | | | |
x| | | | | | | | | |
x| | | | | | | | | |
 |F| | | | | | | | |
 | | | | | | | | | |
 | | | | | | | | | |
如您所见,在第一轮查找过程中,节点[0,2]、[1,2]、[2,2]都将添加到可能节点列表中,因为它们的得分都为N。 我遇到的问题出现在下一个点,当我试图决定继续使用哪个节点时。在上面的示例中,我使用可能节点[0]来选择下一个节点。如果我将其更改为possibleNodes[possibleNodes.length-1],我将得到以下路径

 | | | | | | | | | |
 |S| | | | | | | | |
 | |x| | | | | | | |
 | | |x| | | | | | |
 | | | |x| | | | | |
 | | |x| | | | | | |
 | |x| | | | | | | |
 |F| | | | | | | | |
 | | | | | | | | | |
 | | | | | | | | | |
然后使用possibleNextNodes[Math.round(possibleNextNodes.length/2)-1]

所有这些路径都有相同的成本,因为它们都包含相同数量的步骤,但在这种情况下,最合理的路径如下

 | | | | | | | | | |
 |S| | | | | | | | |
 |x| | | | | | | | |
 |x| | | | | | | | |
 |x| | | | | | | | |
 |x| | | | | | | | |
 |x| | | | | | | | |
 |F| | | | | | | | |
 | | | | | | | | | |
 | | | | | | | | | |

是否有一种正式接受的方法使路径看起来更合理,而不仅仅是数学上正确?

您需要在启发式函数中添加一个平局断路器。这里的问题是,有许多路径具有相同的成本

对于有利于直接路线的简单平局,可以使用叉积。也就是说,如果S是起点,e是终点,X是算法中的当前位置,则可以计算S-e和X-e的叉积,并在启发式偏离0(=直接路线)越远的情况下,向启发式添加惩罚

代码:

 dx1 = current.x - goal.x
 dy1 = current.y - goal.y
 dx2 = start.x - goal.x
 dy2 = start.y - goal.y
 cross = abs(dx1*dy2 - dx2*dy1)
 heuristic += cross*0.001

另请参见,这是一篇关于*的优秀教程。

如果您希望路径看起来自然,则需要确保成本与笛卡尔坐标系上的长度相对应。这意味着对角线移动的成本应该是垂直或水平移动成本的2倍

什么更“明智”?更直?如果算法要解决这个问题,你需要对它进行适当的量化


由于对角移动与水平/垂直移动一样便宜,因此根据A*可用的所有标准,所有路径都是等效的。如果你想要一条更“合理”的路径,你需要告诉算法一些路径比其他路径更可取,有效地将水平/垂直加权为“优于”对角线。据我所知,这将改变您环境的参数。

如果我没记错的话,诀窍是在代价函数中添加一个额外的参数(对于相邻节点之间的每一步,或者对于您的情况中的正方形),该参数会使转向稍微比正常情况下更为严重(例如,对于双向移动,相对成本大于
sqrt(2)
)。现在,在平滑路径和实际降低路径的最佳性(延长路径)之间可能存在一条细微的界限但是,您无法以任何方式避免这种情况。您需要找到特定于您自己的应用程序的某种折衷方法,而这只能通过测试来实现


我相信,一个游戏开发网站上有一篇文章详细介绍了如何做到这一点,但我现在似乎找不到它。不管怎样,试一下你的成本函数,看看你得到了什么结果——我很确定这是正确的方法。

你可以在每个方块的成本计算中添加“控制努力”。actor将尽量不要过度转向或改变方向,因为这将增加路径成本:


我怀疑您需要将相对成本增加到sqrt(2)之外,但是的,这是一条路。我认为您的想法是正确的,但在许多情况下,这仍然会留下许多相同的成本路径。例如,假设s在(1,1)处,F在(11,10)处,则会有9条等分的“最佳路径”每个由9个右下移动组成,其中一个右下移动混合在某个地方。您可能希望右下移动位于一端或正中间,因此您需要一种方法来增加所需路径的分数。+1。出色的平分功能。(您可能需要调整0.001,以确保启发式无法爬过队伍中另一条较短但较丑陋的路径……哦,这可能会产生一些有趣且美丽的(虽然不太理想)路径!)
 dx1 = current.x - goal.x
 dy1 = current.y - goal.y
 dx2 = start.x - goal.x
 dy2 = start.y - goal.y
 cross = abs(dx1*dy2 - dx2*dy1)
 heuristic += cross*0.001