一.什么是a*
一种十分常用的寻路算法,它能够依据某个或某些优化准则,在空间中找到一个从起始点到目标点能避开障碍物的最优路径。
二.算法
以下图为例,敌人要绕过中间的障碍物,寻找到敌人。(以一个方块作为一个节点)
大概思路
1.首先将敌人所在的节点(起始点)加入到开列表中(接下来可能会用到的节点)
2.从开列表中取出花费值最小的节点(等会会讲到如何求花费值)(当前开列表中就一个节点)作为当前点
3.将当前点加入到闭列表中(已经用过的点,也是最后所需的点)
4.遍历当前点周围的点,搜索能通过的点(不是障碍物以及不在闭列表中)加入到开列表中,将它们的父节点设为当前点(如下图,箭头所指方向即为其父节点)
4.5 稍后讲解
5.跳回到第二步
6.直到遍历当前点周围的点时遇到了玩家(终点),即完成了寻路。
7.从闭列表中最后一个点,向前遍历父节点,即为一条完整的路径
花费值计算
F = G + H
G = 从起点 A 移动到指定方格的移动代价,沿着到达该方格而生成的路径。
H = 从指定的方格移动到终点 B 的估算成本。(可以根据自己的要求去计算,这里选择最简单的方法,H = (终点与起点坐标的x轴的差值+终点与起点坐标的y轴的差值))如下图有红点的节点
F = 花费的总值
这个通常被称为试探法,有点让人混淆。为什么这么叫呢,因为这是个猜测。直到我们找到了路径我们才会知道真正的距离,因为途中有各种各样的东西 ( 比如墙壁,水等 ) 。
4.5
当我们遍历当前点周围的点时会遇到一个问题“如果周围的点已经在开列表中怎么办?”
这时我们要重新以当前节点到那个节点的G值,如果小于在开列表里的值则将那个节点的父节点设为当前点并重新计算F值。
具体代码
Astart.h
#pragma once
/*
A*算法对象类
*/
#include <vector>
#include <list>
#include <functional>
#include "cocos2d.h"
USING_NS_CC;
using namespace std;
#define sqrtTwo 2;
const int straightCost = 1;
const int bevelCost = sqrtTwo;
class CPoint
{
public:
CPoint(int x,int y)
:x(x), y(y), F(0), G(0), H(0), parent(nullptr)
{
}
~CPoint(){
};
CPoint* parent;
int x, y; //横纵坐标
int F, G, H; //G起点到当前点的花费,H当前点到终点的花费,F = G+H
};
class Astar
{
public:
Astar();
~Astar();
//初始化地图 1.如果要进行寻路肯定要传地图数据进行
void initAstar(vector<vector<int>>& maze);
// 初始化匿名函数,通过外部传进来判断条件(节点能否通过)。
// 这里因为用的是cocos2d-x,所以参数是vec2类型,可以根据自己的需求调整
void initFun(function<bool(Vec2)> callBk);
// isIgnoreCorner参数是否允许斜角移动 2.开始寻路
list<CPoint*> GetPath(CPoint &startPoint, CPoint &endPoint, bool isIgnoreCorner)