A*(A-Star)算法帮助
本文关键字:算法 帮助 A-Star | 更新日期: 2023-09-27 17:58:28
好吧,这是我更新的代码。它没有减速,但没有出现任何路径。
public static IntPosition[] GetPath(BlockType[,] blocks, IntPosition start, IntPosition end, int threshhold)
{
List<Node> MapNodes = new List<Node>();
MapNodes.Add(new Node() { Position = start });
bool[,] explored = new bool[blocks.GetLength(0), blocks.GetLength(1)];
explored[start.X, start.Y] = true;
int? endNode = null;
int index = 0;
while (endNode == null && index < threshhold)
{
List<Node> addNodes = new List<Node>();
foreach (Node n in MapNodes)
{
//left
if (n.Position.X - 1 >= 0)
if (explored[n.Position.X - 1, n.Position.Y] == false)
if (blocks[n.Position.X - 1, n.Position.Y] == BlockType.Open)
{
int i = addNodes.Count;
addNodes.Add(new Node() { Position = new IntPosition(n.Position.X - 1, n.Position.Y), ParentNode = n });
explored[n.Position.X - 1, n.Position.Y] = true;
if (addNodes[i].Position == end)
endNode = i;
}
//right
if (n.Position.X + 1 <= blocks.GetLength(0) - 1)
if (explored[n.Position.X + 1, n.Position.Y] == false)
if (blocks[n.Position.X + 1, n.Position.Y] == BlockType.Open)
{
int i = addNodes.Count;
addNodes.Add(new Node() { Position = new IntPosition(n.Position.X + 1, n.Position.Y), ParentNode = n });
explored[n.Position.X + 1, n.Position.Y] = true;
if (addNodes[i].Position == end)
endNode = i;
}
//up
if (n.Position.Y - 1 >= 0)
if (explored[n.Position.X, n.Position.Y - 1] == false)
if (blocks[n.Position.X, n.Position.Y - 1] == BlockType.Open)
{
int i = addNodes.Count;
addNodes.Add(new Node() { Position = new IntPosition(n.Position.X, n.Position.Y - 1), ParentNode = n });
explored[n.Position.X, n.Position.Y - 1] = true;
if (addNodes[i].Position == end)
endNode = i;
}
//down
if (n.Position.Y + 1 <= blocks.GetLength(1))
if (explored[n.Position.X, n.Position.Y + 1] == false)
if (blocks[n.Position.X, n.Position.Y + 1] == BlockType.Open)
{
int i = addNodes.Count;
addNodes.Add(new Node() { Position = new IntPosition(n.Position.X, n.Position.Y + 1), ParentNode = n });
explored[n.Position.X, n.Position.Y + 1] = true;
if (addNodes[i].Position == end)
endNode = i;
}
}
MapNodes.AddRange(addNodes);
index++;
}
if (endNode == null)
return new IntPosition[] { };
else
{
List<IntPosition> path = new List<IntPosition>();
path.Add(end);
Node CurrentNode = (MapNodes[(int)endNode].ParentNode);
bool endReached = false;
while (endReached == false)
{
path.Add(CurrentNode.Position);
if (CurrentNode.Position == start)
endReached = true;
else
CurrentNode = CurrentNode.ParentNode;
}
path.Reverse();
return path.ToArray();
}
}
public class IntPosition
{
public int X;
public int Y;
public IntPosition(int x, int y)
{
X = x;
Y = y;
}
public IntPosition() { X = 0; Y = 0; }
public override bool Equals(object obj)
{
return ((IntPosition)obj).X == X && ((IntPosition)obj).Y == Y;
}
}
代码中有几个问题。首先,您的X+1和Y+1检查的比较方式错误(大于而不是小于)。我怀疑这就是导致算法失败的原因。
其次,虽然我不熟悉该算法,但我怀疑您需要做一些事情来确保在后续迭代中不会再次检查您已经检查过的节点。此外,您需要确保没有向MapNodes
添加已经存在的节点。这些因素的结合可能是您所看到的缓慢的原因,因为这将导致具有许多冗余节点的MapNodes
呈指数级增长。
除了Chris提到的,您对MapNodes
的使用还有其他问题。它需要进行排序,并包含所有成员,包括您放入列表addNodes
中的所有节点。缓存所有需要添加到MapNodes
的节点不是有效的a*实现。当您将一个节点添加到addNodes
时,它实际上应该添加到MapNodes
,然后MapNodes
应该按F排序,F是一个与节点相关的数字,是从起始节点到该节点的总成本和为该节点评估的启发式函数的值的总和。互联网上有很多关于启发式函数的描述,我建议你试着读一下。
顺便说一句,你的代码中的启发式在哪里?A*算法只是一个没有启发式的慢速Dijkstra算法。恐怕你实现的更像Dijkstra而不是A*。
为了回答你的实际问题:算法可能不会产生路径,因为存在错误,阻止了搜索算法真正到达目的节点。