开放列表openList:所以F值最小节点的相邻非障碍节点放入其中
关闭列表closeList:用来存储F值最小的节点,最终会形成一条路径
当前节点currentV:正在比较F值的节点
当前节点的相邻非障碍节点adjancentMap:
Map类:初始化地图节点,存在障碍物的节点tag设置为1,其余为0,使用Dictionary存储节点信息
代码如下:
using UnityEngine;
using System.Collections.Generic;
public class Map
{
/// <summary>
/// 初始化地图
/// </summary>
/// <returns></returns>
public static Dictionary<string, MapInfo> GetMap()
{
Dictionary<string, MapInfo> temp = new Dictionary<string, MapInfo>();//tt = 1,表示不可走
for (int i = 0; i < 10; i++)
{
string s = "";
for (int j = 0; j < 10; j++)
{
int tt = 0;
if (i > 1 && i < 8 && j == 5)
{
tt = 1;
}
MapInfo mi = new MapInfo(i, j, tt);
temp.Add(i + "-" + j, mi);
s += mi.tag + " ";
}
Debug.Log(s);
}
return temp;
}
}
/// <summary>
/// 地图节点
/// </summary>
public class MapInfo
{
/// <summary>
/// X
/// </summary>
public int x;
/// <summary>
/// Y
/// </summary>
public int y;
/// <summary>
/// 是否可行走
/// </summary>
public int tag;
/// <summary>
/// G
/// </summary>
public int gValue;
/// <summary>
/// H
/// </summary>
public int hValue;
/// <summary>
/// 父节点
/// </summary>
public MapInfo parent;
public MapInfo()
{ }
/// <summary>
/// 构造
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="tag"></param>
public MapInfo(int x, int y,int tag)
{
this.x = x;
this.y = y;
this.tag = tag;
this.gValue = 0;
this.hValue = 0;
this.parent = null;
}
}
Astar类:用来实现A*最短寻,主要通过计算比较F值
主要代码如下:
using UnityEngine;
using System.Collections.Generic;
public class AStar : MonoBehaviour
{
/// <summary>
/// 地图
/// </summary>
Dictionary<string, MapInfo> map;
/// <summary>
/// open列表
/// </summary>
Dictionary<string, MapInfo> openList = new Dictionary<string, MapInfo>();
/// <summary>
/// close列表
/// </summary>
Dictionary<string, MapInfo> closeList = new Dictionary<string, MapInfo>();
/// <summary>
/// 当前点
/// </summary>
MapInfo currentV;
/// <summary>
/// 当前点的相邻节点列表
/// </summary>
Dictionary<string, MapInfo> adjancentMap;
// Use this for initialization
void Start ()
{
map = Map.GetMap();
MapInfo st = map["6-2"];//start
MapInfo end = map["6-8"];//end
FindPath(st, end);
}
/// <summary>
/// 寻路
/// </summary>
/// <param name="start">起点</param>
/// <param name="end">终点</param>
public void FindPath(MapInfo start,MapInfo end)
{
openList.Add(start.x + "-" + start.y, start);//开始节点加入开放列表中
do
{
currentV = GetTheLowestFrom(openList);//从开放列表中获取最小F值的节点
closeList.Add(currentV.x + "-" + currentV.y, currentV);//将F值最小的节点放入关闭列表
openList.Remove(currentV.x + "-" + currentV.y);//在开放列表中删去F值最小的节点
if (closeList.ContainsKey(end.x + "-" + end.y))//如果关闭列表中包含结束节点,则结束循环
{
Debug.Log("FindPath");
PrintThePath(end);
break;
}
adjancentMap = AdjacentList(currentV);//当前节点的四周相邻非障碍节点
foreach (string k in adjancentMap.Keys)//遍历相邻节点
{
if (closeList.ContainsKey(k))//如果关闭列表中存在,结束此次循环
{
continue;
}
if (!openList.ContainsKey(k))//如果开放列表中不存在,执行
{
adjancentMap[k].parent = currentV;//设置父节点
adjancentMap[k].gValue = currentV.gValue + 1;//G值加1
adjancentMap[k].hValue = GetManhattanDistance(adjancentMap[k], end);//获取H值
openList.Add(k, adjancentMap[k]);//添加至开放列表
}
else//如果开放列表中存在,执行
{
int g = currentV.gValue + 1;//G值加1
if (g < adjancentMap[k].gValue)//如果开放列表节点值
{
adjancentMap[k].gValue = g;//设置相邻节点的G值
adjancentMap[k].parent = currentV;//设置父节点
}
}
}
} while (openList.Count > 0);
}
/// <summary>
/// 获取openlist中F最小的节点
/// </summary>
/// <param name="open"></param>
/// <returns></returns>
//开放列表中的所以数据进行比较,返回F值最小的节点
public MapInfo GetTheLowestFrom(Dictionary<string, MapInfo> open)
{
MapInfo result=null;
int min = 10000;
foreach (MapInfo m in open.Values)
{
if (m.gValue + m.hValue < min)
{
result = m;
min = m.gValue + m.hValue;
}
}
return result;
}
/// <summary>
/// 获取当前节点的相邻节点
/// </summary>
/// <param name="m">当前节点</param>
/// <returns></returns>
public Dictionary<string, MapInfo> AdjacentList(MapInfo m)
{
Dictionary<string, MapInfo> resultDic=new Dictionary<string,MapInfo>();
//上下左右相邻非障碍节点加入字典中
string left = (m.x - 1) + "-" + m.y;
string right = (m.x + 1) + "-" + m.y;
string top = m.x + "-" + (m.y - 1);
string bot = m.x + "-" + (m.y + 1);
if (map.ContainsKey(left))
{
if(map[left].tag==0)
resultDic.Add(left, map[left]);
}
if (map.ContainsKey(right))
{
if (map[right].tag == 0)
resultDic.Add(right, map[right]);
}
if (map.ContainsKey(top))
{
if (map[top].tag == 0)
resultDic.Add(top, map[top]);
}
if (map.ContainsKey(bot))
{
if (map[bot].tag == 0)
resultDic.Add(bot, map[bot]);
}
return resultDic;
}
/// <summary>
/// 获得两个点的曼哈顿距离
/// 作为估值函数
/// </summary>
/// <param name="st"></param>
/// <param name="end"></param>
/// <returns></returns>
//返回该节点的H值(和end节点比较)
public int GetManhattanDistance(MapInfo st, MapInfo end)
{
int result = 0;
result = Mathf.Abs(st.x - end.x) + Mathf.Abs(st.y - end.y);
return result;
}
/// <summary>
/// 输出路径
/// </summary>
/// <param name="end">终点</param>
public void PrintThePath(MapInfo end)
{
string s = "";
MapInfo m = end;
//父节点不为空一直执行,打印出路径
while (m.parent != null)
{
s += "("+m.parent.x + "," + m.parent.y + ")->";
m = m.parent;
}
Debug.Log(s);
}
}
【参考】http://www.unitymanual.com/blog-13769-1078.html
【参考】http://www.unitymanual.com/home.php?mod=space&uid=11537&do=blog&id=110