A*算法的原理

摘自:https://blog.csdn.net/weixin_44489823/article/details/89382502

1:之前没有真正的理解A*算法的原理,于是就找各种博客对A*算法进行原理上的理解,毕竟理解了对以后做寻路啊等会有很大帮助,为了以后忘记了还可以重新温习一遍;

2:绿色的块块代表起始点,红色的快快代表是终点,蓝色的快快代表墙 

image001.jpg

3:如果我们需要寻路,我们当然是想找一条最短路径到达终点,难道还要绕个大湾在抵达终点吗,哈哈

4:ok废话不多说,开始探索

先明白这几个字段的概念:

1:OpenList:可以理解为开放列表,之后需要对开放列表进行遍历,找到最小的那个F值

2:CloseList:可以理解为不需要关注的列表

3:节点:因为没一个节点都有8个小方块指向自己,可以默认为自己成为了父节点

4:G:从起点 A 移动到指定方格的移动代价,沿着到达该方格而生成的路径

5:H:从指定的方格移动到终点 B 的估算成本。这个通常被称为试探法,有点让人混淆。为什么这么叫呢,因为这是个猜测。直到我们找到了路径我们才会知道真正的距离,因为途中有各种各样的东西 ( 比如墙壁,水等 ),最短抵达终点的距离,当然只能水平和垂直方法 。

6:F:F = G+H,利用这个值来做寻路排查的标记

5:详解图:

寻找节点,在根据节点,去寻找有没有在更换路径之后更小的G值,有的话,那么就更新当前的G值和F值并且更新箭头指向,在从Openlist寻找最小的F值,继续遍历,最终找到最优的路径

寻路关键代码:

    /// <summary>
    /// 使用A*算法寻路
    /// </summary>
    /// <param name="start"></param>
    /// <param name="end"></param>
    void FindPath(Vector2 start,Vector2 end)
    {
        //和A*算法无关,只是为了显示使用
        int showFindNum=1;

        //开启列表
        List<Cell> openLs = new List<Cell>();
        //关闭列表
        List<Cell> closeLs = new List<Cell>();

        //起点
        Cell startCell = grid.GetCell(start);
        //终点
        Cell endCell = grid.GetCell(end);
        Debug.LogFormat("寻路开始,start({0}),end({1})!",start,end);

        //将起点作为待处理的点放入开启列表,
        openLs.Add(startCell);

        //如果开启列表没有待处理点表示寻路失败,此路不通
        while(openLs.Count>0)
        {
            //遍历开启列表,找到消费最小的点作为检查点
            Cell cur = openLs[0];
            for (int i = 0; i < openLs.Count; i++)
            {
                if(openLs[i].fCost<cur.fCost&&openLs[i].hCost<cur.hCost)
                {
                    cur = openLs[i];
                }
            }
            Debug.Log("当前检查点:" + cur.ToString()+" 编号:"+showFindNum+"  open列表节点数量:"+openLs.Count);
            //显示在界面,和A*算法无关
            cur.obj.transform.Find("Num").GetComponent<Text>().text=showFindNum.ToString();
            showFindNum++;

            //从开启列表中删除检查点,把它加入到一个“关闭列表”,列表中保存所有不需要再次检查的方格。
            openLs.Remove(cur);
            closeLs.Add(cur);

            //检查是否找到终点
            if(cur==endCell)
            {
                Debug.Log("寻路结束!");
                grid.CreatePath(cur);
                return;
            }

            //根据检查点来找到周围可行走的点
            //1.如果是墙或者在关闭列表中则跳过
            //2.如果点不在开启列表中则添加
            //3.如果点在开启列表中且当前的总花费比之前的总花费小,则更新该点信息
            List<Cell> aroundCells = GetAllAroundCells(cur);
            foreach (var cell in aroundCells)
            {
                
                if (cell.isWall || closeLs.Contains(cell))
                    continue;

                int cost= cur.gCost+ GetDistanceCost(cell, cur);

                if(cost<cell.gCost||!openLs.Contains(cell))
                {
                    cell.gCost = cost;
                    cell.hCost = GetDistanceCost(cell,endCell);
                    cell.parent = cur;
                    Debug.Log("cell:" + cell.ToString() + "  parent:" + cur.ToString() + "  " + cell.PrintCost());
                    if(!openLs.Contains(cell))
                    {
                        openLs.Add(cell);
                    }

                    //显示在界面,和A*算法无关
                    cell.obj.transform.Find("Cost").GetComponent<Text>().text = cell.fCost.ToString();
                }


            }

        }

        Debug.Log("寻路失败!");
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EvanXZ

各位大佬 多多支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值