这几天大体完成了服务器框架的代码,闲下来看了下A*算法,也在断断续续中把自己的源码写完,这里记录下,以后可以回顾:
基本的原理我这里也不在阐述了,这篇翻译还是不错,只是其中有些遗漏罢了:
http://www.cppblog.com/mythit/archive/2009/04/19/80492.aspx
这篇对几个算法有更详细的介绍:
http://blog.csdn.net/niteip/article/details/7519609
下面直接贴代码吧,代码里面有比较详细的注释,三个文件:main.cpp, AstarTest.h, AstarTest.cpp,欢迎拍砖指正,毕竟有批评才会进步嘛,^-^!.
最后一个疑问就是不明白加权曼哈顿距离的好处在哪里,希望知道的告知一下,谢谢~
AstarTest.h
/*
A*搜寻算法,俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC(Non-Player-ControlledCharacter)的移动计算,
或线上游戏的BOT(ROBOT)的移动计算上。该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。
A*算法是一种启发式搜索算法,启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标。这样可以省略大量无谓的
搜索路径,提高了效率。在启发式搜索中,对位置的估价是十分重要的。采用了不同的估价可以有不同的效果。
A*算法的公式为:f(n)=g(n)+h(n),g(n)表示从起点到任意顶点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离。 这个公式遵循以下特性:
如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法
如果h(n)<=“n到目标的实际距离”,则一定可以求出最优解。而且h(n)越小,需要计算的节点越多,算法效率越低。
对于函数h(n),估算距离常用的方法有:
曼哈顿距离:定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里德空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。
例如在平面上,坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为:|x1 - x2| + |y1 - y2|。
欧氏距离:是一个通常采用的距离定义,它是在m维空间中两个点之间的真实距离。在二维和三维空间中的欧氏距离的就是两点之间的距离。例如在平面上,
坐标(x1,y1)的点P1与坐标(x2, y2)的点P2的欧氏距离为: sqrt((x1-x2)^2+(y1-y2)^2 )。
切比雪夫距离:是两个向量之间各分量差值的最大值。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的切比雪夫距离为:max(|x1 - x2| , |y1 - y2|)。
注:关于是否能穿过对角线的规则,是自己定义的
该工程分两种方式寻路:
直线寻路:只能 直上直下直左直右
对角线寻路:包括直线寻路,额外加上走对角线路线
参考网页地址:http://blog.csdn.net/niteip/article/details/7519609
感谢作者
*/
#pragma once
#include <iostream>
#include <queue>
#include <math.h>
using namespace std;
//定义是否可以走对角线的宏
#define WALK_DIAGONAL
#ifdef WALK_DIAGONAL
#define NeighborNum 8 //邻居个数
static int offset[NeighborNum][2]={
{
1,0},{
1,1},{
1,-1},{-1,0},{-1,-1},{-1,1},{
0,-1},{
0,1}};//邻居的坐标选择
#else
#define NeighborNum 4 //邻居个数
static int offset[NeighborNum][2]={
{
1,0},{-1,0},{
0,-1},{
0,1}};//邻居的坐标选择
#endif
//定义二维数组的长度
#define RowNumber 6
#define ColumnNumber 8
//定义曼哈顿距离的扩大比例
#define ManhattanSacle 10 //10倍
enum NodeType
{
Node_Start = 0, //起始点
Node_Barrier, //障碍物,把所有不能通过的点都认为是障碍物
Node_Way, //可通行的路
Node_FindWay, //经过寻路后,会经过的点
Node_End, //终点
Node_Null, //未定义的点
};
//定义找到的路径的符号表示