A * Algorithm System.StackOverflowException

时间:2012-04-09 19:57:58

标签: c# a-star

public List<Location2D> Path(Location2D start, Location2D goal)
{
    openset = new List<NodeInfo>(); // The set of tentative nodes to be evaluated, initially containing the start node.
    closedset = new List<NodeInfo>(); // The set of nodes already evaluated.
    path = new List<Location2D>(); // The path result.
    came_from = new Dictionary<Location2D, Location2D>();

    NodeInfo Start = new NodeInfo();
    Start.SetLoction(start.X, start.Y);
    Start.H = GetHValue(start, goal);
    openset.Add(Start);

    while (openset.Count > 0) { // while openset is not empty
        NodeInfo current = CheckBestNode(); //the node in openset having the lowest f_score[] value

        if (current.Location.Equals(goal)) {
            ReconstructPathRecursive(current.Location);
            return path;
        }

        for (int i = 0; i < 8; i++) { // neighbor nodes.
            NodeInfo neighbor = new NodeInfo();
            neighbor.SetLoction((ushort)(current.Location.X + ArrayX[i]), (ushort)(current.Location.Y + ArrayY[i]));

            bool tentative_is_better = false;

            if (closedset.Contains(neighbor))
                continue;
            if (!map.Cells[neighbor.Location.X, neighbor.Location.Y].Walkable) { closedset.Add(neighbor); continue; }

            Double tentative_g_score = current.G + DistanceBetween(current.Location, neighbor.Location);

            if (!openset.Contains(neighbor)) {
                openset.Add(neighbor);
                neighbor.H = GetHValue(neighbor.Location, goal);
                tentative_is_better = true;
            } else if (tentative_g_score < neighbor.G) {
                tentative_is_better = true;
            } else {
                tentative_is_better = false;
            }

            if (tentative_is_better) {
                came_from[neighbor.Location] = current.Location;
                neighbor.G = tentative_g_score;
            }
        }
    }
    return null;
}

private void ReconstructPathRecursive(Location2D current_node)
{
    Location2D temp;
    if (came_from.TryGetValue(current_node, out temp)) {
        path.Add(temp);
        ReconstructPathRecursive(temp);
    } else {
        path.Add(current_node);
    }
}

所以我实现A *算法,当它找到目标时,它会转到ReconstructPathRecursive 然后应用程序崩溃并抛出此异常An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll

This thread is stopped with only external code frames on the call stack. External code frames are typically from framework code but can also include other optimized modules which are loaded in the target process.

idk出了什么问题!

2 个答案:

答案 0 :(得分:1)

它实际上不必是递归的,因为它是尾递归的。所以你可以像这样重写它:

private void ReconstructPathIterative(Location2D current_node)
{
    Location2D temp;
    while (came_from.TryGetValue(current_node, out temp))
    {
        path.Add(temp);
        current_node = temp;
    }
    path.Add(current_node);
}

只有当路径太长而无法放入堆栈时才会有所帮助,而不是它是无限的。

答案 1 :(得分:1)

我通过将NodeInfo Parent {get; set; }添加为NodeInfo类中的字段来修复它,并且当暂定更好时,我添加了名为List<NodeInfo>的新Nodes: -

if (tentative_is_better) {
                        neighbor.Parent = current;
                        nodes.Add(neighbor);
                        neighbor.G = tentative_g_score;
                    }

然后当它找到目标时: -

if (current.Location.Equals(goal)){
                    ReconstructPath(current);
                    path.Reverse();
                    return path;
                }

其中ReconstructPath: -

private void ReconstructPath(NodeInfo current) {
            if (current.Parent == null) return;
            path.Add(current.Parent.Location);
            ReconstructPath(current.Parent);
        }

现在工作正常。

相关问题