A*最短路径算法

开放列表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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值