关于A*算法的研究
2015-12-03 21:31
369 查看
最近朋友写了一篇A*的博客,觉得很不错,这里我转载一下共同学习。
//定义格子的枚举类型
public enum GridType
{
Normal, Obstacle, Start, End
}
当频繁更换终点,或反复进行多次寻路时
需要清除计算过的格子的FGH值,并且清空开闭数组,不然就会寻错路。
//定义格子的枚举类型
public enum GridType
{
Normal, Obstacle, Start, End
}
定义格子类 public class Grid : IComparable { public int x; public int y; public int f;//总消耗 G+H public int g;//到起点消耗 public int h;//到终点消耗 public GridType type; public Grid fatherNode; //重写CompareTo 方法,用于取出F值最小的格子 public int CompareTo(object obj) { Grid grid = (Grid)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 Grid[,] grids; //开数组,闭数组,和寻路路径 public ArrayList openList; public ArrayList closeList; public ArrayList lujing; //假定起点和终点X,Y值 private int xStart = 2; private int yStart = 1; private int xEnd = 2; private int yEnd = 5; //初始化寻路格子 void Init() { grids = new Grid[row, col]; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { grids[i, j] = new Grid(); grids[i, j].x = i; grids[i, j].y = j; } } //起始点 grids[xStart, yStart].type = GridType.Start; grids[xStart, yStart].h = Manhattan(xStart, yStart); //结束点 grids[xEnd, yEnd].type = GridType.End; //设置障碍物 for (int i = 1; i <= 3; i++) { grids[i, 3].type = GridType.Obstacle; } closeList = new ArrayList(); lujing = new ArrayList(); openList = new ArrayList(); openList.Add(grids[xStart, yStart]); } int Manhattan(int x, int y) //用于计算到终点的H { return (int)(Mathf.Abs(xEnd - x) + Mathf.Abs(yEnd - y)) * 10; } void Start() { Init(); } void Update() { } //绘制格子便于观察 void DrawGrid() { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { Color color; if (grids[i, j].type == GridType.Start) { color = Color.green; } else if (grids[i, j].type == GridType.End) { 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.gray; } GUI.backgroundColor = color; GUI.Button(new Rect(j * size, i * size, size, size), FGH(grids[i, j])); } } } //显示F G H值 string FGH(Grid 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((Grid)openList[i])); } for (int i = 0; i < closeList.Count; i++) { GUI.Button(new Rect(i * size, (row + 2) * size, size, size),FGH((Grid)closeList[i])); } for (int i = 0; i < lujing.Count; i++) { GUI.Button(new Rect(i * size, (row + 3) * size, size, size),FGH((Grid)lujing[i])); } if (GUI.Button(new Rect(col * size, size, size, size), "NEXT")) { NextStep();//一步一步走 } } //获取每个格子的父节点,用于从终点往回查询路径 void getFatherNode(Grid grid) { if (grid.fatherNode != null) { lujing.Add(grid.fatherNode); getFatherNode(grid.fatherNode); // return getFatherNode(grid.fatherNode); } //else //lujing.Add(grid); //return grid; } void NextStep() { //当开数组为空时,寻路结束 if (openList.Count == 0) { print("Over!"); return; } //把F值最小的grid取出来 Grid grid = (Grid)openList[0]; //当寻到终点的时候 if (grid.type == GridType.End) { print("Over"); lujing.Add(grid); //打印路线 getFatherNode(grid); //因为路径是从后往前查找父节点,所以需要reverse则为正确路径 lujing.Reverse(); return; } //遍历处自己外的周围8个格子 for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { //如果只想遍历上下左右4个格子可加个条件 (i==0||j==0) if (!(i == 0 && j == 0)) { int x = grid.x + i; int y = grid.y + j; //不超过边界,不是障碍物,不在closeList数组里 if (x >= 0 && x < row && y >= 0 && y < col && grids[x, y].type != GridType.Obstacle && !closeList.Contains(grids[x, y])) { //计算G int g = grid.g + (int)(Mathf.Sqrt(Mathf.Abs(i) + Mathf.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 = Manhattan(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); //关闭的点从OPEN里移除 openList.Remove(grid); }最重要的需要注意一下:
当频繁更换终点,或反复进行多次寻路时
需要清除计算过的格子的FGH值,并且清空开闭数组,不然就会寻错路。
相关文章推荐
- Kinect结合Unity3D引擎开发体感游戏(一)
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 要慎用mysql的enum字段的原因
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析