1.介绍
1.1.A星寻路是在广度寻路的基础上更加智能。
1.2.它是以周围八格中f值最小的作为下一步,一直到终点。这里引入了一个代价的概念。
代价:f = g +h
f:代价总值
g:起点到当前点走过的路线价值
h:当前点到终点的直线待评估值
2.看图
3.步骤
创建一个八叉树,开始吧起点当做树根,吧周围八格能走的路存入临时动态数组,下一次在数组中选择f值最小的格子作为下一步,直到终点。
4.代码区
#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;
#define ROWS 10
#define COLS 10
#define ZXDJ 10 //直线代价
#define XXDJ 14 //斜线代价
//枚举方向
enum direct{p_up,p_left,p_down,p_right,p_lup,p_ldown,p_rdown,p_rup};
//点类
class MyPoint
{
public:
int x;
int y;
int f;
int g;
int h;
};
//节点类
class treeNode
{
public:
MyPoint pos;
treeNode * pParent;
vector<treeNode *> pChild;
treeNode(MyPoint pos1)
{
pos = pos1;
pParent = NULL;
}
};
//测试地图类
class testMap
{
public:
bool IsFind;
};
//能不能走
bool canWalk(int map[ROWS][COLS], testMap testmap[ROWS][COLS], MyPoint pos)
{
//如果是障碍
if (map[pos.x][pos.y] == 1) return false;
//不在地图内
if (pos.x < 0 || pos.x >= ROWS || pos.y < 0 || pos.y >= COLS) return false;
//已经走过
if (testmap[pos.x][pos.y].IsFind == true) return false;
return true;
}
//求H值
int setH(const MyPoint currentPos,const MyPoint endPos)
{
int x = endPos.x-currentPos.x;
int y = endPos.y-currentPos.y;
return (x + y)*ZXDJ;
}
//求F值
int setF(int g,int h)
{
return (g + h);
}
int main()
{
//1.寻路前准备
//1.1地图
int map[ROWS][COLS] = {
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0,
0,0,0,1,0,0,0,0,0,0
};
//1.2测试地图
testMap testmap[ROWS][COLS] = { 0 };
//1.3设置起点和终点
MyPoint begPos = { 1,1 };
MyPoint endPos = { 7,8 };
//1.4标记起点已经走过
testmap[begPos.x][begPos.y].IsFind = true;
//1.5准备八叉树
treeNode *pRoot = new treeNode(begPos); //吧开始起点作为树根
//1.6当前节点 吧开始节点作为当前节点
treeNode * p_CurrentNode = pRoot;
//1.7
vector<treeNode *> buffer ;
vector<treeNode *> ::iterator it;
vector<treeNode *> ::iterator Minit;//用来管理最小的
//1.8临时点
treeNode * pChild;
//是否找到终点
bool IsFindEnd = false;
//定义一个是否需要寻找的变量作为while()循环条件
bool IsNeedFind = true;
//2.开始寻路
while (IsNeedFind)
{
//在当前点中
for (int i = 0; i < 8; i++)
{
pChild = new treeNode(p_CurrentNode->pos);
switch(i)
{
//2.1 g值增加
//直着走
case p_up:
pChild->pos.y --;
pChild->pos.g += ZXDJ;
break;
case p_left:
pChild->pos.x--;
pChild->pos.g += ZXDJ;
break;
case p_down:
pChild->pos.y++;
pChild->pos.g += ZXDJ;
break;
case p_right:
pChild->pos.x++;
pChild->pos.g += ZXDJ;
break;
//斜着走
case p_lup:
pChild->pos.x--;
pChild->pos.y--;
pChild->pos.g += XXDJ;
case p_ldown:
pChild->pos.x--;
pChild->pos.y++;
pChild->pos.g += XXDJ;
case p_rdown:
pChild->pos.x++;
pChild->pos.y++;
pChild->pos.g += XXDJ;
case p_rup:
pChild->pos.x++;
pChild->pos.y--;
pChild->pos.g += XXDJ;
}
//判断能不能走
if (canWalk(map, testmap, pChild->pos))
{
//2.2入树
p_CurrentNode->pChild.push_back(pChild);
//2.3存入数组中
buffer.push_back(pChild);
//2.4计算h值
pChild->pos.h = setH(pChild->pos , endPos);
//2.5计算f值
pChild->pos.f = setF(pChild->pos.g, pChild->pos.h);
}
else
{
//如果不能走释放空间
delete pChild;
}
}//end of(i)
//3寻路后
//3.1选择f值最小的点
Minit = buffer.begin();//默认为开始的点
for (it = buffer.begin(); it < buffer.end(); it++)
{
if ((*Minit)->pos.f > (*it)->pos.f)
Minit = it;
}
//3.2当前点切换成f值最小的点
p_CurrentNode = (*Minit);
p_CurrentNode->pParent = pChild;
//3.3最小的点从buff中删除
buffer.erase(Minit);
//3.4如果是终点
if (p_CurrentNode->pos.x == endPos.x && p_CurrentNode->pos.y == endPos.y)
{
IsNeedFind = false;
IsFindEnd = true;
break;
}
//3.5如果buffer为空
if (buffer.empty())
break;
}//end of(while(1))
if (IsFindEnd)
{
while (p_CurrentNode)
{
printf("路径是:\n");
printf("(%d,%d)\n", p_CurrentNode->pos.x, p_CurrentNode->pos.y);
p_CurrentNode = p_CurrentNode->pParent;
}
printf("找到终点啦");
}
return 0;
}