A*迷宫寻路算法
在A*算法里面,有两个概念,一个是已经走过的步数G,一个是走到目标需要的步数H。
例如我从起点S出发,S的G就是0了。往右走一格到T,那T的G就是0+1=1。再走一步,就是1+1=2。反正从G=g的点出发,走一格后的G就是g+1。
H也很好算。例如目标是(m,n),当然格是(u,v),那么H=abs(u-m)+abs(v-n)
算出G和H之后,我们要算一个F,简单的话,F=G+H。实际有些地方会偏重G或H,可以加个权值,这个需要根据实际情况判断。我们这里直接令F=G+H。
根据这样的定义,我们可以看到,如果F越小,则说明走过的步数较少,而且离目标较近,是一个比较好的点。
A*寻路算法就是基于上面的理论,其过程如下:
(1)把起点S放到一个open_list里面。
(2)对open_list进行排序,找出F最小的格子。
(3)取出F最小的格子,放到close_list里面。
(4)找到当前格子相邻的格子,计算它的F。
1)如果这个格子在close_list里面,不用管,跳过。
2)如果这个格子在open_list里面,而且F比open_list里的值小,更新open_list里的值。
3)如果这个格子不在open_list里面,直接加入到open_list。
(5)重复第2步。
实现的代码如下:
/// <summary>
/// 计算路径
/// </summary>
public void CalcPath()
{
PosNode pn0 = new PosNode(1, 1, 0, null, ROW, COL);
open_list.Add(pn0);
bool finish = false;
while (open_list.Count != 0)
{
open_list.Sort();
PosNode now = open_list[open_list.Count - 1];
open_list.RemoveAt(open_list.Count - 1);
close_dict.Add(now, 0);
PosNode[] nextto = new PosNode[4];
nextto[0] = new PosNode(now.row - 1, now.col, now.G + 1, now, ROW, COL);
nextto[1] = new PosNode(now.row + 1, now.col, now.G + 1, now, ROW, COL);
nextto[2] = new PosNode(now.row, now.col - 1, now.G + 1, now, ROW, COL);
nextto[3] = new PosNode(now.row, now.col + 1, now.G + 1, now, ROW, COL);
for (int i = 0; i < 4; i++)
{
if (!IsValid(nextto[i]))
{
continue;
}
if (close_dict.ContainsKey(nextto[i]))
{
continue;
}
int index = -1;
for (int j = open_list.Count - 1; j >= 0; j--)
{
if (open_list[j].Equals(nextto[i]))
{
index = j;
break;
}
}
if (index == -1)
{
open_list.Add(nextto[i]);
if (nextto[i].row == ROW - 2 && nextto[i].col == COL - 2)
{
finish = true;
break;
}
}
else
{
if (nextto[i].F < open_list[index].F)
{
open_list[index].F = nextto[i].F;
open_list[index].pre = nextto[i].pre;
}
}
}
if (finish)
{
break;
}
}
}
/// <summary>
/// 是否合法节点
/// </summary>
private bool IsValid(PosNode pn)
{
if (pn.row < 0 || pn.row >= ROW || pn.col < 0 || pn.col >= COL)
{
return false;
}
if (maze[pn.row, pn.col] == 1)
{
return false;
}
return true;
}
/// <summary>
/// 打印路径
/// </summary>
public List<Position> PrintPath()
{
List<Position> list = new List<Position>();
PosNode now = open_list[open_list.Count - 1];
while (now != null)
{
list.Add(GetPosition(now.row, now.col));
now = now.pre;
}
return list;
}
代码就是这么多,不难吧!
源码下载:https://download.youkuaiyun.com/download/lweiyue/10830542