首先非常感谢唐老师的课程,讲的非常好
添加链接描述
-
三个变量:
G值 = 父节点的G值 + 父节点到当前点的移动代价
(父节点的G是0,如果斜着走就是根号2,直着走就是1)H值 = 当前点到结束点的曼哈顿距离
寻路消耗公式 F:=G+H
-
还有两个列表
开放列表: 吧当前所有可以走的节点都放进开放列表
关闭列表:每一次走过一个节点之后都把这个节点放到关闭列表里面 -
具体步骤
a、将开始点记录为当前点P
b、将当前点P放入关闭列表
c、搜寻点P所有邻近点,假如某邻近点既没有在开放列表或关闭列表里面,则计算出该邻近点的F值,并设父节点为P,然后将其放入开放列表
d、判断开放列表是否已经空了,如果没有说明在达到结束点前已经找完了所有可能的路径点,寻路失败,算法结束;否则继续。
e、从开放列表拿出一个F值最小的点,作为寻路路径的下一步。
f、判断该点是否为结束点,如果是,则寻路成功,算法结束;否则继续。
g、将该点设为当前点P,跳回步骤c。 -
找出路径
从终点节点开始,找其父节点,顺藤摸瓜,一直找到起始节点,这便是一条路径
总结:
- A*并不是最短路,他是以最快的速度找到通往目标的路径
- A*在死路情况下会找遍所有点
一下跟着写的代码,一个小demon:、
优化的地方:
- 本demon是用的list存储,list很多操作个比较耗,可以用红黑树(堆)来优化排序过程
- 判断是不是在开放或者关闭列表中,list会遍历所有,我们可以在节点里加一个属性做标记
格子类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AStarNode
{
//格子对象坐标
public int x;
public int y;
//寻路消耗
public float f;
//距离起点距离
public float g;
//距离终点的距离
public float h;
//父对象
public AStarNode fataher;
//格子类型
public ENodeType type;
//构造函数,传入格子坐标和格子类型
public AStarNode(int x,int y,ENodeType type)
{
this.x = x;
this.y = y;
this.type = type;
}
}
/// <summary>
/// 格子类型
/// </summary>
public enum ENodeType
{
Walk,
Stop,
}
管理类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AStartMgr
{
#region 构造单例模式
private AStartMgr() {
}
public static AStartMgr Instance
{
get
{
return Nested._instance;
}
}
private class Nested
{
internal static readonly AStartMgr _instance = new AStartMgr();
}
#endregion
//地图相关所有格子的对象容器
private AStarNode[,] nodes;
public AStarNode[,] Nodes
{
get {
return nodes; }
}
//开启列表
private List<AStarNode> openList=new List<AStarNode>();
//关闭列表
private List<AStarNode> closeList = new List<AStarNode>();
//地图的宽高
private int mapW;
private int mapH;
/// <summary>
/// 初始化地图信息
/// </summary>
/// <param name="w"></param>
/// <param name="h"></param>
public void InitMapInfo(int w,int h)
{
this.mapW = w;
this.mapH = h;
nodes = new AStarNode[w, h];
for(int i = 0; i < w; i++