如果在迭代之间保存节点成本启发式算法,则算法将在第一次迭代后中断。如果更改了起点和目标,则无法找到新路径。只有通过清算成本才能找到新的途径。这是正常的吗?
添加了代码。优先级队列尚未实现。它适用于从Unity 3D中的XYZ空间转换的网格。
if (newMovementCostToNeighbor < jumpPoint.gCost || jumpPoint.fCost <= 0)
{
jumpPoint.gCost = newMovementCostToNeighbor;
jumpPoint.hCost = getDistance(jumpPoint, targetNode);
jumpPoint.parent = currentNode;
successors.Add(jumpPoint);
}
识别IDSuccessors中的问题,检查路径成本是否为&lt;保存的gcost或者从未访问过jumpPoint(如果它的fCost&lt; = 0)。由于检查主要取决于jumpPoint小于保存的gCost的路径成本,因此路径查找在运行一次后会中断。
if (newMovementCostToNeighbor < jumpPoint.gCost || (!openSet.Contains(jumpPoint) && !closedSet.Contains(jumpPoint)) || jumpPoint.fCost <= 0)
{
jumpPoint.gCost = newMovementCostToNeighbor;
jumpPoint.hCost = getDistance(jumpPoint, targetNode);
jumpPoint.parent = currentNode;
successors.Add(jumpPoint);
}
找到解决方案。补充支票。我们的想法是检查runPoint在运行期间是否从未见过,所以一种方法是检查openSet或closedSet中是否缺少它。
void FindPath(Vector3 startPos, Vector3 targetPos)
{
Node startNode = grid.NodeFromWorldPoint(startPos);
Node targetNode = grid.NodeFromWorldPoint(targetPos);
List<Node> openSet = new List<Node>();
HashSet<Node> closedSet = new HashSet<Node>();
openSet.Add(startNode);
while(openSet.Count > 0)
{
Node currentNode = openSet[0];
for(int i = 1; i < openSet.Count; i++)
{
if(openSet[i].fCost < currentNode.fCost || (openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost))
{
currentNode = openSet[i];
}
}
openSet.Remove(currentNode);
closedSet.Add(currentNode);
if(currentNode == targetNode)
{
RetracePath(startNode, targetNode);
return;
}
List<Node> successors = IDSuccessors(currentNode, startNode, targetNode);
foreach(Node n in successors)
{
if(n != null)
{
openSet.Add(n);
}
}
}
}
public List<Node> IDSuccessors(Node currentNode, Node startNode, Node targetNode)
{
List<Node> successors = new List<Node>();
List<Node> neighbors = grid.getNeighbors(currentNode);
foreach (Node neighbor in neighbors)
{
int dx = Mathf.Clamp(neighbor.gridX - currentNode.gridX, -1, 1);
int dy = Mathf.Clamp(neighbor.gridY - currentNode.gridY, -1, 1);
Node jumpPoint = Jump(currentNode.gridX, currentNode.gridY, dx, dy, startNode, targetNode);
if (jumpPoint != null)
{
int newMovementCostToNeighbor = currentNode.gCost + getDistance(currentNode, jumpPoint);
if (newMovementCostToNeighbor < jumpPoint.gCost || jumpPoint.fCost <= 0)
{
jumpPoint.gCost = newMovementCostToNeighbor;
jumpPoint.hCost = getDistance(jumpPoint, targetNode);
jumpPoint.parent = currentNode;
successors.Add(jumpPoint);
}
}
}
return successors;
}