——个人笔记
本人学习《Unity人工智能游戏开发》和Siki学院的《Unity游戏开发人工智能编程》的笔记
图中,绿色方格为起点,红色方格为终点,蓝色为障碍物。 第一次就会找到四周的9个方格并放入开启列表,并计算他们的F值。图的计算方式和步骤一样只是单位长度和代码中的不同。找最优F值就是C点,接着找C周围的方格,把C移除开启列表,加入关闭列表,接着找到现在最优F值是D点,按照步骤走就行,这里不详细说了。
public class Point
{
public Point Parent { get; set; }
public int X { get; set; }
public int Y { get; set; }
public float G { get; set; }//起点到该点的距离
public float H { get; set; }//预计该点到终点距离
public float F { get; set; }//最终距离F=G+H
public bool IsWall { get; set; }
//更新父方格和F值的方法
public void UpdateParent(Point parent, float g)
{
this.Parent = parent;
this.G = g;
F = G + H;
}
public Point(int x, int y)
{
this.X = x;
this.Y = y;
IsWall = false;
this.Parent = null;
}
}
private void InitMap()
{
for (int x = 0; x < mapWeight; x++)
{
for (int y = 0; y < mapHeight; y++)
{
map[x, y] = new Point(x, y);
}
}
map[4, 2].IsWall = true;
map[4, 3].IsWall = true;
map[4, 4].IsWall = true;
}
private void FindPath(Point start, Point end)
{
//开启列表
List openList = new List();
//关闭列表
List closeList = new List();
openList.Add(start);
while (openList.Count > 0)
{
//找开启列表中F值最小的方格
Point point = FindMinFofPoint(openList);
openList.Remove(point);
closeList.Add(point);
//获取C点周围的方格(不含障碍物)
List surroundList = GetSurroundPoints(point);
//把周围方格中已存在关闭列表的除去
PointsFilter(surroundList, closeList);
//计算他们的F值和设置父亲
foreach (Point surroundPoint in surroundList)
{
if (openList.IndexOf(surroundPoint) > -1)
{
//一个点的H值不变
//所以已存在列表中的方格,只要算G值更优就是F值更优
float nowG = Vector2.Distance(new Vector2(surroundPoint.X, surroundPoint.Y), new Vector2(point.X, point.Y)) + point.G;
if (nowG < surroundPoint.G)
{
//更新父方格和F值的方法
surroundPoint.UpdateParent(point, nowG);
}
}
else
{
surroundPoint.Parent = point;
//计算F值
CalF(surroundPoint, end);
openList.Add(surroundPoint);
}
}
//判断一下是否是终点
if (openList.IndexOf(end) > -1)
{
break;
}
}
}
//找在openlist中F值最小的
private Point FindMinFofPoint(List openList)
{
float f = float.MaxValue;
Point temp = null;
foreach (Point p in openList)
{
if (p.F < f)
{
temp = p;
f = p.F;
}
}
return temp;
}
//获取周围所有走的格子
private List GetSurroundPoints(Point point)
{
List list = new List();
Point up = null, down = null, right = null, left = null;
if (point.Y > 0)
{
down = map[point.X, point.Y - 1];
if (!down.IsWall)
{
list.Add(down);
}
}
if (point.Y < mapHeight - 1)
{
up = map[point.X, point.Y + 1];
if (!up.IsWall)
{
list.Add(up);
}
}
if (point.X > 0)
{
left = map[point.X - 1, point.Y];
if (!left.IsWall)
{
list.Add(left);
if (up != null && up.IsWall == false&& !map[point.X - 1, point.Y + 1].IsWall)
list.Add(map[point.X - 1, point.Y + 1]);//lu
if (down != null && !down.IsWall&& !map[point.X - 1, point.Y - 1].IsWall)
list.Add(map[point.X - 1, point.Y - 1]);//ld
}
}
if (point.X < mapWeight - 1)
{
right = map[point.X + 1, point.Y];
if (!right.IsWall)
{
list.Add(right);
if (up != null && !up.IsWall&&!map[point.X + 1, point.Y + 1].IsWall)
list.Add(map[point.X + 1, point.Y + 1]);//ru
if (down != null && !down.IsWall&&!map[point.X + 1, point.Y - 1].IsWall)
list.Add(map[point.X + 1, point.Y - 1]);//rd
}
}
return list;
}
//除去周围可行格子中已经存在closelist的格子
private void PointsFilter(List src, List closeList)
{
foreach (Point p in closeList)
{
if (src.IndexOf(p) > -1)
{
src.Remove(p);
}
}
}
//计算F,G,H值
private void CalF(Point now, Point end)
{
float h = Mathf.Abs(now.X - end.X) + Mathf.Abs(now.Y - end.Y);
float g = 0;
if (now.Parent != null)
{
g = Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(now.Parent.X, now.Parent.Y))+now.Parent.G;
}
float f = h + g;
now.H = h;
now.G = g;
now.F = f;
}