我正在制作一个2D瓦片地图,现在尝试实现A*路径查找。我正在按照维基百科上的A*伪代码进行操作。
除了算法在决策上出现一些奇怪的行为外,其他进展顺利。
到目前为止我的代码如下:
void Pathfinding(Point from, Point destination) { goalNode = new Node(destination, 0, 0); startNode = new Node(from, 0, ManhattanDistance(from, destination)); open = new List<Node>(); //节点列表 closed = new List<Node>(); open.Add(startNode); //添加起始点 while(open.Count > 0) { node = getBestNode(); //获取F值最低的节点 if(node.position == goalNode.position) { Debug.Log("到达目标"); getPath(node); break; } removeNode(node, open); closed.Add(node); List<Node> neighbors = getNeighbors(node); foreach(Node n in neighbors) { float g_score = node.G + 1; float h_score = ManhattanDistance(n.position, goalNode.position); float f_score = g_score + h_score; if(isValueInList(n, closed) && f_score >= n.F) continue; if(!isValueInList(n, open) || f_score < n.F) { n.parent = node; n.G = g_score; n.G = h_score; if(!isValueInList(n, open)) { map_data[n.position.x, n.position.y] = 4; open.Add(n); } } } }}
运行此代码的结果如下:
蓝色表示开放列表中的节点,绿色表示选择的到达目标节点的路径。
解决方案:
void Pathfinding(Point from, Point destination) { goalNode = new Node(destination, 0, 0); startNode = new Node(from, 0, ManhattanDistance(from, destination)); open = new List<Node>(); //节点列表 closed = new List<Node>(); open.Add(startNode); //添加起始点 while(open.Count > 0) { node = getBestNode(); //获取F值最低的节点 if(node.position == goalNode.position) { Debug.Log("到达目标"); getPath(node); break; } removeNode(node, open); closed.Add(node); List<Node> neighbors = getNeighbors(node); foreach(Node n in neighbors) { float g_score = node.G + 1; float h_score = ManhattanDistance(n.position, goalNode.position); float f_score = g_score + h_score; if(isValueInList(n, closed) && f_score >= n.F) continue; if(!isValueInList(n, open) || f_score < n.F) { n.parent = node; n.G = g_score; n.H = h_score; if(!isValueInList(n, open)) { map_data[n.position.x, n.position.y] = 4; open.Add(n); } } } }}
回答:
首先,您的开放节点应该按降序排序,而您的代码中没有排序。虽然您计算了距离(g)和启发式(h),但从未实际使用它们。您应该考虑使用有序容器而不是列表(因为在每次迭代中排序列表效率不高)
其次,您没有将启发式值存储在节点中,如下所示:
n.G = h_score;
应该改为:
n.H = h_score;