A *(A-Star)算法帮助

时间:2011-06-05 07:36:45

标签: c# xna path-finding 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;
    }
}

2 个答案:

答案 0 :(得分:0)

代码存在一些问题。首先,你的X + 1和Y + 1检查比较错误(大于而不是小于)。我怀疑这是导致算法失败的原因。

其次,虽然我不熟悉算法,但我怀疑你需要做些什么来确保在后续迭代中不再检查你已检查过的节点。此外,您需要确保不向MapNodes添加已存在的节点。这些组合很可能是您所看到的缓慢的原因,因为它将导致MapNodes指数增长,并带有许多冗余节点。

答案 1 :(得分:0)

除了Chris提到的内容之外,使用MapNodes还有其他问题。它需要进行排序,并包含所有成员,包括您放在列表addNodes上的所有节点。缓存需要添加到MapNodes的所有节点不是有效的A *实现。将节点添加到addNodes时,实际上应该将其添加到MapNodes,然后MapNodes应按F排序,这是与节点关联的数字,即节点的总和从startnode到该节点的总成本以及为该节点评估的启发式函数的值。互联网上有多种启发式功能的描述,我建议你试着阅读。

顺便问一下,代码中的启发式在哪里? A *算法只是一种没有启发式的慢Dijkstra算法。我担心你所实施的东西比Dijkstra更像A *。

并回答你的实际问题:算法可能不会产生路径,因为存在错误,阻止搜索算法实际到达目标节点。