小工具知识网

当前位置: 首页 > 行业知识 > 路径规划A*(A-Star)算法

行业知识

路径规划A*(A-Star)算法

2026-10-30 20:45:57 来源:互联网转载

路径规划A*算法介绍

A*(A-Star)算法是一种常用的寻路算法,用于图形表达的环境中找到起点到目标点的最短路径。

代价函数()由两部分组成:起点沿着已生成的路径到达当前节点的开销()和当前节点到终点的预估开销ℎ()。公式表示: () = () + ℎ()

A*算法的详细原理之定义

基本定义

G: G表示从起点A移动到网格上指定方格的移动耗费(上下左右,下面实例没写沿斜方向移动)

H: H表示从指定方格移动到终点的预计耗费(H方法多种,这里设定忽略障碍物上下左右移动)

F: F=G+H,表示该点的总耗费

4.open列表:一个记录下所有被考虑来寻找最短路径的格子

5. closed列表: 一个记录下不会再被考虑的格子

曼哈顿距离:通过计算两点在空间中沿着网格线(垂直和水平方向)距离来度量它们之间的距离

A*算法结合了广度优先搜索和启发式搜索的思想。它使用一个启发式函数来估计从当前位置到目标位置的代价,通过不断更新并选择代价最低的路径来进行搜索。

下面是A*算法的详细步骤:

1. 初始化

   - 将起点放入一个待处理节点列表中,并将其代价设为0。

   - 初始化一个节点存储表,用于记录每个节点的父节点、代价等信息。

   - 初始化一个节点集合,用于存储已经访问过的节点。

2. 循环直到找到目标点或者遍历完所有可达节点:

   - 从待处理节点列表中选择代价最低的节点,作为当前节点。

   - 如果当前节点为目标点,算法结束,可以通过节点存储表回溯找到最短路径。

   - 将当前节点从待处理节点列表中移除,放入已访问节点集合中。

   - 对当前节点的相邻节点进行处理:

   - 如果相邻节点已经在已访问节点集合中,跳过该节点。

   - 计算相邻节点的代价,包括从起点到该节点的代价和从该节点到目标点的启发式估计代价。

   - 如果相邻节点不在待处理节点列表中,将其加入,并更新节点存储表。

   - 如果相邻节点已经在待处理节点列表中,并且新的代价更小,则更新节点存储表中的信息。

3. 如果待处理节点列表为空,则表示无法从起点找到目标点,算法结束。

   A*算法的关键在于如何选择合适的启发式函数来估计代价。一个好的启发式函数应该满足以下条件:

   - 它应该是可计算的,并且能够对任意节点对进行估价。

   - 对于目标点,它的估价应该为0。

   - 它应该尽可能准确地估计节点到目标点的实际代价

这里使用曼哈顿距离

A*算法在寻路问题中具有较好的性能和效率,在很多实际应用中得到广泛使用。但需要注意的是,A*算法只能保证找到一条最短路径,而不能保证是全局最优的路径。同时,在大规模图形环境中,A*算法的效率可能会受到影响,可以采用一些优化策略来加快搜索速度。

路径规划A*算法实现实例

Node:定义每个结点的属性

using UnityEngine;using System;//寻路算法的一个节点public class Node : IComparable{    public float nodeTotalCost;//总成本    public float estimatedCost;//估算成本    //estimatedCost=nodeTotalCost+estimatedCost    //f            =       g     +      h    public bool bObstacle;//障碍物    public Node parent;//父节点    public Vector3 position;//每个节点的位置    public Node() { //结点信息        this.estimatedCost = 0.0f;        this.nodeTotalCost = 1.0f;        this.bObstacle = false;        this.parent = null;    }    public Node(Vector3 pos) {//结点位置        this.estimatedCost = 0.0f;        this.nodeTotalCost = 1.0f;        this.bObstacle = false;        this.parent = null;        this.position = pos;    }    public void MarkAsObstacle() { //设置障碍物        this.bObstacle= true;    }    public int CompareTo(object obj)//比较节点估算成本的大小    {        Node node = (Node)obj;        if (this.estimatedCost node.estimatedCost){            return 1;        }        return 0;    }}

 PriorityQueue:优先级队列

using System.Collections;using System.Collections.Generic;using UnityEngine;//优先级队列public class PriorityQueue {    private ArrayList nodes= new ArrayList();//数组列表        public int Length { //获取结点的数量        get { return this.nodes.Count; }    }    public Node First()//获取优先级队列第一个结点    {        if (this.nodes.Count > 0)        {            return (Node)this.nodes[0];        }         return null;    }    public bool Contains(object node) { //检查队列里是否有该结点        return this.nodes.Contains(node);    }    public void Push(Node node) { //存入优先级队列        this.nodes.Add(node);        this.nodes.Sort();//从小到大排序    }    public void Remove(Node node) {//从优先级队列删除        this.nodes.Remove(node);        this.nodes.Sort();    }}

 GirdManager:网格管理器,画出参考网格线

网格编号从原点开始,左为X正方向,上位Z轴正方向

using System.Collections;using UnityEngine;//网格管理器public class GirdManager : MonoBehaviour{    private static GirdManager s_Instance=null;    public static GirdManager instance {//单例        get         {            if (s_Instance == null) {                s_Instance = FindObjectOfType(typeof(GirdManager)) as GirdManager;                if (s_Instance == null)                {                    Debug.Log("你在场景中必须要有一个网格管理器");                }            }            return s_Instance;        }    }    private void OnApplicationQuit()    {        s_Instance = null;    }    public int numOfRows;//网格行数    public int numOfColumns;//网格列数    public float gridCellSize;//每一个网格大小    public bool showGrid = true;//画出网格    private GameObject[] obstacleList;//障碍物数组    private Node[,] nodes;//结点数组    private Vector3 origin = new Vector3();    public Vector3 Origin {        get { return origin;}    }    void Awake() {//初始化时必须执行        origin=this.transform.position;        obstacleList = GameObject.FindGameObjectsWithTag("Obstacle");//查找障碍物,障碍物标签标识为Obstacle        CalculateObstacles();    }    private void CalculateObstacles()//计算障碍物属于哪个网格    {        nodes = new Node[numOfColumns,numOfRows];        int index = 0;        for (int i = 0; i intervalTime)        {            elapsedTime = 0.0f;            FindPath();//每隔一秒事件更新一次路径        }    }    void OnDrawGizmos()    {        if (pathArray == null)         {            return;        }        if (pathArray.Count > 0)         {            int index = 1;            foreach (Node node in pathArray)             {                if (index  

注意:设置每个cube的tag

路径实现结果展示

路径规划A*算法实例

学习参考:AStar_demo_1_哔哩哔哩_bilibili

上一篇:安装 Kali NetHunter (完整版、精简版、非root版)、实战指南、ARM设备武器化指南、andrax、安卓渗透drozer

下一篇:云服务器怎么使用gpt?