游戏AI实现-寻路算法(Dijkstra)

news/2024/12/19 17:49:14/

戴克斯特拉算法(英语:Dijkstra's algorithm),又称迪杰斯特拉算法、Dijkstra算法,是由荷兰计算机科学家艾兹赫尔·戴克斯特拉在1956年发现的算法。

算法过程:

1.首先设置开始节点的成本值为0,并将开始节点放入检测列表中。

2.将检测列表中的所有点按到目标点所需的成本值排序,选择成本最小的节点作为当前节点,并将其移出检测列表。

3.将当前点周围的点中不包含在检测列表中的点加入到检测列表,将周围点加入到已检测列表中。

4.更新检测列表中的节点到当前节点的成本值。

5.重复2,3,4直到找到目标点。

代码实现:

public class Dijkstra : FindPathAlgorithm
{public Dijkstra(int[,] mapData, int xCount, int zCount) : base(mapData, xCount, zCount){}public override List<Vector2Int> FindPath(Vector2Int startPos, Vector2Int goalPos){DataNode dataNode = this.DijkstraFind(startPos, goalPos);if (dataNode == null){Debug.LogError("寻路有误,请检查参数是否正确");return null;}return Utils.GetPath(dataNode);}DataNode DijkstraFind(Vector2Int startPos, Vector2Int goalPos){//存储要检测的点List<DataNode> frontier = new List<DataNode>();//存储已经检测的点List<Vector2Int> reached = new List<Vector2Int>();DataNode startNode = new DataNode(startPos, null);startNode.gCost = 0;frontier.Add(startNode);reached.Add(startPos);while (frontier.Count > 0){DataNode currentNode = GetLowestgCostNode(frontier);frontier.Remove(currentNode);if (currentNode.pos == goalPos){Debug.Log("完成!!!");return new DataNode(goalPos, currentNode.parent);}List<DataNode> neighbors = GetNeighbors(currentNode.pos, reached);foreach (DataNode neighbourNode in neighbors){if (!frontier.Contains(neighbourNode)){neighbourNode.parent = currentNode;frontier.Add(neighbourNode);}reached.Add(neighbourNode.pos);}this.UpdateCost(frontier, currentNode);}return null;}//更新成本值void UpdateCost(List<DataNode> nodes, DataNode currentNode){for (int i = 0; i < nodes.Count; i++){int newCost = currentNode.gCost + CalculateDistanceCost(nodes[i].pos, currentNode.pos);if (nodes[i].gCost > newCost){nodes[i].gCost = newCost;}}}List<DataNode> GetNeighbors(Vector2Int current, List<Vector2Int> reached){List<DataNode> neighbors = new List<DataNode>();for (int i = 0; i < Utils.pointDir.Count; i++){Vector2Int neighbor = current + Utils.pointDir[i];if (this.IsCanAdd(neighbor, reached)){neighbors.Add(new DataNode(neighbor, null));}}return neighbors;}bool IsCanAdd(Vector2Int current, List<Vector2Int> reached){if (reached.Contains(current))return false;if (current.x >= 0 && current.y >= 0 && current.x < MapData.m_MapData.GetLength(1) && current.y < MapData.m_MapData.GetLength(0)){//如果是障碍物,则不能被Addif (MapData.m_MapData[current.y, current.x] == 1){return false;}return true;}return false;}private int CalculateDistanceCost(Vector2Int a, Vector2Int b){return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);}private DataNode GetLowestgCostNode(List<DataNode> pathNodeList){DataNode lowestFCostNode = pathNodeList[0];for (int i = 1; i < pathNodeList.Count; i++){if (pathNodeList[i].gCost < lowestFCostNode.gCost){lowestFCostNode = pathNodeList[i];}}return lowestFCostNode;}
}

结果:

参考链接:

Pathfinding in Unity - Part3: Dijkstra Algorithm Theory (youtube.com)

Pathfinding in Unity - Part4: Dijkstra Algorithm Implementation (youtube.com)

How Dijkstra's Algorithm Works (youtube.com)

戴克斯特拉算法 - 维基百科,自由的百科全书 (wikipedia.org)


http://www.ppmy.cn/news/1556443.html

相关文章

STM32 485发数乱码怎么回事

STM32通过RS485发送数据时出现乱码,可能的原因有多种。以下是一些常见的原因及其相应的解决方法: 波特率不匹配: 检查STM32的串口波特率设置是否与接收端(如串口助手或另一设备)的波特率设置一致。波特率决定了串口数据传输的速度,如果发送和接收两端的波特率不一致,就会…

HTTP 响应状态码对照表

HTTP 响应状态码用于表示服务器对客户端请求的处理结果。状态码分为五个类别&#xff0c;分别为&#xff1a; 1. 1xx&#xff08;信息性状态码&#xff09; 这些状态码表示请求已被接受&#xff0c;正在继续处理。 100 Continue&#xff1a;服务器已接收到请求头&#xff0c…

白平衡和色彩偏移使用(富士)

一富士相机不同白平衡的使用思路 1 如果不会用&#xff0c;就用白色优先&#xff0c;我们一般都是拍人&#xff0c;用白色优先皮肤就不会偏色 &#xff0c;不会让环境影响太大 2不用自动 3 环境优先&#xff1a; 和白色优先相反 白色优先让人变白少受环境影响&#xff0c;…

一个异地访问局域网OA,ERP网站,远程桌面,异地游戏联机的方式

一、概述 本软件能够实现异地之间的P2P直连穿透&#xff0c;可无需通过中继服务器也可提供服务。本产品采用的算法可在包括对称型NAT在内的大多数网络环境实现P2P通讯。因在数据传无需中继服务器作为中转&#xff0c;故此具有强劲的传输速度和安全性。数据在传输过程中采用各类…

电脑开机提示error loading operating system怎么修复?

前一天电脑还能正常运行&#xff0c;但今天启动时却显示“Error loading operating system”&#xff08;加载操作系统错误&#xff09;。我已经仔细检查了硬盘、接线、内存、CPU和电源&#xff0c;确认这些硬件都没有问题。硬盘在其他电脑上可以正常使用&#xff0c;说明不是硬…

如何解决手机,电脑等工作室同ip关联问题

在现代工作室中&#xff0c;手机和电脑等设备的网络连接问题成为一个日益严重的难题。众多设备常常因共享同一IP地址而遭遇各种限制和封禁&#xff0c;尤其是在进行矩阵运营、游戏打金搬砖、试玩等多种网络活动时&#xff0c;IP关联问题更是成为影响工作效率和收益的关键因素。…

【JavaWeb后端学习笔记】WebSocket通信

WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c;并进行双向数据传输。 主要应用场景&#xff1a;视频弹幕、网页聊天、体育实况更新、股票基金报价实时…

Unity屏幕截图、区域截图、读取图片、WebGL长截屏并下载到本地jpg

Unity屏幕截图、区域截图、读取图片、WebGL长截屏并下载到本地jpg 一、全屏截图并保存到StreamingAssets路径下 Texture2D screenShot;//保存截取的纹理public Image image; //显示截屏的Imagepublic void Jietu(){StartCoroutine(ScrrenCapture(new Rect(0, 0, Screen.width…