【A星算法】A星寻路算法详解(小白也可以看懂+C#代码+零基础学习A*)

article/2025/10/2 20:17:04

1.问题背景

在制作RPG游戏角色和NPC移动时,需要角色自动避开障碍物,到达终点
怎么快速找到一条到达终点的路径?
使用a星寻路算法

2.A星算法的思路

绿色:起点;红色:终点 ;黑色:障碍物
新增的浅绿方块为当前评估节点
对角线的代价为14.14
直线代价为10
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基本概念:

f = g + h
f: 总评估代价
g:起点到当前点的代价
h:当前点到终点的预期(或理想)代价(如果当前评估点到终点的直线上没有障碍物,则当前的总代价f不会改变)
将总代价f作为权重,每次优先遍历最小的f节点
a星算法,会在开表中寻找总花费最小的节点为评估点,遍历当前评估点附近点,在附近点,选择总代价最小的点作为评估点的下一节点

1.初始化起点,终点;将起点放入开表,作为评估点,在开表中选择总代价最小的作为评估节点,如果评估节点为终点,则结束
2.将当前的节点移除开表,放入闭表中(将当前的节点标记为已评估节点)
3.先遍历评估节点周围8个点(上下左右,左上角,右上角,左下角,右下角),将它们放入一个临近点集合中
4.遍历临近点集合,如果闭表已经有该点(该点已经被评估过)或者该点是障碍物,跳过该点
5. 计算 邻近点到起点总花费newcost=当前到邻近点的距离+当前点到起点的花费
6. 1)newGCost 小于之前计算的Gost,说明该点已经被遍历过,在开表中,
说明之前的路径存在绕远路,将邻近点的上一节点改为当前点,计算邻近点的f,g,h花费
2)开表中不包含该邻近点,该节点没有被遍历,不在开表,将邻近点的上一节点改为当前点,
加入开表,计算邻近点的f,g,h花费
7.重复1
上面的过程,如果看不太懂,后面核心代码实现,有代码和注释
距离的计算
给定两个坐标,计算两个坐标的路径距离
代码 创建APathNode类

3.代码实现

public class APathNode
{public int X;public int Z;public bool available;//如果是障碍物为falsepublic float GCost = 0;//起点到当前点的花费public float HCost = 0;//当前点到终点的预期花费public float TotalCost = 0;//总花费public APathNode LastNode;//上一个节点
}

在这里插入图片描述

代码,创建AStarSearchPath类,下面代码均属于该类
计算两点的距离

public float GetCostByDistance(APathNode currentNode,APathNode neighborNode){float cost = 0;int Horizontal = Math.Abs(currentNode.X - neighborNode.X);int Vertical = Math.Abs(currentNode.Z - neighborNode.Z);int line = Math.Min(Horizontal, Vertical);//对应上图一个橙色箭头int brokenline = Horizontal + Vertical;//折线//CurveCostWeigh=14.14f,LineCostWeight=10f//cost=        曲线价值      + 直线价值 //cost=        曲线价值   +  brokenline(1黄+2橙)-2*line(橙)cost = line * CurveCostWeigh+(brokenline-2*line)*LineCostWeight;return cost;}

寻找附近的邻近点

private List<APathNode> GainNeighborNode(APathNode currentNode){List<APathNode> neighborNodes = new List<APathNode>();for (int i = -1; i <2 ; i++){for (int j = -1; j < 2; j++){if(i==0&&j==0) continue;//排除当前节点int x = currentNode.X + i;int z = currentNode.Z + j;if (x >= 0 && x < width && z >= 0 && z < height){neighborNodes.Add(Map[z, x]);//在范围的邻近点加入集合}}}return neighborNodes;}

得到最后的寻路节点集合

private void RetracePath(){FinalPaths = new List<APathNode>();APathNode point = EndPathNode;while (point!=null){FinalPaths.Add(point);point = point.LastNode;}}

寻路方法核心代码

public void SearchPath(){//将起点加入开表OpenList.Add(StartPathNode);//APathNodewhile(OpenList.Count>0){currentNode = FindMinExpectCost();//寻找总花费最小节点//将当前的节点移除开表,放入闭表中(将当前的节点标记为已评估节点)OpenList.Remove(currentNode);CloseList.Add(currentNode);//如果评估点等于终点,结束寻路if (currentNode == EndPathNode){RetracePath();//找到寻路路径Debug.Log("---找到了");return;}else{//遍历评估节点周围8个点(上下左右,左上角,右上角,左下角,右下角)List<APathNode> neighborNodes = GainNeighborNode(currentNode);for (int i = 0; i < neighborNodes.Count; i++){//如果闭表已经有该点(该点已经被评估过)或者该点是障碍物if (CloseList.Contains(neighborNodes[i]) || !neighborNodes[i].available){continue;}//新的 起点->neighbor =当前点->邻近点 +当前点->起点//计算 该邻近点到起点总花费=当前到邻近点的距离+当前点到起点的花费float newGCost = GetCostByDistance(currentNode, neighborNodes[i]) + currentNode.GCost;//1.如果邻近点到起点总花费<之前已计算的花费,说明之前的路径存在绕远路,将邻近点的上一节点改为当前点//因为计算过邻近点Gcost,所有一定存在开表中,后面值为false//2》.开表中不包含邻近点,该节点没有被遍历if (newGCost < neighborNodes[i].GCost || !OpenList.Contains(neighborNodes[i])){//更新邻近点的三大代价,将邻近点的上一节点设置为当前节点neighborNodes[i].GCost = newGCost;neighborNodes[i].HCost = GetCostByDistance(neighborNodes[i], EndPathNode);neighborNodes[i].TotalCost = neighborNodes[i].GCost + neighborNodes[i].HCost;neighborNodes[i].LastNode = currentNode;if (!OpenList.Contains(neighborNodes[i])){OpenList.Add(neighborNodes[i]);//2》.如果开表中不包含邻近点,该节点没有被遍历}}}}}}

代码初始化地图大小,障碍物坐标,起点终点坐标

public void initMapData2(Vector2 startPoint,Vector2 endPoint,Vector2 rect, GameObject root=null){this.startPoint = startPoint;this.endPoint = endPoint;//初始化地图高度,宽度this.width = (int)rect.x;this.height = (int)rect.y;if (startPoint.x <= 0 || startPoint.x > width||startPoint.y <= 0 || startPoint.y > height){throw new Exception("输入的startPoint超出范围");}if (endPoint.x <= 0 || endPoint.x > width||endPoint.y <= 0 || endPoint.y > height){throw new Exception("输入的endPoint超出范围");}Map = new APathNode[height, width];for (int i = 0; i <height; i++){for (int j = 0; j < width; j++){#region 基于自己的规则设置障碍物GameObject c=root.transform.GetChild((i*width)+j).gameObject;Map[i, j] = new APathNode();Map[i, j].X = j;Map[i, j].Z = i;Color color = c.GetComponent<MPImage>().color;if (color.r<=0&&color.g<=0&&color.b<=0)#endregion 基于自己的规则设置障碍物{Debug.Log("false");Map[i, j].available = false;}else{Debug.Log("true");Map[i, j].available = true;}}}StartPathNode = new APathNode();EndPathNode = new APathNode();StartPathNode = Map[(int)startPoint.y, (int)startPoint.x];EndPathNode = Map[(int)endPoint.y, (int)endPoint.x];}

AStarSearchPath类的属性

    public float LineCostWeight = 10f;public float CurveCostWeigh = 14.14f;public List<APathNode> OpenList=new List<APathNode>();public List<APathNode> CloseList=new List<APathNode>();public APathNode currentNode;public APathNode[,] Map;public APathNode StartPathNode;public APathNode EndPathNode;public int width;public int height;public List<APathNode> FinalPaths=new List<APathNode>();

4.结束语

希望上面的代码对大家有所帮助,有疑问的地方可以在评论区留言

优化和扩展

平滑路径,生成路径不平滑,删除无用的节点
A星寻路尽管相对于其他算法,效率比较高,但是当地图节点,比较多时,花费时间还是比较多
最小堆,可以优化在openlist开表中取最小花费的时间
拐点算法,只寻找关键的拐点
权重引导寻路,f=g+h+w,权重存储在AStarSearchPath的Map中,提前设置权重小的节点,寻路时,会沿着提前设置的节点寻路
编写地图编辑器,基于游戏引擎,在场景中设置障碍物,用图片保存
如果大家想学习更多的扩展,麻烦大家点赞评论收藏,支持一下,如果有很多人想学习,考虑出更多的关于A星的扩展


http://chatgpt.dhexx.cn/article/ME7nnTkK.shtml

相关文章

A-star算法自学

搜索过程 广度优先搜索&#xff08;BFS&#xff09;算法与Dijsktra算法的结合&#xff0c;可以得出最短的路径。 将地图信息通过划分为方形或者其他多边形格子的方法进行表示&#xff0c;便于利用二维数组存放地图信息&#xff0c;每个格子有可行和不可行两种状态&#xff1b;…

python3.6实现的A星算法

A星算法原理: 原理我就不再赘述,可以参考这篇博客https://blog.csdn.net/hitwhylz/article/details/23089415 最近用js写了一遍&#xff0c;用的同样的算法&#xff0c;需要js代码的看这里&#xff1a;https://blog.csdn.net/qq_39687901/article/details/85697127 代码实现: …

A星寻路算法介绍

你是否在做一款游戏的时候想创造一些怪兽或者游戏主角&#xff0c;让它们移动到特定的位置&#xff0c;避开墙壁和障碍物呢&#xff1f; 如果是的话&#xff0c;请看这篇教程&#xff0c;我们会展示如何使用A星寻路算法来实现它&#xff01; 在网上已经有很多篇关于A星寻路算…

对A星算法的理解

1、A*算法的**搜索区域 ** 传统A星算法是将地图简化成栅格&#xff0c;计算路径时是用每个栅格的中心点作为单位进行计算。 搜索区域分为两部分&#xff1a;开放列表和封闭列表 开放列表可以进行访问&#xff0c;封闭列表则不可以访问&#xff08;包括不可走 (unwalkable) 的方…

A星算法(Java实现)

一、适用场景 在一张地图中&#xff0c;绘制从起点移动到终点的最优路径&#xff0c;地图中会有障碍物&#xff0c;必须绕开障碍物。 二、算法思路 1. 回溯法得到路径 (如果有路径)采用“结点与结点的父节点”的关系从最终结点回溯到起点&#xff0c;得到路径。 2. 路径代…

A-Star(A*)算法

【由于专栏后几篇限制vip观看&#xff0c;我又把完整算法在公众号“武汉AI算法研习”进行了发布&#xff0c;可以查看全专栏文章。】 A-Star(A*)算法作为Dijkstra算法的扩展&#xff0c;在寻路和图的遍历过程中具有一定的高效性。 【适用范围】静态图搜索 【算法流程】A-Sta…

A星算法代码

A星算法代码python3实现 前言一、A*&#xff1f; A星1.一个搜索算法2.结果展示 二、使用环境1.python 3.x2.一些解释说明 一些话 前言 产生本文的缘由 学校计科课程要求的小作业, 在csdn上看了好多, 记录一下自己的学习 以下是本篇文章正文内容 一、A*&#xff1f; A星 1.一…

A星算法(基于matlab)

概述 基于上一篇文章提到的DFS算法和BFS算法 A星算法属于图这种数据结构的搜索算法&#xff0c;对比于树的遍历搜索&#xff0c;需要考虑到的问题是&#xff1a;同一个节点的重复访问&#xff0c;所以需要对于已经访问过的节点进行标记。 曼哈顿距离&#xff1a; 在几何度量空…

【A星算法】--第四篇(A星算法)

本篇主要介绍A星算法的过程&#xff1a; * 把起始节点加进openList * while openList 不为空 { * 当前节点 openList 中成本最低的节点 * if&#xff08;当前节点 目标节点&#xff09;{ * 路径完成 …

A星算法详解(个人认为最详细,最通俗易懂的一个版本)

A* 寻路算法 原文地址&#xff1a; http://www.gamedev.net/reference/articles/article2003.asp 概述 虽然掌握了 A* 算法的人认为它容易&#xff0c;但是对于初学者来说&#xff0c; A* 算法还是很复杂的。 搜索区域(The Search Area) 我们假设某人要从 A 点移动到 B 点&…

A星算法理解

A星算法理解 1.选择A星算法的原因 为了进行路径规划算法是不可回避的&#xff1a;启发式搜索算法是比较常规的一类算法就是在状态空间中的搜索对每一个搜索的位置进行评估&#xff0c;得到最好的位置&#xff0c;再从这个位置进行搜索直到目标。这样可以省略大量无谓的搜索路…

A星(A*, A Star)算法详解

MulinB按&#xff1a;经典的智能寻路算法&#xff0c;一个老外写的很透彻很清晰&#xff0c;很容易让人理解神秘的A*算法。以下是一个中文翻译版。 A*寻路初探 GameDev.net 作者&#xff1a; Patrick Lester 译者&#xff1a;Panic 2005年3月18日 译者序&#xff1a;很久以前就…

A星算法

A星算法 1.简述 A星算法就是试图在地图中找到一条最短路径&#xff0c;但不保证一定存在。 任务 小猫去找青蛙玩&#xff08;好TM弱智啊~&#xff09;条件 黑色方块无法通行&#xff0c;每走一个格子小猫消耗的体力都为1。 2.如果说你是小猫&#xff0c;你会怎么走&#xf…

A星算法说明

A*算法说明 文章目录 前言原理说明如何构造 h ( n ) h(n) h(n)一、欧氏距离二、曼哈顿距离三、其他 关于 g ( n ) g(n) g(n)路况设置如何实现 完整的流程搜索过程图示允许斜走&#xff0c;使用优先队列禁止斜走&#xff0c;使用优先队列允许斜走&#xff0c;使用普通队列禁止斜…

A星算法优化(一)启发函数

基于Python语言对A星算法进行优化&#xff1a;(视频中会拿python与matlab作对比) 源码地址&#xff1a;https://github.com/Grizi-ju/ros_program/blob/main/path_planning/Astar.py B站详解视频&#xff1a;https://www.bilibili.com/video/BV1FL4y1M7PM?spm_id_from333.999…

猴子都能看懂的A星算法原理

文章目录 A星算法基本原理什么是寻路算法算法的思路 算法实现脚本1————cconst.cs脚本2————AStar.cs Unity演示演示样例一演示样例二演示样例三演示样例四 俗话说&#xff0c;好记性不如烂笔头&#xff0c;对于有了解过寻路算法的同学&#xff0c;对于A星算法应该不陌生…

A星寻路算法详解(C++实现 完整代码+图片演示 )

文章目录 三种寻路算法 A星寻路算法A星寻路算法思想A星寻路准备A星寻路过程&#xff08;图例&#xff09;A星寻路代码&#xff08;完整&#xff09; 三种寻路算法 深度寻路算法&#xff1a;不一定能找到最佳路径&#xff0c;但是寻路快速&#xff0c;只能走直线。广度寻路算法…

A星(A*、A Star)路径规划算法详解(附MATLAB代码)

首先看看运行效果&#xff0c;分别有三种模式&#xff0c;代码运行前需要通过鼠标点击设置起点和终点。 第一种模式直接输出最短路径 第二种模式输出最短路径的生成过程 第三种模式输出最短路径的生成过程和详细探索的过程 代码获取 gitee链接&#xff1a;https://gitee.c…

什么是脏读?不可重复读?幻读?如何解决?

什么是脏读&#xff1f;不可重复读&#xff1f;幻读&#xff1f;如何解决&#xff1f; 朋友最近面试美团&#xff0c;被面试官问到数据库的幻读问题&#xff0c;自己正好最近复习到这&#xff0c;做个笔记整理一下数据库的三大特征以及隔离级别。 一.先来回顾一下什么是事务&…

MySQL理论:脏读、不可重复读、幻读

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;MySQL理论&#xff1a;脏读、不可重复读、幻读 ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&#xf…