【Unity】A*算法

一、A*算法

前提:制作好虚拟地图MAP(以二维数组为例(三维基本一样只是每次搜索的次数会比二维多)),虚拟地图假设以char[,]来定义,里面每个字符都是已定好权值意义的字符,或者你也可以直接用int[,]来定义二维数组,直接保存每个坐标的权值。而这个虚拟地图如何创建的,是要根据实际场景来创建的,即二维数组每个元素都是对应着实际场景上的坐标上的物体的,权值也是视其物体而言,比方说它是一个障碍物,那么权值就应该怎么样之类的意思。本例以权值小的为最高优先权,权值越小即代价越小。

虚拟地图准备好了后,还需要一个数据结构体来存储每个节点(地图节点)的信息,如下:

//节点数据结构体
public class PointData
{
    public Point point;
    public double g, h;
    public PointData parent;//上一个节点(也就是从哪个节点走到该节点的)

    public PointData(Point point,double g,double h,PointData parent)
    {
        this.point = point; //当前节点的坐标(x,y)
        this.g = g; //从起点到达该节点的代价(真实的、几乎准确的)
        this.h = h; //该节点到终点的代价(虚拟的、不准确的)
        this.parent = parent;
    }
    //总代价(即g+h)
    public double F()
    {
        return g + h;
    }
}

A*步骤:(前提已经制作好虚拟地图MAP, char[,]类型 我们是通过它来判断节点的权值和是否可走之类的)

1.确定起点S和终点E,确保S和E不是同一个位置

2.定义一个开启列表list并将起点S的PointData节点数据加入开启列表list(后面说的list就是开启列表)。

节点S的PointData =  new PointData(new Point(S.x,S.y), 0, 0, null);

3. 开始一个循环,结束条件为遍历到了终点E 或者 list已经没有元素, list没有元素意味着几乎全部节点都遍历了都无法到达终点

3.1 取出list中 F最小的节点 作为当前节点

3.2 将当前节点对应的MAP上的元素char设置为visited(已访问的意思)

3.3 遍历当前节点周围8个节点,以当前节点的上方节点为例,若它是终点,那么就可以直接记录一下当前节点退出即可,否则,再判断它是不是已存放入开启列表list,若是,将目前计算出的上方节点g值(g=当前节点.G+当前节点到上方节点的距离)与之前计算出的上方节点g'值(g'=上方节点的父节点的G值 + 上方节点的父节点与上方节点的距离)进行比对,若g<g' 那么修改其上方节点的G值=g,再将上方节点的parent改为当前节点;若还没有存放入开启列表,则直接new一个该上方节点对应的节点数据PointData,其g值是当前节点的G值+当前节点与上方节点的距离,h值是上方节点与终点的距离+上方节点对应的权值(即Map[上方节点point.x,point.y]),parent设置为当前节点。

3.4 遍历完8个节点后从list开启列表移除当前节点(意味着该节点的搜索已经完毕)

之后就是不断地重复3.1,3.2,3.3,3.4这个过程,直至找到终点,一直没找到的话 开启列表就没元素了,因为所有元素(可以走的)都会被标记上visited,上面我少些了一些东西,比方说,遍历周围8个节点这里,你应该要按照实际情况,判断哪些节点是可以继续遍历的,是可以继续走下去的,才把它放入开启列表。

3.5 若找到终点,上面也说了会用一个变量保存终点前一个节点dataPoint,之后根据dataPoint.parent不断地 找到父节点的方式将所有路径节点找出保存入一个列表,然后就可以返回一个A*算出的最短路径点列表给外面使用了。

当然,A*算法也可能会出错,在找出路径点后,如果不放心可以加一些判断是不是真的符合实际情况。

如果哪方面不会的话可以在评论区提问。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值