您的位置:首页 > 移动开发 > Unity3D

unityA* 寻路算法,使用OnGUI()函数

2016-10-24 18:35 381 查看
A*(A-Star)算法是一种静态路网中求解最短路最有效的直接搜索方法。
注意是最有效的直接搜索算法。之后涌现了很多预处理算法(ALT,CH,HL等等),在线查询效率是A*算法的数千甚至上万倍。
公式表示为: f(n)=g(n)+h(n)
其中 f(n) 是从初始点经由节点n到目标点的估价函数,
g(n) 是在状态空间中从初始节点到n节点的实际代价,
h(n) 是从n到目标节点最佳路径的估计代价。
保证找到最短路径(最优解的)条件,关键在于估价函数f(n)的选取:
估价值h(n)<= n到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到最优解。并且如果h(n)=d(n),即距离估计h(n)等于最短距离,那么搜索将严格沿着最短路径进行, 此时的搜索效率是最高的。
如果 估价值>实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

/// <summary>
/// 格子类型
/// </summary>
public enum GridType
{
Normal,
Obstacle,
Start,
End
}
/// <summary>
/// 为了实现格子的排序,继承ICompareable
/// </summary>
public class MapGrid:IComparable
{
/// <summary>
/// 记录坐标
/// </summary>
public int x;
public int y;

/// <summary>
/// 总消耗
/// </summary>
public int f;
/// <summary>
/// 当前到起点的消耗
/// </summary>
public int g;
//当前到终点的消耗
public int h;

public GridType type;
/// <summary>
/// 父节点
/// </summary>
public MapGrid fatherNode;

/// <summary>
/// 排序
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public int CompareTo(object obj)
{
MapGrid grid = (MapGrid)obj;
if(this .f <grid .f)
{
//升序
return -1;
}
if(this .f >grid .f)
{
//降序
return 1;
}
return 0;
}
}

public class AStar : MonoBehaviour {

public int row = 5;
public int col = 10;
//格子大小
public int size = 70;

public MapGrid[,] grids;
public ArrayList openList;
public ArrayList closeList;

//开始和结束的位置
private int xStart = 2;
private int yStart = 1;
private int xEnd = 2;
private int yEnd = 5;

private Stack<string> fatherNodeLocation;

void Init()
{
grids = new MapGrid[row, col];

for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
//初始化格子,记录格子的坐标
grids[i, j] = new MapGrid();
grids[i, j].x = i;
grids[i, j].y = j;
}
}
//开始点和其h的值
grids[xStart, yStart].type = GridType.Start;
grids[xStart, yStart].h = Manhatten(xStart, yStart);

grids[xEnd, yEnd].type = GridType.End;

fatherNodeLocation = new Stack<string>();

for (int i = 1; i <= 3; i++)
{
grids[i, 3].type = GridType.Obstacle;
}

openList = new ArrayList();
openList.Add(grids[xStart, yStart]);

closeList = new ArrayList();
}

private int Manhatten(int x,int y)
{
return (int)(Math.Abs(xEnd - x) + Math.Abs(yEnd - y)) * 10;
}

void Start()
{
Init();
}

void DrawGrid()
{
for (int i = 0; i < row ; i++)
{
for (int j = 0; j < col ; j++)
{
Color color = Color.yellow;
if(grids [i,j].type ==GridType .Start )
{
color = Color.green;
}
else if(grids [i,j].type ==GridType .Start )
{
color = Color.red;
}
else if (grids [i,j].type ==GridType .Obstacle )
{
color = Color.blue;
}
else if(closeList .Contains (grids [i,j]))
{
color = Color.yellow;
}
else
{
color = Color.grey;
}

GUI.backgroundColor = color;
GUI.Button(new Rect(j * size, i * size, size, size), FGH(grids[i, j]));
}
}
}

private string FGH(MapGrid grid)
{
string str = "F" + grid.f + "\n";
str += "G" + grid.g + "\n";
str += "H" + grid.h + "\n";
str += "(" + grid.x + "," + grid.y + ")";
return str;
}

void OnGUI()
{
DrawGrid();
for (int i = 0; i < openList .Count ; i++)
{
GUI.Button(new Rect(i * size, (row + 1) * size, size, size), FGH((MapGrid)openList[i]));
}

for (int j = 0; j < closeList .Count ; j++)
{
GUI.Button(new Rect(j * size, (row + 1) * size, size, size), FGH((MapGrid)closeList[j]));
}

if(GUI .Button (new Rect (col *size ,size ,size ,size ),"next"))
{
NextStep();
}
}

private void NextStep()
{
if (openList.Count == 0)
{
print("over !");
return;
}

MapGrid grid=(MapGrid )openList [0];
if(grid.type ==GridType .End )
{
print ("find");
ShowFatherNode(grid);
return ;
}

for (int i = -1; i <=1; i++)
{
for (int j = -1; j <=1; j++)
{
int x = grid.x + i;
int y = grid.y + j;

if(x>=0&&x<row &&y>=0&&y<col&&
grids [x,y].type !=GridType .Obstacle &&
!closeList .Contains (grids[x,y]))
{
int g = grid.g + (int)(Math.Sqrt((Math.Abs(i) + Math.Abs(j))) * 10);
if(grids[x,y].g==0||grids [x,y].g>g)
{
grids[x, y].g = g;
grids[x, y].fatherNode = grid;
}

grids[x, y].h = Manhatten(x, y);
grids[x, y].f = grids[x, y].g + grids[x, y].h;

if(!openList .Contains (grids[x,y]))
{
openList.Add(grids[x, y]);
}

openList.Sort();
}
}
}

closeList.Add(grid);
openList.Remove(grid);
}

private void ShowFatherNode(MapGrid grid)
{
if(grid.fatherNode !=null )
{
string str = grid.fatherNode.x + "," + grid.fatherNode.y;
fatherNodeLocation.Push(str);
ShowFatherNode(grid.fatherNode);
}

if(fatherNodeLocation .Count !=0)
{
print(fatherNodeLocation.Pop());
}
}
}


原文链接:点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: