A* 寻路

 

A* 寻路

  先来看图吧

   

 

其中 左上角的 绿色 为起始点  右下角的绿色为 终点。蓝色为 障碍物,红色 为要走的路, 灰色为 探索的路。

 

A*方法总结

 

路径评分

选择路径中经过哪个方格的关键是下面这个等式:

F = G + H

这里:
    * G = 从起点A,沿着产生的路径,移动到网格上指定方格的移动耗费。
    * H = 从网格上那个方格移动到终点B的预估移动耗费。这经常被称为启发式的,可能会让你有点迷惑。这样叫的原因是因为它只是个猜测。我们没办法事先知道路径的长度,因为路上可能存在各种障碍(墙,水,等等)。

 

每一步的操作写在一起:

   1,把起始格添加到开启列表。
   2,重复如下的工作:
      a) 寻找开启列表中F值最低的格子。我们称它为当前格。
      b) 把它切换到关闭列表。
      c) 对相邻的8格中的每一个?
          * 如果它不可通过或者已经在关闭列表中,略过它。反之如下。
          * 如果它不在开启列表中,把它添加进去。把当前格作为这一格的父节

点。记录这一格的F,G,和H值。
          * 如果它已经在开启列表中,用G值为参考检查新的路径是否更好。更低

的G值意味着更好的路径。如果是这样,就把这一格的父节点改成当前格,并且重新

计算这一格的G和F值。如果你保持你的开启列表按F值排序,改变之后你可能需要重

新对开启列表排序。

      d) 停止,当你
          * 把目标格添加进了开启列表,这时候路径被找到,或者
          * 没有找到目标格,开启列表已经空了。这时候,路径不存在。
   3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到起始格。这就是

你的路径。

 

----------------------------------前一阵没事写的 代码--------------------------------------------

//============================================================

    class AstarNode {
        public int g = 0;
        public int h = 0;

        public int x=0;
        public int y = 0;
         int f = 0;

         public int F {

             get
             {
                 return g + h;
             }         
         }

       public  AstarNode parent = null;      
    
    
    }


    class AStarAnalisys
    {
        List<AstarNode> openList = new List<AstarNode>();
        List<AstarNode> closeList = new List<AstarNode>();
        Point bPoint=new Point(0,0);
        Point ePoint=new Point(0,0);
        byte[,] map = new byte[20, 20];

        AstarNode CurNode = null;       

        Point[] directionP = new Point[8] { 
        new Point(-1,-1),
        new Point(-1,0),
        new Point(-1,1),

        new Point(0,-1),
        new Point(0,1),

        new Point(1,-1),
        new Point(1,0),
        new Point(1,1)       
        
        };


        public int costG(AstarNode pnode, int g)
        {
            AstarNode p = pnode.parent;

            return p.g + g;


        }


        public void prepare(Point bP, Point eP, byte[,] maps)
        {
            map = maps;
            bPoint = bP;
            ePoint = eP;
            CurNode = new AstarNode();
            CurNode.x = bP.X;
            CurNode.y = bP.Y;
            CurNode.g = 0;
            CurNode.parent = null;
            CurNode.h = (Math.Abs(eP.X - bP.X) + Math.Abs(eP.Y - bP.Y))*10;
            openList.Add(CurNode);
           Analisys(CurNode);
        
        }

   public  void  Analisys( AstarNode cuNode)
        {


            List<AstarNode> lis = (from item in openList orderby item.F ascending select item).ToList<AstarNode>();

            if (lis.Count > 0)
            {
                AstarNode newCurNode = lis[0];

                cuNode = newCurNode;

               // openList.Remove(newCurNode);
                RemoveNode(openList, new Point(newCurNode.x, newCurNode.y));
                closeList.Add(newCurNode);

                if (newCurNode == null)
                {
                    MessageBox.Show("这儿没有路可走了");
                    Form1.maparray = map;
                    return;
                }

                //------------------------------------------



                foreach (Point p in directionP)
                {

                    int x = cuNode.x + p.X;
                    int y = cuNode.y + p.Y;

                    if (x >= 0 && x < 20 && y >= 0 && y < 20)
                    {
                        if (Math.Abs(p.X) + Math.Abs(p.Y) == 2)
                        {
                            if (p.X == 1 && p.Y == 1)
                            {
                                if (map[x - 1, y] == 4 || map[x, y - 1] == 4) continue;
                            }


                            if (p.X == -1 && p.Y == -1)
                            {
                                if (map[x, y + 1] == 4 || map[x + 1, y] == 4) continue;
                            }


                            if (p.X == 1 && p.Y == -1)
                            {
                                if (map[x - 1, y] == 4 || map[x, y + 1] == 4) continue;
                            }


                            if (p.X == -1 && p.Y == 1)
                            {
                                if (map[x + 1, y] == 4 || map[x, y - 1] == 4) continue;
                            }

                        }



                        if (map[x, y] == 4)//如果是障碍物
                        {
                            continue;
                        }
                        else
                        {
                            AstarNode exits = isExits(closeList, new Point(x, y));
                            if (exits != null)
                            {// 如果在关闭列表里
                             
                                continue;
                            }
                            else
                            {      // 如果不在关闭列表里,也不是障碍物
                                   
                                
                             map[x, y] = 6; 
                             //再看看是不是在 开放列表里
                                AstarNode open = isExits(openList, new Point(x, y));
                                if (open == null)
                                {
                                   
                                    AstarNode tempNode = new AstarNode();
                                    tempNode.x = x;
                                    tempNode.y = y;
                                    tempNode.parent = cuNode;
                                    tempNode.h = (Math.Abs(ePoint.X - x) + Math.Abs(ePoint.Y - y)) * 10;

                                    if (Math.Abs(p.X) + Math.Abs(p.Y) == 2)
                                        tempNode.g = costG(tempNode, 14);
                                    else
                                    {
                                        tempNode.g = costG(tempNode, 10);
                                    }

                                    openList.Add(tempNode);
                                }
                                else
                                { //如果在开放列表里
                                   
                                    AstarNode tempNode = new AstarNode();
                                    tempNode.x = x;
                                    tempNode.y = y;
                                    tempNode.parent = cuNode;
                                    tempNode.h = (Math.Abs(ePoint.X - x) + Math.Abs(ePoint.Y - y)) * 10;

                                    if (Math.Abs(p.X) + Math.Abs(p.Y) == 2)
                                        tempNode.g = costG(tempNode, 14);
                                    else
                                    {
                                        tempNode.g = costG(tempNode, 10);
                                    }

                                    if (tempNode.g > open.g)
                                    {
                                        //如果有更好的路                                      
                                       // open.parent = cuNode;


                                        if (Math.Abs(p.X) + Math.Abs(p.Y) == 2)
                                            open.g = costG(tempNode, 14);
                                        else
                                        {
                                            open.g = costG(tempNode, 10);
                                        }
                                       
                                        openList.Add(tempNode);
                                        continue;

                                    }


                                }


                            }


                        }

                    }
                    else
                    {
                        //如果点不在地图中
                        continue;

                    }




                    if ((x == ePoint.X && y == ePoint.Y))
                    {
                        AstarNode wst = cuNode;
                        List<AstarNode> temp = new List<AstarNode>();

                        AstarNode tempCurNode = new AstarNode();

                        tempCurNode.x = x;
                        tempCurNode.y = y;
                        temp.Add(tempCurNode);

                       // MessageBox.Show(closeList.Count.ToString());


                        while (wst != null)
                        {
                            temp.Add(wst);
                            wst = wst.parent;


                        }

                        string ss = "";
                        foreach (AstarNode i in temp)
                        {

                            ss += "(" + i.x + "," + i.y + ")\n";
                            map[i.x, i.y] = 5;
                        }

                       // MessageBox.Show(" 找到的路径是:\n" + ss);

                        Form1.maparray = map;
                        return;
                    }

                }

                //---------------------------------------------------------------

                Analisys(cuNode);
            }
            else
            {
                MessageBox.Show("没有路可走了");
                Form1.maparray = map;

                return;

            }     

     


            
                
                       
        
        
        }

        AstarNode isExits(List<AstarNode> list, Point p)
        { 
          foreach(AstarNode  item in list )
          {
          
           if(item.x==p.X && item.y==p.Y)
           {
               return item;
           
           }
          
          }

          return null;        
        
        }


        void RemoveNode(List<AstarNode> list, Point p)
        {
            List<AstarNode> templist = (from item in list where item.x == p.X && item.y == p.Y select item).ToList();

            foreach (AstarNode item in templist)
            {
                    list.Remove(item);              

            }

        }


     
    
    }

 

 

附:

 

A* 算法的详解

http://data.gameres.com/message.asp?TopicID=25439

 

源代码:

 

Download Source Code

 

 

posted @ 2012-06-15 13:16  kingNull  阅读(402)  评论(0编辑  收藏  举报