A*算法梳理

来源:互联网 发布:央视1台网络直播电视 编辑:程序博客网 时间:2024/04/29 22:46

一,基本原理

在游戏开发的过程中,要求掌握基本的语言基础,熟记基本的设计模式,还要对游戏开发中的算法和数学,物理知识有所了解。当然物理和数学不需要精通,能明白基本原理,能灵活应用即可。A*算法在游戏的算法中还是算比较经常使用到的。最近在一个游戏开发中有应用到,周末时间就按照自己的使用心的做一个梳理。

A*算法是一种人工智能的算法,解决一个搜索问题的过程。处理对象从一个开始位置点经过中间点到达目标位置点的过程。中间点不是随意选择,而是根据当前点到达目标点的路径是最短的目标去寻找。看过的参考资料有提到,这样的一些点就构成了一个图的数据结构,这个图就是状态空间,而寻找的过程就称为状态空间搜索。该搜索方式有深度优先,广度优先和启发式搜索方式。

A*算法其中一种启发式的搜索方式。具体的定义为:f(n) =g(n)+h(n);

g--表示从开始状态到第n个点的最短路径。 h-表示从第n个点到目标点的估算代价。f--表示到目前这个迭代阶段估算的从初始点经过第n个点到达目标点的预计值,将这个值与之前的迭代值进行比较,便可以得到第n个点是否在最优路径中。

简单的说这个过程,就是选择一个起点,从当前的点八个方向开始判断,假设每次移动的水平长度都是固定为X,则斜角的长度为根号2的x长度。假设目标点在开始点的右边,那么第一次取到的点就是右上角和右下角两个方向的两个点是作为下一个继续判断的起点(即在最优路径中, 最优路径不一定只有一条),第一次寻找到的最优路径的点就作为新的点继续进行搜索八个方向的移动,依次寻找,最后到达目标点。

二、伪代码

void rearch(pstart,pend)

创建open列表;---作为可以被搜索的全部的点(如果被搜索过,或者判断不是最优路径的点则从该列表中删除);存放所有点的f(n)值

创建所有待搜索点的数组数据m_grid[][];--存放所有点的标记()

向open列表添加节点;

while(open列表不为空)

n= min(open)--返回列表中估值最小的点

m_grid相应点标记为已经被搜索;

if(n是目标点)

return 路径

        else

检查4个方向的路径以及相对应的估值。(我的游戏只需要设定四个方向)

if(每一个方向的点是否在设定的行列中,并且该点是还未在本次的搜索中被搜索过的点)

向open列表添加该节点next;

三、数据与源码

数据

#define  MAX_GRID 200
//定义点的属性
typedef struct Point
{
int x;//点的横坐标
int y;//的纵坐标
int g;//表示从起始点到该点的移动成本
int h;//表示该点到目的点的移动成本
int f;//表示该点的估价成本 f(n)=g(n)+h(n)
bool operator < (const Point & _point) const{      //重载比较运算符
return f > _point.f;
}
}Point;
//定义前驱结点
typedef struct Father
{
int x;
int y;
}Father;


Father pre[MAX_GRID][MAX_GRID];//保存前驱结点
int map_grid[MAX_GRID][MAX_GRID];//图形的状态
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//方向数组
int row = 40;//行数
int col = 40;//列数

代码:

/********************************
A*算法处理
*********************************/
int QsPictureStory::Distance(int sx,int sy,int ex,int ey)
{
return (sx-ex)*(sx-ex)+(sy-ey)*(sy-ey);
}


//判断当前的方向是否在图中(边界判断)
bool QsPictureStory::Judge(int x,int y)
{
if(x>=0&&x<row&&y>=0&&y<col)
return true;
return false;
}


void QsPictureStory::Print_Path(int ex,int ey)
{
int x =0;
int y=0;
if(pre[ex][ey].x==-1&&pre[ex][ey].y==-1)
{
return;
}
else
{
x=pre[ex][ey].x;
y=pre[ex][ey].y;
//CCLOG("(=打印路径==%d---%d---%d===%d======",ex,ey,x,y);//打印路径
//CCLOG("(=打印路径==%d===%d======",x,y);//打印路径
Print_Path(x,y);


CCPoint point;
point.x = x*32;
point.y = 800-y *20;
m_gameCarMovePathVector.push_back(point);
//map_grid[x][y]=8;//最短路径上铺设'*'
//CCLOG("(=Print_Path==%d===%d======",x,y);//打印路径
}
}


/*A*算法*/
void QsPictureStory::A_Star(int sx,int sy,int ex,int ey)
{
if(map_grid[sx][sy]!=0 || map_grid[sx][sy]!=0)
{
return;
}
//CCLOG("(=sx==%d===%d===%d==%d====",sx,sy, ex, ey);//打印路径
priority_queue<Point>Q_open;//构造open list
Point pst;//开始点
Point pnext;//邻接点
int i;
pst.x=sx;
pst.y=sy;
pst.g=0;
pst.h=Distance(sx,sy,ex,ey);
pst.f=pst.g+pst.h;
Q_open.push(pst);//起始点加入open list之中
while(!Q_open.empty())//当open list非空
{
pst=Q_open.top();//返回open list中的估价值最小的值
Q_open.pop();//删除open list中估价值最小值


map_grid[pst.x][pst.y]= 8;
if(pst.x==ex&&pst.y==ey)//找到目标点
{


Print_Path(ex,ey);
map_grid[ex][ey]=8;
//int m_gameMapArr[40][40]={0};

//CCLOG("--A_Star---%d-----%d----",ex, ey);
return;
}
else
{
for(i=0;i<4;i++)//检查当前结点的每个相邻的点
{
pnext.x=pst.x+dir[i][0];
pnext.y=pst.y+dir[i][1];


//第一:点一定要在图形范围之内
if(Judge(pnext.x,pnext.y) && map_grid[pnext.x][pnext.y]==0)
{
//保存该点的前驱节点的坐标,用来打印开始点到目标点的路径
pre[pnext.x][pnext.y].x = pst.x;
pre[pnext.x][pnext.y].y = pst.y;
//将该点移进 open list并计算其成本
pnext.g=pst.g+1;//当前点的g值
pnext.h=Distance(pnext.x,pnext.y,ex,ey);//当前点的h值
pnext.f=pnext.g+pnext.h;//当前点的f值
Q_open.push(pnext);


map_grid[pnext.x][pnext.y]= 8;
}
}//end for
}//end else
}//end while
}//end A_Star

四、说明

1、在将地图的所有信息读取到map_grid数组后,需要将pre数组都初始化为-1,作为标记。否则循环挑不出来。

2、如果在地图需要碰撞而不能通过,那这些位置先做标记(tiled map editor中可以标记),这样子读取出的地图信息就能作为判断,从而不对这些不能通过的部分进行搜索。(下周得整理下tilemap的一些基本用法和注意事项,偷下懒。呼呼)

       

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我电脑打不了字怎么办 xp系统玩lol卡怎么办 手机上打不了字怎么办 手机打不了字了怎么办 手机的键盘没了怎么办 微信不能打字了怎么办 电脑输不进去字怎么办 短信在桌面没了怎么办 先锋影音ios没了怎么办 砚台里墨汁干了怎么办 浮石打错了想换怎么办 全蛋打发不起来怎么办 裱花剩下的奶油怎么办 打过头的淡奶油怎么办 淡奶油发过了怎么办 打好的蛋清有水怎么办 想戒烟却坚持不了怎么办 给淮山弄的很痒怎么办 淮山接触皮肤痒怎么办 洗山药后手很痒怎么办 公司老板跑路了怎么办 小工厂老板跑路怎么办 学生医保卡丢了怎么办 在私企年龄大了怎么办 百度网盘上传慢怎么办 百度云盘上传慢怎么办 手机qq打字闪退怎么办 苹果5s手机闪退怎么办 手机qq总是闪退怎么办 qq邮箱密码忘了怎么办 qq加不了群怎么办视频 孩子好几天不大便怎么办 宝宝7天没有大便怎么办 40天小孩不拉屎怎么办 40多天婴儿便秘怎么办 小孩拉绿色稀便怎么办 5岁好几天不拉屎怎么办 2个月宝宝不大便怎么办 两月宝宝不拉屎怎么办 好几天没大便了怎么办 初生婴儿便秘解不出大便怎么办