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的一些基本用法和注意事项,偷下懒。呼呼)
- A*算法梳理
- 逻辑回归算法梳理
- 算法关系梳理
- 安全算法梳理
- 安全算法梳理
- 排序算法梳理
- 机器学习算法思想梳理
- 机器学习:算法简单梳理
- 机器学习算法思想梳理
- jvm垃圾回收算法梳理
- 算法导论梳理(一)
- 机器学习 --算法思想梳理
- 面试高级算法梳理笔记
- 机器学习 --算法思想梳理
- 在线最优化算法梳理
- 梳理
- 梳理
- 梳理
- Android Binder机制浅析之注册MediaPlayerService(1)
- Cocos2d-X 3.2学习——DrawNode使用注意
- JAVA_WEB项目(结合Servlet+jsp+ckEditor编辑器+jquery easyui技术)实现新闻发布管理系统第四篇:前台首页,新闻分类(体育新闻,科技新闻等),新闻列表分页的实现
- Android使用WiFi连接adb
- 嵌入式开发_时序进阶(基于cortex-A9、DS18B20温度传感器)
- A*算法梳理
- 《离散数学》第二周作业
- 学生信息管理系统
- Hibernate Session的Flush模式
- 删除文件名含有f的文件
- 主角做完一件事情后,更新自己状态的回调函数
- 常见算法在实际项目中的应用
- 二叉搜索树--进阶篇之红黑树
- 【Unix/Linux.Shell Script】Shell Script的执行及特殊字符