A*算法--C#版

要学A*算法,首先向大家安利一个视频:一级棒A*算法讲解视频

这个视频真的讲的超级好,演示效果一级棒。以前我看书看A*是真心没看懂,什么启发函数、估值函数...真心看得累。强烈建议和我一样的同学看看上面的那个视频,看完之后,你自己都可以写出A*算法来找最短路径。

然后下面写写我觉得在实现A*算法的过程中,一些需要注意的问题:

1. 注意,已经加入到openList中的Node,需要设置一个标志来记录,下一次访问其他节点的时候,在“把邻居结点加入到openList”这个步骤时,要注意,如果邻居Node已经被加入到openList,则不要重复添加了!之前我忽略了这个问题,结果导致算法在do-while循环中出不来了,因为重复的节点一直在被添加。

2.

注意,GCost = preNode.GCost + GetCost( curNode.pos, PreNode.pos)。
而不是:GCost = GetCost( curNode.pos, startNode.pos)
在修复以上两个Bug后,顺利找到了最短路径。

关于A*,对于找最短路径而言,

HCost = 从当前结点到目标节点的Cost。

GCost = 从当前结点到起始点的Cost。(是cost,不是距离!见上面2)

        FCost = HCost + GCost.

部分代码:

1.节点的数据结构

    class Node
        {
        private Node father;    //父节点
        internal Node Father
            {
            get { return father; }
            set { father = value; }
            }
        //cost
        private int g_cost;
        public int G_cost
            {
            get { return g_cost; }
            set { g_cost = value; }
            }
        private int h_cost;
        public int H_cost
            {
            get { return h_cost; }
            set { h_cost = value; }
            }
        private int f_cost;
        public int F_cost
            {
            get { return f_cost; }
            set { f_cost = value; }
            }
        //对应地图上的行号列号
        private int i;
        /// <summary>
        /// 列号
        /// </summary>
        public int I
            {
            get { return i; }
            set { i = value; }
            }
        private int j;
        /// <summary>
        /// 行号
        /// </summary>
        public int J
            {
            get { return j; }
            set { j = value; }
            }
        //是否为墙壁
       public bool wall;
        //是否被加入到了close中
       private bool inClose;
       private bool inOpen;

       public bool InOpen
           {
           get { return inOpen; }
           set { inOpen = value; }
           }
       public bool InClose
           {
           get { return inClose; }
           set { inClose = value; }
           }
        public Node()
            {
            father = null;
            wall = false;
            g_cost = 0;
            h_cost = 0;
            f_cost = 0;
            i = 1000;
            j = 1000;
            inClose = false;
            inOpen = false;
            }
        /// <summary>
        /// 外部调用这个函数来给node赋值,初始化时候用
        /// </summary>
        /// <param name="m">行号</param>
        /// <param name="n">列号</param>
        /// <param name="wall">map中的数值</param>
        public void inital(int m , int n , char iswall)
            {
            J = m;
            I = n;
            wall = iswall.Equals('0')?false : true;
            inClose = false;
            }
        }
2.A*算法主体

            /// <summary>
            /// A*之找到最短路径算法
            /// </summary>
            /// <param name="map">地图</param>
            /// <param name="mapStr">原始txt读到的string,用于最后修改并且打印路径</param>
            /// <param name="rowNum">地图的行数</param>
            /// <param name="columNum">地图的列数</param>
            public void GetShortestPath ( Node[ , ] map , string mapStr , int rowNum , int columNum )
            {
                //0.将起点加入到开放列表中
                openList .Add ( map[ startY_ , startX_ ] );
                //int curPosX,curPosY;//temp use,X:列,Y:行
                #region do--while循环体
                do
                    {                    
                    openList .Sort ( SortByFHcost );                   
                    curNode = openList[ 0 ];
                    //将其从open中移除                    
                    openList .Remove ( curNode );
                    curNode .InOpen = false; ;                                    
                    //加入到close列表中
                    //closeList .Add ( curNode );                   
                    //设置开关
                    curNode .InClose = true;
                    //判断是否为终点
                    if( curNode.I == endX_ && curNode.J == endY_ )
                        {
                        Console .WriteLine ( "find path" );
                        break;
                        }                    
                    #region 把邻居加入到开放列表中                   
                    tempY = curNode .J - 1;
                    if ( tempY >= 0 )
                        {
                        //不越界,检查墙壁,可以则加入
                        AddNewNodeToList ( map[ tempY , curNode .I ] , curNode );
                        }
                    //↖
                    tempX = curNode .I - 1;
                    if ( tempX >= 0 && tempY >= 0 )
                        {
                        AddNewNodeToList ( map[ tempY , tempX ] , curNode );
                        }
                    //↗  
                    //tempY = startY - 1//上面已经算了一次,所以这里可以不运算这一步了
                    tempX = curNode .I + 1;
                    if ( tempX < columNum && tempY >= 0 )
                        {
                        AddNewNodeToList ( map[ tempY , tempX ] , curNode );
                        }
                    //左
                    tempX = curNode .I - 1;
                    if ( tempX >= 0 )
                        {
                        AddNewNodeToList (  map[ curNode .J,tempX ] , curNode );
                        }
                    //右
                    tempX = curNode .I + 1;
                    if ( tempX < columNum )
                        {
                        AddNewNodeToList (  map[ curNode .J, tempX ] , curNode );
                        }
                    //下
                    tempY = curNode .J + 1;
                    if ( tempY < rowNum )
                        {
                        AddNewNodeToList ( map[ tempY,curNode .I  ] , curNode );
                        }
                    //↙
                    tempX = curNode .I - 1;
                    if ( tempX >= 0 && tempY < rowNum )
                        {
                        AddNewNodeToList (  map[ tempY ,tempX ] , curNode );
                        }
                    //↘
                    tempX = curNode .I + 1;
                    if ( tempX < columNum && tempY < rowNum )
                        {
                        AddNewNodeToList (  map[ tempY, tempX ] , curNode );
                        }
                    //周围8个全部检查并加入到开放列表完毕
                    #endregion 加入完毕                    
                    }
                while( true );
                #endregion do-while完毕
                //找到最短路径,打印输出
                
                //输出最短路径坐标
            }//end for method

效果图:


源代码我放在了GitHub上,需要的朋友:点击打开链接

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值