A*(A-Star)算法帮助
嗯,这是我更新的代码。它并没有减速,但没有出现任何路径。
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;
}
}
Well, this is my updated code. It doesn't slow down, but no path appears.
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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该代码有几个问题。首先,您的 X + 1 和 Y + 1 检查的比较方式错误(大于而不是小于)。我怀疑这就是导致算法失败的原因。
其次,虽然我不熟悉该算法,但我怀疑您需要做一些事情来确保您已经检查过的节点不会在后续迭代中再次检查。另外,您需要确保不会将节点添加到已存在的
MapNodes
中。这些因素的结合很可能是您所看到的速度缓慢的原因,因为它将导致带有许多冗余节点的MapNodes
呈指数增长。There are a couple of issues with the code. Firstly, your X + 1 and Y + 1 checks have the comparison the wrong way around (greater-than instead of less-than). I suspect that's what causing the algorithm to fail.
Secondly, while I'm not familiar with the algorithm, I suspect you need to do something to ensure that nodes you've already check are not checked again in subsequent iterations. Also, you need to make sure you don't add nodes to
MapNodes
that are already present. The combination of these is likely to be the cause of the slowness you're seeing, because it will result in exponential growth ofMapNodes
with many redundant nodes.除了 Chris 提到的之外,您对 MapNodes 的使用还存在其他问题。它需要排序,并包含所有成员,包括您放在列表
addNodes
上的所有节点。缓存需要添加到 MapNodes 的所有节点不是有效的 A* 实现。当您将节点添加到addNodes
时,它实际上应该添加到MapNodes
中,然后MapNodes
应按 F 排序,F 是一个关联的数字与一个节点,它是从起始节点到该节点的总成本与为该节点评估的启发式函数的值之和。互联网上有多种关于启发式函数的描述,我建议您尝试阅读。顺便说一句,你的代码中的启发式在哪里? A* 算法只是一种没有启发式的缓慢 Dijkstra 算法。恐怕你所实现的更像是 Dijkstra 而不是 A*。
并回答您的实际问题:该算法可能不会产生路径,因为存在错误,从而阻止搜索算法实际到达目标节点。
Next to what Chris mentions, there's something else wrong with your usage of
MapNodes
. It needs to be sorted, and contain all members, including all nodes you put on the listaddNodes
. Caching all nodes which need to be added toMapNodes
is not a valid A* implementation. When you add a node toaddNodes
, it should actually be added toMapNodes
andMapNodes
should then be sorted by F, which is a number associated with a node, which is the sum of the total cost from the startnode to that node and the value of a heuristic function evaluated for that node. There are multiple descriptions of heuristic functions on the internet, I suggest you try to read about that.And btw, where's the heuristic in your code? An A* algorithm is just a slow Dijkstra algorithm without a heuristic. I'm afraid what you've implemented resembles Dijkstra more that A*.
And to answer your actual question: the algorithm probably doesn't yield a path because there are bugs, preventing the search algorithm from actually reaching the destination node.