C# 如何实现A*算法?

C# 如何实现A*算法?,c#,algorithm,a-star,C#,Algorithm,A Star,在C#?中,哪一种应该是获得*(a星)算法的简单实现的方法详细解释了基本实现: 这篇博文的目的是通过一个非常简单的C#实现来展示A*的基本原理 它还指出了更好的实现,更适合生产使用: 至于找到更好路线的方法,有很多C#示例比这一个更好、更丰富。在CodeProject上有一个非常好的演示解决方案,它可以为搜索算法设置动画,并允许用户调整一些设置。[……] 。它有一个漂亮、清晰的GUI,并允许调整一些设置 在函数AStar中,我们首先创建一个新的matrixNode,参数为fromX和fromY。

在C#?

中,哪一种应该是获得*(a星)算法的简单实现的方法详细解释了基本实现:

这篇博文的目的是通过一个非常简单的C#实现来展示A*的基本原理

它还指出了更好的实现,更适合生产使用:

至于找到更好路线的方法,有很多C#示例比这一个更好、更丰富。在CodeProject上有一个非常好的演示解决方案,它可以为搜索算法设置动画,并允许用户调整一些设置。[……]

。它有一个漂亮、清晰的GUI,并允许调整一些设置


在函数AStar中,我们首先创建一个新的matrixNode,参数为fromX和fromY。matrixNode具有属性,“fr”是指任何给定matrixNode与起始节点之间的距离,“to”是指给定matrixNode与目标matrixNode之间的距离(在unitTest的示例中,坐标(3,3)处为“E”),以及属性“sum”是“to”与“fr”之和。属性父节点是对给定节点在从开始节点到达结束节点的路径中移动到的matrixNode的引用。如维基百科页面所述,绿色和红色词典分别是openSet和closedSet。这些集合的总体思想是,我们试图在绿色/开放集合中找到具有最低“和”值的matrixNode,因为“和”是节点从起始节点(fromX,fromY)到结束节点(toX,toY)的距离之和

publicstaticvoidunittest\u AStar()
{
char[][]矩阵=新char[][{new char[]{'-','S','-','-','X'},
新字符[]{'-','X','X','-','-'},
新字符[]{'-','-','-','-','X','-'},
新字符[]{'X','-','X','E','-'},
新字符[]{'-','-','-','-','-','X'};
//正在寻找从(0,1)处的“S”到(3,3)处的“E”的最短路径
//标有“X”的障碍物
int fromX=0,fromY=1,toX=3,toY=3;
matrixNode endNode=AStar(矩阵、fromX、fromY、toX、toY);
//循环通过父节点,直到到达起始节点
堆栈路径=新堆栈();
while(endNode.x!=fromX | | endNode.y!=fromY)
{
推送路径(endNode);
endNode=endNode.parent;
}
推送路径(endNode);
Console.WriteLine(“从的最短路径”+
(“+fromX+”,“+fromY+”)到”+
“(“+toX+”,“+toY+”)是:\n”);
而(path.Count>0)
{
matrixNode节点=path.Pop();
Console.WriteLine(“+node.x+”,“+node.y+”);
}
}
公共类矩阵节点
{
公共整数fr=0,to=0,sum=0;
公共整数x,y;
公共矩阵节点父节点;
}
公共静态矩阵node AStar(char[][]矩阵,int-fromX,int-fromY,int-toX,int-toY)
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//在这个版本中,矩阵中的一个元素可以一步向左/向上/向右/向下移动,对角线移动两步。
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//绿色和红色的键是matrixNode的x.ToString()+y.ToString()
字典绿色=新建字典();//打开
字典红色=新字典();//已关闭
matrixNode startNode=新matrixNode{x=fromX,y=fromY};
字符串键=startNode.x.ToString()+startNode.x.ToString();
绿色。添加(键,开始节点);
Func smallestGreen=()=>
{
KeyValuePair最小=绿色。元素位于(0);
foreach(绿色的KeyValuePair项)
{
if(item.Value.sum<最小值.Value.sum)
最小=项目;
否则如果(item.Value.sum==最小的.Value.sum
&&item.Value.to<最小值.to)
最小=项目;
}
返回最小;
};
//将这些值添加到当前节点的x和y值以获得左/上/右/下邻居
List FourNeights=新列表()
{新的KeyValuePair(-1,0),
新的KeyValuePair(0,1),
新的KeyValuePair(1,0),
新的KeyValuePair(0,-1)};
int maxX=矩阵.GetLength(0);
如果(maxX==0)
返回null;
int maxY=矩阵[0]。长度;
while(true)
{
如果(greens.Count==0)
返回null;
KeyValuePair电流=最小绿色();
if(current.Value.x==toX&¤t.Value.y==toY)
返回当前值;
绿色。移除(当前。键);
reds.Add(current.Key,current.Value);
foreach(四邻域中的KeyValuePair plusXY)
{
int nbrX=当前.Value.x+plusXY.Key;
int nbrY=当前.Value.y+加上.Value;
字符串nbrKey=nbrX.ToString()+nbrY.ToString();
如果(nbrX<0 | | nbrY<0 | | nbrX>=maxX | | nbrY>=maxY
||矩阵[nbrX][nbrY]='X'//用'X'标记的障碍物
||红色。集装箱(nbrKey))
继续;
if(绿色容器(nbrKey))
{
matrixNode curNbr=绿色[nbrKey];
int-from=Math.Abs(nbrX-fromX)+Math.Abs
    public static void unitTest_AStar()
    {
        char[][] matrix = new char[][] { new char[] {'-', 'S', '-', '-', 'X'},
                                         new char[] {'-', 'X', 'X', '-', '-'},
                                         new char[] {'-', '-', '-', 'X', '-'},
                                         new char[] {'X', '-', 'X', 'E', '-'},
                                         new char[] {'-', '-', '-', '-', 'X'}};

        //looking for shortest path from 'S' at (0,1) to 'E' at (3,3)
        //obstacles marked by 'X'
        int fromX = 0, fromY = 1, toX = 3, toY = 3;
        matrixNode endNode = AStar(matrix, fromX, fromY, toX, toY);

        //looping through the Parent nodes until we get to the start node
        Stack<matrixNode> path = new Stack<matrixNode>();

        while (endNode.x != fromX || endNode.y != fromY)
        {
            path.Push(endNode);
            endNode = endNode.parent;
        }
        path.Push(endNode);

        Console.WriteLine("The shortest path from  " +
                          "(" + fromX + "," + fromY + ")  to " +
                          "(" + toX + "," + toY + ")  is:  \n");

        while (path.Count > 0)
        {
            matrixNode node = path.Pop();
            Console.WriteLine("(" + node.x + "," + node.y + ")");
        }
    }

    public class matrixNode
    {
        public int fr = 0, to = 0, sum = 0;
        public int x, y;
        public matrixNode parent;
    }

    public static matrixNode AStar(char[][] matrix, int fromX, int fromY, int toX, int toY)
    {
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        // in this version an element in a matrix can move left/up/right/down in one step, two steps for a diagonal move.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        //the keys for greens and reds are x.ToString() + y.ToString() of the matrixNode 
        Dictionary<string, matrixNode> greens = new Dictionary<string, matrixNode>(); //open 
        Dictionary<string, matrixNode> reds = new Dictionary<string, matrixNode>(); //closed 

        matrixNode startNode = new matrixNode { x = fromX, y = fromY };
        string key = startNode.x.ToString() + startNode.x.ToString();
        greens.Add(key, startNode);

        Func<KeyValuePair<string, matrixNode>> smallestGreen = () =>
        {
            KeyValuePair<string, matrixNode> smallest = greens.ElementAt(0);

            foreach (KeyValuePair<string, matrixNode> item in greens)
            {
                if (item.Value.sum < smallest.Value.sum)
                    smallest = item;
                else if (item.Value.sum == smallest.Value.sum
                        && item.Value.to < smallest.Value.to)
                    smallest = item;
            }

            return smallest;
        };


        //add these values to current node's x and y values to get the left/up/right/bottom neighbors
        List<KeyValuePair<int, int>> fourNeighbors = new List<KeyValuePair<int, int>>()
                                            { new KeyValuePair<int, int>(-1,0),
                                              new KeyValuePair<int, int>(0,1),
                                              new KeyValuePair<int, int>(1, 0),
                                              new KeyValuePair<int, int>(0,-1) };

        int maxX = matrix.GetLength(0);
        if (maxX == 0)
            return null;
        int maxY = matrix[0].Length;

        while (true)
        {
            if (greens.Count == 0)
                return null;

            KeyValuePair<string, matrixNode> current = smallestGreen();
            if (current.Value.x == toX && current.Value.y == toY)
                return current.Value;

            greens.Remove(current.Key);
            reds.Add(current.Key, current.Value);

            foreach (KeyValuePair<int, int> plusXY in fourNeighbors)
            {
                int nbrX = current.Value.x + plusXY.Key;
                int nbrY = current.Value.y + plusXY.Value;
                string nbrKey = nbrX.ToString() + nbrY.ToString();
                if (nbrX < 0 || nbrY < 0 || nbrX >= maxX || nbrY >= maxY
                    || matrix[nbrX][nbrY] == 'X' //obstacles marked by 'X'
                    || reds.ContainsKey(nbrKey))
                    continue;

                if (greens.ContainsKey(nbrKey))
                {
                    matrixNode curNbr = greens[nbrKey];
                    int from = Math.Abs(nbrX - fromX) + Math.Abs(nbrY - fromY);
                    if (from < curNbr.fr)
                    {
                        curNbr.fr = from;
                        curNbr.sum = curNbr.fr + curNbr.to;
                        curNbr.parent = current.Value;
                    }
                }
                else
                {
                    matrixNode curNbr = new matrixNode { x = nbrX, y = nbrY };
                    curNbr.fr = Math.Abs(nbrX - fromX) + Math.Abs(nbrY - fromY);
                    curNbr.to = Math.Abs(nbrX - toX) + Math.Abs(nbrY - toY);
                    curNbr.sum = curNbr.fr + curNbr.to;
                    curNbr.parent = current.Value;
                    greens.Add(nbrKey, curNbr);
                }
            }
        }
    }