百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

使用这个算法我可以实现英雄联盟里英雄的走位|Java 开发实战

liebian365 2025-03-04 12:59 15 浏览 0 评论


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

基本概念

  • 首先在大学我们遇到最多的算法Dijkstra、Floyd、广度搜索、深度搜索。关于这些算法我们以后再慢慢的研究,今天的重点在A*算法上。A*算法是一种启发式算法。与上述几种算法不同的是A*算法在考虑起始节点的同时还会考虑到目标节点的代价。
  • 在A*算法中我们给每个节点都定义一些属性。最基本的就是下文提到的三基数-这里的三基数是我自己定义的一个名词。什么叫启发式就是在探索路径的时候既要选择里起始点最近也要考虑到里目标节点的消费问题。

三基值

  • 上面的一些概念可能会使你很模糊,这里我们直接看定义。

F=G+H : 表示一个节点的总消费值;换句话说就是离起始节点和目标节点距离的总和 G : 表示该从其实节点到该节点的消费值; H : 表示从该节点到目标节点的消费值;(这里注意一下,这里的消费值其实是一个预估值,因为我们无法判断到目标节点的具体路径,这个H值得获取本文会提供三种方法,其中使用最广泛的是曼哈顿距离)


三基值计算

常规约定

  • 在方格地图中我们约定横向或者纵向单位消费为10
  • 在方格地图中斜向单位消费为14
  • 在墙(墙、河流等不可经过的节点统称)角我们是不可以斜着穿越的,这是常识。实际中我们每个移动的物体都是有自己的空间的,如下图这样S-->E的过程S'已经占用了Q(墙)的领域了。

  • 在非墙角地方根据自己需求可以设定可穿越,也可以设定不可穿越。本文设定是可穿越的。


G值计算

  • 三基数在上面定义中我们已经列出了其计算公式,可能有的人看的不是很明白。我们这里详细解释一下
  • 首先我们先看三基值中的G值,G表示该从其实节点到该节点的消费值,这句话的意思从开始节点移动到当前节点需要的实际的消费,这里是需要考虑到不可经过的节点的。如下图S表示起始点,E表示目标节点,N表示当前节点,黑色的表示墙(不可经过的节点集合)。我们规定在墙角是无法斜着穿过去,在其他地方是可以斜着经过的。有了这个约定,我们可以算出图3中 S--->N1 消费10, S--->N2消费14,因为从S到N2不是处于墙角。 途中N3--->N4就是明显的墙角。所以N3--->N4消费是20。

H值计算方式

  • H值和G值作用相反,H值是预估到目标节点的消费值。
-  首先G是针对其实点的,而H值是针对目标节点的
-  其次G值是真实值,而H值是预估值
-  最后G值得计算是允许斜线行走的,但是H值计算只能横向和纵向的结合
  • 下图(图4中从N2--->E点的H=40+10),其中40部分已经穿墙了。这里因为是预估值所以不考虑墙的存在。到这里我们基本的定义已经结束了

集合列表

  • 在我们A*寻路的过程中,我们需要用到两个集合,一个我们成为开放集合(OpenList),另外一个我们称之为闭合集合(ClosedList)。
  • 举个例子我们去超市购物,我们都会推个手推车,把喜欢的东西放进购物车里。最后结算的时候或者是中途我们会选择价格更实惠的东西替代我们已经选择的同等产品
  • 在A*中我们也是这样,openList就相当于购物车,我们会将见到的喜欢的物品加入购物车,但是加入购物车并不一定最后会买,在A*中,我们会将节点周围可用的节点加入openList,但是并不一定最后需要。在openList添加的过程我们会慢慢用'更实惠'的节点代替已经选择的相同的节点。在超市最后放到我们自己的包里才是最后我们要带回家的东西。在A*算法中加到closedList中才是我们最后的东西。

寻路解析

本小节图片来源以下文章。其中思想参考源以下文章

blog.csdn.net/zgwangbo/ar… blog.csdn.net/hitwhylz/ar…

  • 经过上面的介绍我们了解了A*中我们一些约定的定义,理解上面这些定义的基础上我们下面的流程会很易懂。

初始地图

  • 如图5,地图上蓝色方格表示墙,关于墙的定义上面已经解释过了。左边青色的表示S(起始节点),右边的红色节点表示我们的目标节点。小圆点表示从S到E的最有路径之一。从图5我们可以看出我们在墙角没有斜走,而在其他路段上我们选择斜着走了。下面介绍节点就以图5中的坐标为准。比如起始节点我们就称之为(2,3)。
    • 蓝色方格表示不可经过方格
    • 青色的边框的方格表示已经加入openList
    • 高亮显示的边框表示添加在closedList
    • 青色表示其实节点
    • 红色表示目标节点


递归寻走

  • 首先我们常规的寻路是不可能出现首尾相同的情况。但是项目中得处理这种情况,如果其实节点和目标节点是地图上的统一节点,那么我们的路径就是当前节点。
  • 选择当前节点周围可用的节点,如果不在openList集合中则分别计算三基数的值并且加入到openList集合中,计算三基数的同事将待加入openList的节点的父节点设置为当前节点。
  • 如果已经存在openList集合中且结合中的G值大于当前节点(周围节点之一)的G值,则将当前节点更新到openList集合中。否则不加入也不更新。
  • 周围节点选择完之后我们就把该节点(起始节点)加入closedList中,然后从openList中选择F值最小的节点,在继续重复上面三步骤。

图示流程

  • 按照图5中我们可以获得起始节点(2,3)的周围节点列表如图6。并逐个分析是否该加入openList中。


  • 通过比较我们发现目前周围的八个节点全部有效且全不在openList中,那么我们就全部加入并计算三基数的值,并设置他们的父节点为(2,3)。如图7


  • 从图7中我们可以看出在起始节点(2,3)周围(3,3)这个节点的F值此时在openList中最小,所以此时我们将(2,3)移除openList并将(2,3)加入到closedList中。此时(2,3)由高亮方格显示表示加入closedList集合,
  • (2,3)节点就算是结束了他的使命了,加入了closedList集合中的节点我们将不会再去考虑,我们可以认为加入到closedList集合中的点已经成墙了。那么下面我们从openList中选取F值最小(3,3)为新的起始节点,开始重复上面的流程,但是我们发现(3,3)的右上、正右、右下都是墙,还有正左(2,3)在closedList集合中。这四点我们是不用考虑的。那么只剩下

(2,2),(3,2),(2,4),(3,4)这四个点。但是这四个点恰巧有全部在openList中。依照上面的流程我们得以此比较这四个点和openList集合中对应的点的G值谁大谁小。就一个原则谁小留谁。由图8我们可以知道,新获得的这四个点的G值均大于openlist里对应的点的G值,所以我们这里放弃这四个点。他们没有被我们喜欢,我们抛弃这些点。这一轮结束我们将(3,3)加入到closedList集合中。如果新节点G值小于对应的openList中的点的G值得话,我们就要更新openList集合中的对应的那个点。所谓的更新就是将新节点替换原来那个节点。注意此时新节点和openList对应的那个点出了三基数不同,还有父节点也不同了。

  • 这里需要解释下为什么新节点的G值都会加10呢,那是因为我们最起始的节点是(2,3),而此时的起始节点是(3,3),比如我们算(2,2)G值得时候实际上是(2,3)--->(3,3)--->(2,2)整个过程的G值。所以是10+14。


  • 由图9我们能够看到此时我们openList中最小F值应该是(3,4),下面的步骤就是一直重复。


  • 直到我们的目标节点成为起始节点就表示循环结束,这个时候我们通过我们的目标节点在closedlist总通过父节点就能反向回去获得整条路径了。

不足之处

  • 关键在于估价函数h(n)的选取:估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解

源码

源码地址:
https://gitee.com/zxhGroup/Algorithm

[//]: A译文: blog.csdn.net/coutamg/art… *[//]:其他最小路径算法:
www.cnblogs.com/biyeymyhjob… *[//]:启发式算法:
baike.baidu.com/item/%E5%90…

作者:zxhtom
链接:
https://juejin.cn/post/6971217122210889759

相关推荐

精品博文嵌入式6410中蓝牙的使用

BluetoothUSB适配器拥有一个BluetoothCSR芯片组,并使用USB传输器来传输HCI数据分组。因此,LinuxUSB层、BlueZUSB传输器驱动程序以及B...

win10跟这台计算机连接的前一个usb设备工作不正常怎么办?

前几天小编闲来无事就跑到网站底下查看粉丝朋友给小编我留言询问的问题,还真的就给小编看到一个问题,那就是win10跟这台计算机连接的一个usb设备运行不正常怎么办,其实这个问题的解决方法时十分简单的,接...

制作成本上千元的键盘,厉害在哪?

这是稚晖君亲自写的开源资料!下方超长超详细教程预警!!全文导航:项目简介、项目原理说明、硬件说明、软件说明项目简介瀚文智能键盘是一把我为自己设计的——多功能、模块化机械键盘。键盘使用模块化设计。左侧的...

E-Marker芯片,USB数据线的“性能中枢”?

根据线缆行业的研究数据,在2019年搭载Type-C接口的设备出货量已达到20亿台,其中80%的笔记本电脑和台式电脑采用Type-C接口,50%的智能手机和平板电脑也使用Type-C接口。我们都知道,...

ZQWL-USBCANFD二次开发通讯协议V1.04

修订历史:1.功能介绍1.1型号说明本文档适用以下型号:  ZQWL-CAN(FD)系列产品,USB通讯采用CDC类实现,可以在PC机上虚拟出一个串口,串口参数N,8,1格式,波特率可以根据需要设置(...

win10系统无法识别usb设备怎么办(win10不能识别usb)

从驱动入手,那么win10系统无法识别usb设备怎么办呢?今天就为大家分享win10系统无法识别usb设备的解决方法。1、右键选择设备管理器,如图:  2、点击更新驱动程序,如图:  3、选择浏览...

微软七月Win8.1可选补丁有内涵,含大量修复

IT之家(www.ithome.com):微软七月Win8.1可选补丁有内涵,含大量修复昨日,微软如期为Win7、Win8.1发布7月份安全更新,累计为6枚安全补丁,分别修复总计29枚安全漏洞,其中2...

如何从零开始做一个 USB 键盘?(怎么制作usb)

分两种情况:1、做一个真正的USB键盘,这种设计基本上不涉及大量的软件编码。2、做一个模拟的USB键盘,实际上可以没有按键功能,这种的需要考虑大量的软件编码,实际上是一个单片机。第一种设计:买现成的U...

电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题

电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题注意:有些方法会清除USB设备里的数据,请谨慎操作,如果不想丢失数据,可以先连接到其他电脑,看能否将数据复制出来,或者用一些数据恢复软件去扫...

未知usb设备设备描述符请求失败怎么解决

出现未知daousb设备设备描述符请求失du败解决办zhi法如下:1、按下Windows+R打开【运行】;2、在版本运行的权限输入框中输入:services.msc按下回车键打开【服务】;2、在服务...

读《飘》47章20(飘每章概括)

AndAhwouldn'tleaveMissEllen'sgrandchildrenfornotrashystep-patobringup,never.Here,Ah...

英翻中 消失的过去 37(消失的英文怎么说?)

翻译(三十七):消失的过去/茱迪o皮考特VanishingActs/JodiPicoult”我能做什么?“直到听到了狄利亚轻柔的声音,我才意识到她已经在厨房里站了好一会儿了。当她说话的时候,...

RabbitMQ 延迟消息实战(rabbitmq如何保证消息不被重复消费)

现实生活中有一些场景需要延迟或在特定时间发送消息,例如智能热水器需要30分钟后打开,未支付的订单或发送短信、电子邮件和推送通知下午2:00开始的促销活动。RabbitMQ本身没有直接支持延迟...

Java对象拷贝原理剖析及最佳实践(java对象拷贝方法)

作者:宁海翔1前言对象拷贝,是我们在开发过程中,绕不开的过程,既存在于Po、Dto、Do、Vo各个表现层数据的转换,也存在于系统交互如序列化、反序列化。Java对象拷贝分为深拷贝和浅拷贝,目前常用的...

如何将 Qt 3D 渲染与 Qt Quick 2D 元素结合创建太阳系行星元素?

Qt组件推荐:QtitanRibbon:遵循MicrosoftRibbonUIParadigmforQt技术的RibbonUI组件,致力于为Windows、Linux和MacOSX提...

取消回复欢迎 发表评论: