问题描述
我编写了A *的实现,该实现依赖于在sortedSet中按节点F分数对节点进行排序。
在某些情况下,排序似乎是在Node对象的“ F”值实际上是 second 最低值而不是Min值时插入“ Min”值,如上所述。我完全不知道为什么会这样。我相信这会引起连锁反应,导致nodeTree.Remove和nodeTree.RemoveWhere失败,但这可能是导致此问题的实际原因,我确实不确定-尽管我不知道如何解决此问题是的。
这是使用的比较器。我认为我不太清楚如何实现这些功能,这是相对明显的,但是我认为这应该可以按照我的预期进行。
public class FValueFirst : Comparer<PathfindingAgent.Node>
{
public override int Compare(PathfindingAgent.Node x,PathfindingAgent.Node y)
{
int result = x.F.Compareto(y.F);
if (result == 0)
{
result = y.G.Compareto(x.G);
}
if(x == y)
{
result = 0;
}
return result;
}
}
这是Node对象,仅供参考。
public class Node
{
public Cell cell;
public float G;
public float H;
public bool Opened;
public bool Closed;
public Node PrevIoUs;
public float F { get => G + H; }
}
这是全部发生的功能。谢天谢地,结果是确定性的。根据当前的destID和网格障碍物的特定布局,它会始终在同一迭代中变得混乱。
public void PathTo(Vector3Int destID)
{
SortedSet<Node> nodeTree = new SortedSet<Node>(new FValueFirst());
Vector3Int radius = PathfindingGrid.Instance.GridRadius;
NodeGrid = new Node[radius.x * 2 + 1,radius.y * 2 + 1,radius.z * 2 + 1];
Node startNode = new Node()
{
cell = PathfindingGrid.Cells[CurrentID.x,CurrentID.y,CurrentID.z],G = 0,H = 0
};
Node endNode = new Node()
{
cell = PathfindingGrid.Cells[destID.x,destID.y,destID.z],H = 0
};
Vector3Int sID = startNode.cell.ID;
Vector3Int eID = endNode.cell.ID;
NodeGrid[sID.x,sID.y,sID.z] = startNode;
NodeGrid[eID.x,eID.y,eID.z] = endNode;
if (endNode.cell.IsOccupied) return;
nodeTree.Add(startNode);
int iterations = 0;
while(true)
{
Node node;
node = nodeTree.Min;
node.Closed = true;
nodeTree.RemoveWhere(n => n == node);
if(node == nodeTree.Min)
{
throw new Exception($"Incorrect node was removed from the tree");
}
if (node == endNode)
{
List<Node> chain = BacktraceChain(node);
Debug.Log($"Path found from {CurrentID} to {destID} with score {endNode.G} traversing {chain.Count} cells in {iterations} iterations");
DrawLine(chain,Color.white);
break;
}
List<Node> neighbours = GetNeighbours(node);
foreach(Node neighbour in neighbours)
{
if (neighbour == startNode || neighbour.Closed) continue;
float newg = Vector3Int.distance(node.cell.ID,neighbour.cell.ID) + node.G;
if (!neighbour.Opened || newg < neighbour.G)
{
neighbour.G = newg;
neighbour.H = ManhattanHeuristic(neighbour,endNode);
neighbour.PrevIoUs = node;
if(!neighbour.Opened)
{
nodeTree.Add(neighbour);
neighbour.Opened = true;
}
else
{
nodeTree.RemoveWhere(n => n == neighbour);
nodeTree.Add(neighbour);
}
}
}
iterations++;
}
}
解决方法
为了后代,我解决了这个问题-这是由于我对SortedList类型的经验不足。
在函数结尾处发现的这段代码应归咎于
style: {
base: {
backgroundColor: 'red',}
}
特别是,树中的项目无法将其比较值修改为不再在该索引中正确比较的程度。该项目必须 first 从列表中删除,修改和读取。
事后看来,我的猜测是,尽管在修改后立即将其删除,但由于修改,该树无法被充分遍历以访问目标项。
因此,我的解决方案是简单地重新排列块,以使删除和添加分别发生在修改的两侧,就像这样:
if (!neighbour.Opened || newg < neighbour.G)
{
neighbour.G = newg;
neighbour.H = ManhattanHeuristic(neighbour,endNode);
neighbour.Previous = node;
if(!neighbour.Opened)
{
nodeTree.Add(neighbour);
neighbour.Opened = true;
}
else
{
nodeTree.RemoveWhere(n => n == neighbour);
nodeTree.Add(neighbour);
}