所以我在Unity C#中实现了一个A *算法来做一些测试,以便构建一个基于2D的游戏。我知道有几个组件可以帮助你解决这个问题,但我想尝试自己只是为了挑战。
我基本上已经阅读了A *应该如何表现并将行为转换为代码。它几乎可以工作。但是有一些观点,相邻的瓷砖具有完全相同的分数(曼哈顿距离+距离原点的距离),并且您最终得到的路径通向目的地但不是最短的。正如你在图像中看到的那样,那两个相邻的瓷砖具有相同的分数,但我在那一点上随机选取...(在下图中,起点是猫,红叉是目的点。绿色半透明文件是计算出的路径)
我在想,因为没有太多的瓷砖,我可以从4个初始相邻瓷砖中计算出4个不同的路径,将有效的路径存储在一个数组中,然后基本上只使用最短的,但也许会是太多的开销,还有另一种解决方案吗?
使用基本计算计算距离I
。private int CalculateManhattanDistance(int x1, int x2, int y1, int y2)
{
return Mathf.Abs(x1 - x2) + Mathf.Abs(y1 - y2);
}
答案 0 :(得分:3)
也许这有助于您了解@ZdeněkJelínek和@Peter Wishart所指出的内容。 openSet(也称为frontier)通常是PriorityQueue。队列的节点根据其优先级进行排序。节点的优先级计算为到目前为止的成本(案例中的步数)和启发式距离(在您的情况下为曼哈顿)的总和。因此,一旦A *到达优先级为11的节点,它将停止探索该路径并继续其他路径(蓝色圆圈)
答案 1 :(得分:2)
我建议您针对代码检查 A * e.g. on Wikipedia的伪代码。
基于那个伪代码你会像这样实现算法数据,我怀疑你已经简化了其中的一些:
var closedSet = new HashSet<GraphNode>();
var openSet = new List<GraphNode>{startNode};
var cameFrom = new Dictionary<GraphNode, GraphNode>();
var gScore = new Dictionary<GraphNode, double>();
var fScore = new Dictionary<GraphNode, double>();
当算法对启发式算法做出错误的首选时,就像在这个测试用例中一样,它最初会评估错误方向的移动。 但这应该不是问题:
fScore
gScore
(通过cameFrom)fScore
openSet
移至closedSet
这意味着沿着“错误”路径的节点将计算增加的实际+预期距离,达到算法开始选择其他open
节点的程度,例如第一次迭代中的“右”节点。