AStar(A*)算法核心思想( for unity)

news2024/11/24 0:09:19

AStar算法

  • 算法思想
  • 举例理解
  • 核心代码

A* 算法,A* (A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法,也是解决许多搜索问题的有效算法。算法中的距离估算值与实际值越接近,最终搜索速度越快。

注意:AStar的类应该作为一种单例类只提供调用方法,对节点的初始化都应该在节点类中完成

算法思想

1.创建两个列表用于维护节点,openList和closeList
openList用于存储所有已保存但是还未考察的节点
closeList用于存储已经访问的节点

2.只要openList中还存在未考察节点,就从中取出一个代价最低的节点作为当前节点。
3.如果当前节点是目标节点则说明一条合适的路径已经找到。如果不是,则开始为何该节点。
4.对不在closeList列表中的节点重新维护代价,然后放入openList中。
5持续2->4的过程。

举例理解

首先我们需要知道估价函数:F(N)=G(N) + H(N) AStar算法会不断维护节点的代价,已得到代价最小的一段路径
其中:G为是在状态空间中从初始状态状态n的最小代价
H为 是从状态n目标状态的最小估计代价

以正方形节点为举例:
对于单位正方形,边长为1,对角线代价为√2 ≈1.1414
但是为了计算将代价都×10,我们规定在水平垂直方向上移动所需的代价为10,对角向方向上移动所需的代价为14.正方形节点代价
正方形节点的代价开销我会按如下格式标注
请添加图片描述
那么如果使用A*算法去寻找(0,0,)到(2,2)的路径,会发生什么呢?
第一次寻找:
开始时openList中只有(0,0)一个节点,所以直接找(0,0)的邻居,红色部分为(0,0)的邻居节点(一个正方形应该有8个邻居节点,但是也可以规定对角线方向上的节点不是邻居节点,但一般都不会这样做。)
请添加图片描述
这三个邻居节点一开始都不存在与closeList中,所以把这三个邻居节点都放入openList中(保存节点时,不会考虑存入的节点代价,任意此刻代价较大的节点都会可能在经历几次查找之后变为openList最小的节点,这样我们的算法就可以“反悔”自己走过的路径)

第二次寻找:
此时,openList中有三个节点,也可以看出(1,1)的代价花费最小,所以我们把(1,1)节点拿出来
(1,1)的邻居节点为: (0,0), (1,0), (2,0), (0,1), (2,1),(0,2), (1,2), (2,2)
(0,0)节点已经位于closeList中,(1,0)和(0,1)位于openList中,所以这三个节点都不再重新计算(不退步,也不故意绕路)
请添加图片描述
其实在进行这一步寻找时,在找到(2,2)节点时就会直接返回结果,我们也可以看到通过A*算法找到的节点代价是最小的,但是路径却不一定是唯一的(如果在上述正方形节点中,对角线方向上的节点不被视为邻居,那么可以有两条路径从(0,0)通向(2,2))

在正方形节点中计算F会用到曼哈顿方法花费

Vector2 dist =new Vector2Int(Mathf.Abs((int)pos.x - (int)other.pos.x), Mathf.Abs((int)pos.x- (int) other.pos.y));
int lowest =Mathf.Min(dist.x, dist.y);
int highest =Mathf.Max(dist.x, dist.y);
int horizontalMoveRequired =highest - lowest;
return lowest *14 + horizontalMoveRequired *10;

意思是对于一个直角三角形的路径,我们可以按照先走一个较短直角边的等腰直角三角形的对角线,然后在走一段两直角边之差的距离就可以了。
请添加图片描述

核心代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AStar{

    public static AStar Instace;

    public List<NodeBase> _openList; //打开列表
    public List<NodeBase> _closeList; //关闭列表
    
    public List<NodeBase> FindPath(NodeBase startNode,NodeBase endNode){
        
        _openList = new List<NodeBase>(){ startNode}; //起始需要在打开列表中填入开始节点
        _closeList =new List<NodeBase>();

        //在这之前应该初始好所有的节点。
        startNode.G = 0;
        startNode.H = startNode.GetDistance(endNode.coords);
        
        while(_openList.Count > 0){
            NodeBase currentNodeBase = GetLowestFCostNode(_openList);
            if(currentNodeBase == endNode) return CalculatePath(endNode); 
           
            _openList.Remove(currentNodeBase);
            _closeList.Add(currentNodeBase);

            var tantativeGCost = currentNodeBase.G + currentNodeBase.GetDistance(endNode.coords); 
            //遍历邻居

            foreach(NodeBase n in currentNodeBase.Neighbours){
                if(_closeList.Contains(n)) continue;
                
                if(tantativeGCost < n .G && !_openList.Contains(n)){
                    n.father =currentNodeBase;
                    n.G= tantativeGCost;
                    n.H= n.GetDistance(endNode.coords);
					
                    _openList.Add(n);
                }
            }
        }
        return CalculatePath(endNode); //调用计算路径的函数返回结果序列
    }


    //得到Fcost最低的一个点
    private NodeBase GetLowestFCostNode(List<NodeBase> nodes){
        NodeBase lowe![请添加图片描述](https://img-blog.csdnimg.cn/0127049aecc5498d8cc9f14a51ddc5d5.png)
stFcostNode = nodes[0];
        foreach(Node n  in nodes){
            if(n.F < lowestFcostNode.F){
                lowestFcostNode = n;
            }
        }
        return lowestFcostNode;
    }


    //计算结果路径路径
    private List<NodeBase> CalculatePath(NodeBase node){
        List<NodeBase> nodeBases = new List<NodeBase>();
        while(node != null){
            nodeBases.Add(node);
            node=node.father;
        }
        nodeBases.Reverse();
        return nodeBases;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软考初级哪个好考

其实软考初级的实用性差不多。只是看自身怎么看&#xff0c;考哪一科对你来说&#xff0c;产生的意义更大&#xff0c;对自己以后的发展前景帮助大&#xff0c;那你就选择哪一科就行。 软考初级科目有&#xff1a;程序员、网络管理员、信息处理技术员、信息系统运行管理员、网…

C语言之vs2022安装教程,还不会的快来看

下载安装包官方无毒下载链接:https://visualstudio.microsoft.com/zh-hans/vs/点击链接或者复制到浏览器出现如下按钮点击下载社区版本Visual Studio 2022Community 2022: 社区版&#xff0c;也可以理解为个人版。适用于学生、开源和个人。一些新手用来学习是个不错的选择Profe…

第十三届蓝桥杯省赛 C++ B组 - 修剪灌木

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;蓝桥杯题解集合 &#x1f4dd;原题地址&#xff1a;付账问题 &#x1f4e3;专栏定位&#xff1a;为想参加蓝桥别的小伙伴整理常考算法题解&#xff0c;祝大家…

sentinel部署配置

sentinel部署配置sentinel 部署&#xff08;V1.8.6&#xff09;获取 Sentinel 控制台启动修改用户名密码控制台登录客户端集成sentinel 部署&#xff08;V1.8.6&#xff09; 获取 Sentinel 控制台 您可以从 release 页面 下载最新版本的控制台 jar 包。 官网&#xff1a; ht…

【C语言】深度剖析数据在内存中的存储---(附源码 | 建议收藏)

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;凡人修C传 &#x1f4ac;总结&#xff1a;希望你看完之后&…

让Tomcat服务器运行在Windows后台

让tomcat运行在Windows后台一、设置环境变量二、安装tomcat服务三、设置后台自动运行本机环境&#xff1a;win10一、设置环境变量 进入tomcat主目录的bin文件夹&#xff0c;复制路径 快捷键winr键唤出运行框&#xff0c;输入sysdm.cpl然后点击“确定”进入系统属性面板 在系统…

传统工科应该怎么学习机器学习or深度学习?

还是老生常谈。建议先不要直接上手机器学习/深度学习&#xff0c;先把你研究对象/信号的机理给搞清楚&#xff0c;然后再开始上现代信号处理&#xff0c;机器学习/深度学习算法&#xff0c;只有对你研究对象的机理深入了解&#xff0c;才能更好地对信号处理算法&#xff0c;机器…

【职工管理系统】C++全栈体系(十三)

职工管理系统 第一章 管理系统需求 职工管理系统可以用来管理公司内所有员工的信息 公司中职工分为三类&#xff1a;普通员工、经理、老板&#xff0c;显示信息时&#xff0c;需要显示职工编号、职工姓名、职工岗位、以及职责 普通员工职责&#xff1a;完成经理交给的任务 …

运算符重载及组合与继承

目录 一、运算符重载 1.1普通运算符重载 1.2特殊运算符重载 二、标准输入输出流 三、组合与继承 3.1组合 3.2继承 1) public继承方式 2) protected继承方式 3) private继承方式 小作业&#xff1a;模仿c的string类&#xff0c;自己实现string类 一、运算符重载 百度…

【文件随机读写和文件缓冲区】

1.1fseek函数 1.2ftell函数1.3rewind函数2. 文件读取结束的判定2.1文件缓冲区 1.1fseek函数 根据文件指针的位置和偏移量来定位文件指针。 int fseek ( FILE * stream, long int offset, int origin );看不懂没关系&#xff0c;举个例子你就明白了。 我们首先在text.txt文…

送什么礼物给小学生合适?保护视力的专业护眼台灯

在学生们过节以及生日来临&#xff0c;父母们会精心为孩子准备好礼物的&#xff0c;而最有实际意义的&#xff0c;是对学习有所帮助的&#xff0c;比如学习机、护眼灯、绘画本&#xff0c;能丰富孩子的生活都可以&#xff0c;这几年儿童青少年的近视率迅速上升&#xff0c;有52…

TypeScript中的 | 分隔符、 运算符、类型谓词is

一. | 分隔符 在 TypeScript 中联合类型&#xff08;Union Types&#xff09;表示取值可以为多种类型中的一种&#xff0c;联合类型使用 | 分隔每个类型。联合类型通常与 null 或 undefined 一起使用&#xff1a; const sayHello (name: string | undefined) > { /* ... …

WC!咱平时使用的PDF,原来这么不安全?

早前&#xff0c;在2019年3月初&#xff0c;来自明斯特大学及波鸿鲁尔大学的德国研究人员称&#xff0c;他们已经设法利用新发现的漏洞&#xff0c;并成功地攻破了PDF文件中的数字签名。 随后&#xff0c;2019年10月再次披露&#xff1a; 加密PDF存在PDFex漏洞。 最后&#x…

基于wordpress和Sakura主题插件搭建博客网站

基于wordpress和Sakura主题插件搭建博客网站1.引言2.认清现实3.使用的本地化方法4.分享自己走的一些弯路5.硬刚404的余波6.额外的收获1.引言 最近&#xff0c;本着试试的想法&#xff0c;想着找一个前端方面的工作&#xff0c;遇到一些招聘软件或者网站上面有一栏是个人博客网站…

我用递归写单调栈(?)

前言&#xff1a;嗯,这个题上午有的思路&#xff0c;敲了一中午代码&#xff0c;改了一下午最后超时? 题&#xff1a;D. Boris and His Amazing Haircut 题意&#xff1a;一个理发师可以把一段数组给建成一个高度&#xff0c;他现在每个高度的剪子都有若干个。给一个原始数组和…

STL - Set容器

基本概念 构造和赋值 功能描述&#xff1a;创建set容器以及赋值 #include <algorithm> //算法 #include <iostream> #include <set> #include <string> using namespace std;// set/multiset容器void printSet(set<int>& s) {for (set<i…

Java之节点流和处理流(Buffered字节字符处理流)

文章目录前言基本介绍Buffered字符处理流BufferedReader缓冲字符输入流BufferedWriter缓冲字符输出流文件拷贝Buffered字节处理流文件拷贝&#xff08;二进制文件&#xff09;处理流关闭问题前言 Java中的流按照功能可以分为节点流和处理流。其中节点流是直接用来访问数据源&a…

GO的interface的使用和反射

博客主页&#xff1a;&#x1f3c6;看看是李XX还是李歘歘 &#x1f3c6; &#x1f33a;每天不定期分享一些包括但不限于计算机基础、算法、后端开发相关的知识点&#xff0c;以及职场小菜鸡的生活。&#x1f33a; &#x1f497;点关注不迷路&#xff0c;总有一些&#x1f4d6;知…

自动化测试

一、关于自动化什么是自动化?扫地机器人 自动浇水机 自动洗手液 智能马桶... &#xff0c;能够有效的减少人力的消耗&#xff0c;同时提高生活质量。而自动化测试同样&#xff0c;能够有效减少人力的投入&#xff0c;同时提高了测试的质量和效率。回归测试&#xff0c;版本越来…

23.Isaac教程--Isaac导航

Isaac导航 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 节点和消息 Isaac 应用程序由多个节点创建。 导航堆栈具有以下节点&#xff1a; GlobalLocalization&#xff1a;在没有先验信息的情况下&#xff0c;仅使用当前范围扫描测量来估计地…