1.介绍
广度寻路算法是上,左,下,右一起试探,把试探过能走的点用以四叉树的方式保存起来,直到试探到终点。
广度相比于深度,可以找到从起点到终点的最佳路径
废话不多说,看图
2.图
图中1表示起点,2表示终点
3.步骤&&方法:
1.如上图,这里引入一个层的概念,例如起点(1,9)就是第一层,随之试探出第二层…
2.这里可以使用C++的vector,把第一层的节点存入vector中,在进行循环,在之后吧第一层的每一个节点试探出的节点存放到vect中,直到试探出终点循环结束。
4.代码
#include"stdfax.h"
#define ROW 10
#define COL 10
//枚举
enum direct { p_Up, p_Left, p_Down, p_Right };
class testMap
{
public:
bool IsGo;//是否走过
};
struct MyPoint
{
int x;
int y;
};
class treeNode
{
public:
//数据域
MyPoint pos;
//指针域
treeNode * Parent; //指向上一层的指针
vector<treeNode *> pChild; //指向下一层的指针
treeNode(int x,int y)
{
pos.x = x;
pos.y = y;
Parent = NULL;
}
treeNode(MyPoint pos1)
{
pos = pos1;
Parent = NULL;
}
};
//试试能不能走
bool CanWalk(int map[ROW][COL], testMap testmap[ROW][COL],MyPoint pos)
{
//是障碍
if (map[pos.x][pos.y] ) return false;
//已经走过
if (testmap[pos.x][pos.y].IsGo == true) return false;
//不在地图内
if (pos.x >= ROW || pos.x < 0 || pos.y >= COL || pos.y < 0) return false;
return true;
}
int main()
{
//1.准备一个地图
int map[ROW][COL] = {
1,1,1,1,1,1,1,1,1,1,
1,0,1,0,0,0,0,1,1,1,
1,0,0,0,1,1,1,1,1,1,
1,0,0,0,0,0,0,0,1,1,
1,0,1,1,1,1,1,0,1,1,
1,0,0,0,0,1,1,0,1,1,
1,0,1,0,1,1,1,0,1,1,
1,0,0,0,1,1,0,0,1,1,
1,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1
};
//2.准备一个测试地图
testMap testmap[ROW][COL] = { 0 };
//3.初始化起点和终点
MyPoint BegPoint = { 1,1 }; //起点
MyPoint EndPoint = { 8,2 }; //终点
testmap[BegPoint.x][BegPoint.y].IsGo = true;//标记起始点已经走过
vector<treeNode *> Current; //用于储存当前层的节点
vector<treeNode *> Next; //用于储存下一层的节点
treeNode * pRoot = new treeNode(BegPoint); //起点节点当做树的根
Current.push_back(pRoot);//吧树的节点存放到当前层中
MyPoint tempPos;
//3.寻路
MyPoint currentPos; //用于表示当前点
treeNode * pChild = NULL; //专门用来存储新节点
bool IsEnd = false; //判断是不是终点
while (1)
{
//printf("666");
//清除下一层
Next.clear();
//表示当前层的循环
for (int i = 0; i < Current.size(); i++)
{
currentPos = Current[i]->pos; //当前点等于当前层中第i个节点的点
//开始走
for (int j = 0; j < 4;j++)
{
switch (j)
{
case p_Up://向上
tempPos.x = currentPos.x;
tempPos.y = currentPos.y - 1;
break;
case p_Left://左
tempPos.x = currentPos.x-1;
tempPos.y = currentPos.y;
break;
case p_Down://向下
tempPos.x = currentPos.x;
tempPos.y = currentPos.y + 1;
break;
case p_Right://向右
tempPos.x = currentPos.x + 1;
tempPos.y = currentPos.y;
break;
default:
break;
}
//判断是不是能走
if (CanWalk(map,testmap, tempPos))
{
//1.开辟新内存
pChild = new treeNode(tempPos);
//2.节点入树
Current[i]->pChild.push_back(pChild);
//3.保存到下一层(Next)中
Next.push_back(pChild);
//4.新节点的Parent指针指向上一层节点
pChild->Parent = Current[i];
//5.标记已经走过
testmap[tempPos.x][tempPos.y].IsGo = true;
//如果是终点
if (tempPos.x == EndPoint.x && tempPos.y == EndPoint.y)
{
IsEnd = true;
break;
}
}
if (IsEnd)
break;
}//end of(j)
if (IsEnd)
break;
}//end of(i)
if (IsEnd)
{
printf("找到终点啦");
while (NULL != pChild)
{
printf("路径是:");
printf("(%d,%d)\n ", pChild->pos.x, pChild->pos.y);
pChild = pChild->Parent;
}
break;
}
//当前层切换到下一层
Current = Next;
}
printf("程序结束\n");
return 0;
}
5.总结
1.广度与深度的比较
1.1.没有回退
1.2.深度不一定能找到最佳路径,广度能
1.3.时间复杂度高
2.个人感觉广度寻路算法要比深度寻路算法要有趣的多。像RPG游戏里的自动寻路用的就是类似于广度的算法吧。比如A星寻路就是在广度的基础上更加智能优化了一点。
明天继续更新A星寻路算法,前几天因为开学原因没时间啦。