A *搜索算法称为A星算法。这是一个在图形平面,路径。求出最低通过成本的算法。

经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上。

首先:1、在Map地图中任取2个点,開始点和结束点

2、首先推断该点是不是不能够穿越的点,或者是已经再close中了

3、假设2步骤为真。什么都不做,假设为假,那么我们就进行加入了

4、假设在加入的时候,发现该点在open中不存在。那么我们直接加入,并且视之为当前节点,假设该点              存在open中,那么我们比較G值,假设发现当前节点到该节点的G小于原来的G,那么再又一次设置G,F值,
             然后设置这个节点为当前节点。

5、再添推断玩之后,再加入它的4个邻接点,循环1-4的步骤。直至找到,或者说是open中为null了的时              候,就结束查询了。

代码例如以下:

#include <iostream>
#include <string>
#include "AStartMap.h"
using namespace std; int main() {
AstartMap *gameMap = new AstartMap;
gameMap->initMap();
if(gameMap != 0) {
delete gameMap;
gameMap = 0;
}
return 0;
} #ifndef ASTARTNODE_H_
#define ASTARTNODE_H_ class AStartNode
{
public:
AStartNode();
~AStartNode(); public:
void setPos(int icol, int irow);
void setG(int iG);
int getG();
void setH(int iH);
int getH();
void setF(int iF);
void setFID(int iFID);
int getFID();
int getF();
int getCol();
int getRow(); private:
int m_Col;
int m_Row;
int m_G;
int m_H;
int m_F;
int m_FID;
};// end of AStartNode #endif // end of ASTARTNODE_H_ #include "AStartNode.h" AStartNode::AStartNode() : m_Col(0), //
m_Row(0),
m_G(0),
m_H(0),
m_F(0),
m_FID(0)
{ } AStartNode::~AStartNode() { } void AStartNode::setPos(int icol, int irow) {
m_Col = icol;
m_Row = irow;
} void AStartNode::setG(int iG) {
m_G = iG;
} int AStartNode::getG() {
return m_G;
} void AStartNode::setH(int iH) {
m_H = iH;
} int AStartNode::getH() {
return m_H;
} void AStartNode::setF(int iF) {
m_F = iF;
} int AStartNode::getF() {
return m_F;
} int AStartNode::getCol() {
return m_Col;
} int AStartNode::getRow() {
return m_Row;
} void AStartNode::setFID(int iFID) {
m_FID = iFID;
} int AStartNode::getFID() {
return m_FID;
} #ifndef ASTARTMAP_H_
#define ASTARTMAP_H_ #include <vector>
class AStartNode;
class AstartMap
{
public:
typedef enum {
STARTMAP_COL = 10,
STARTMAP_ROW = 10,
} StartMap; typedef enum {
MAPPATH_BEGINPOINT = -2,
MAPPATH_WALL = -1,
MAPPATH_ROAD = 0,
MAPPATH_ENDPOINT = 2,
} MapPath; typedef enum {
STARTNODE_G = 10,
STARTNODE_H = 10,
}StartNodeInfo; public:
AstartMap();
~AstartMap(); public:
void initMap(); private:
void _initMapBoard();
void _initSelectBeginPoint();
void _addIntoCloseNode(AStartNode *newCloseNode);
void _addIntoOpenNode(AStartNode *newOpenNode);
void _deleteBeginNodefromOpenNode(AStartNode *newOpenNode);
void _add_adjacentnodeToOpenNode(AStartNode *newOpenNode);
void _beginToMove();
void _setStartNode_G_H_Value(AStartNode *newOpenNode, AStartNode *parentNode);
bool _isWater(AStartNode *pStartNode);
bool _isInClose(AStartNode *pStartNode);
bool _isInOpen(AStartNode *pStartNode); private:
AStartNode *_getMinFstartNode();
AStartNode *_getAStartNodeAt(int iCol, int iRow);
void _heapRebuild(std::vector<AStartNode *> &rStartNodeArray,int root,int size);
void _heapSort(std::vector<AStartNode *> &rStartNodeArray ,int size); private:
std::vector<AStartNode *> m_AstartNode;
std::vector<AStartNode *> m_openNode;
std::vector<AStartNode *> m_closeNode;
AStartNode *m_pEndNode;
int GameMap[STARTMAP_COL][STARTMAP_ROW]; // map };// end of AstartMap bool isNum(int inum); #endif // end of ASTARTMAP_H_ #include "AStartNode.h" #include <iostream>
#include <ctype.h>
#include <assert.h>
#include <cmath> #include "AStartMap.h" extern bool isNum(int inum); AstartMap::AstartMap() : m_pEndNode(0)
{ } AstartMap::~AstartMap() { } void AstartMap::initMap() {
/*
*@init the game map
*/
_initMapBoard();
} void AstartMap::_initMapBoard() {
//memset(GameMap, MAPPATH_ROAD, STARTMAP_COL * STARTMAP_ROW * sizeof(int));
for(int i = 0; i < STARTMAP_COL; ++i) {
for(int j = 0; j < STARTMAP_ROW; ++j) {
GameMap[i][j] = MAPPATH_ROAD;
AStartNode *aStartNode = new AStartNode;
aStartNode->setPos(i, j);
m_AstartNode.push_back(aStartNode);
}
} for(int i = 0; i < 7; ++i) { // set the game wall
GameMap[i + 2][4] = MAPPATH_WALL;
} _initSelectBeginPoint();
} void AstartMap::_initSelectBeginPoint() {
int ibegin_xpos = 0;
int ibegin_ypos = 0; std::cout<<"Select the Begin Point(X in(0-9), y in (0- 9): \n";
std::cin>>ibegin_xpos;
std::cin>>ibegin_ypos;
if(!isNum(ibegin_xpos) || !isNum(ibegin_ypos)) return; std::cout<<"Select the End Point(X in(0-9), y in (0- 9): \n";
int iend_xpos = 0;
int iend_ypos = 0;
std::cin>>iend_xpos;
std::cin>>iend_ypos;
if(!isNum(iend_xpos) || !isNum(iend_ypos)) return;
GameMap[iend_xpos][iend_ypos] = MAPPATH_ENDPOINT; // set end point AStartNode *pBeginNode = _getAStartNodeAt(ibegin_xpos, ibegin_ypos);
m_pEndNode = _getAStartNodeAt(iend_xpos, iend_ypos); if(pBeginNode == 0) return;
pBeginNode->setG(0);
pBeginNode->setF(0);
pBeginNode->setH(0);
m_openNode.push_back(pBeginNode); /*
*@Game Begin
*the player begins to move
*/
_beginToMove();
} void AstartMap::_beginToMove() {
while(true) {
AStartNode *pBeginNode = _getMinFstartNode();
std::cout<<"select point: "<<pBeginNode->getCol()<<", "<<pBeginNode->getRow()<<std::endl;
_add_adjacentnodeToOpenNode(pBeginNode);
_addIntoCloseNode(pBeginNode);
_deleteBeginNodefromOpenNode(pBeginNode); if(pBeginNode == m_pEndNode) { // find the end position
std::cout<<"fine the end position"<<std::endl<<std::endl;
break;
}
}
} AStartNode *AstartMap::_getAStartNodeAt(int iCol, int iRow) {
int iNode_Count = m_AstartNode.size();
for(int i = 0; i < iNode_Count; ++i) {
if(m_AstartNode[i]->getCol() == iCol && m_AstartNode[i]->getRow() == iRow) return m_AstartNode[i];
}
return 0;
} void AstartMap::_addIntoCloseNode(AStartNode *newCloseNode) {
if(newCloseNode == 0) return;
m_closeNode.push_back(newCloseNode);
} void AstartMap::_addIntoOpenNode(AStartNode *newOpenNode) {
if(newOpenNode == 0) return;
m_openNode.push_back(newOpenNode); // then other 4 node
} void AstartMap::_add_adjacentnodeToOpenNode(AStartNode *newOpenNode) {
int ileftNodeRow = newOpenNode->getRow() - 1;
if(ileftNodeRow >= 0) {
AStartNode *leftNode = _getAStartNodeAt(newOpenNode->getCol(), ileftNodeRow); if(!_isWater(leftNode) && !_isInClose(leftNode) ) {
if(! _isInOpen(leftNode) ) {
// in open
leftNode->setFID(newOpenNode->getFID());
_addIntoOpenNode(leftNode);
_setStartNode_G_H_Value(leftNode, newOpenNode);
} else {
// not in open
// _setStartNode_G_H_Value(leftNode, newOpenNode);
}
}
} int irightNodeRow = newOpenNode->getRow() + 1;
if(irightNodeRow < STARTMAP_ROW) {
AStartNode *rightNode = _getAStartNodeAt(newOpenNode->getCol(), irightNodeRow);
if(!_isWater(rightNode) && !_isInClose(rightNode)) {
if(! _isInOpen(rightNode) ) {
// in open
rightNode->setFID(newOpenNode->getFID());
_addIntoOpenNode(rightNode);
_setStartNode_G_H_Value(rightNode, newOpenNode);
} else {
// not in open
//_setStartNode_G_H_Value(rightNode, newOpenNode);
}
}
} int iupNodeCol = newOpenNode->getCol() - 1;
if(iupNodeCol >= 0) {
AStartNode *upNode = _getAStartNodeAt(iupNodeCol, newOpenNode->getRow());
if(!_isWater(upNode) && !_isInClose(upNode)) {
if( ! _isInOpen(upNode)) {
//in open
upNode->setFID(newOpenNode->getFID());
_addIntoOpenNode(upNode);
_setStartNode_G_H_Value(upNode, newOpenNode);
} else {
//_setStartNode_G_H_Value(upNode, newOpenNode);
}
}
} int idownNodeCol = newOpenNode->getCol() + 1;
if(idownNodeCol < STARTMAP_COL) {
AStartNode *downNode = _getAStartNodeAt(idownNodeCol, newOpenNode->getRow());
if(!_isWater(downNode) && !_isInClose(downNode)) {
if( ! _isInOpen(downNode)) {
//in open
downNode->setFID(newOpenNode->getFID());
_addIntoOpenNode(downNode);
_setStartNode_G_H_Value(downNode, newOpenNode);
} else {
//_setStartNode_G_H_Value(downNode, newOpenNode);
}
}
}
} bool AstartMap::_isWater(AStartNode *pStartNode) { int icol = pStartNode->getCol();
int irow = pStartNode->getRow();
if(GameMap[icol][irow] == MAPPATH_WALL) return true;
return false;
} bool AstartMap::_isInClose(AStartNode *pStartNode) {
assert(pStartNode);
std::vector<AStartNode *>::iterator it = m_closeNode.begin();
for( ; it != m_closeNode.end(); ++it) {
if(*it == pStartNode) {
return true;
}
}
return false;
} bool AstartMap::_isInOpen(AStartNode *pStartNode) {
assert(pStartNode);
std::vector<AStartNode *>::iterator it = m_openNode.begin();
for(; it != m_openNode.end(); ++it) {
if(*it == pStartNode) {
return true;
}
}
return false;
} void AstartMap::_deleteBeginNodefromOpenNode(AStartNode *newOpenNode) {
if(newOpenNode == 0) return;
std::vector<AStartNode *>::iterator it = m_openNode.begin();
for( ; it != m_openNode.end(); ++it) {
if(*it == newOpenNode) {
m_openNode.erase(it);
break;
}
}
} void AstartMap::_setStartNode_G_H_Value(AStartNode *newOpenNode, AStartNode *parentNode) {
if(newOpenNode == 0 || parentNode == 0) return ;
if(newOpenNode->getCol() == 6 && newOpenNode->getRow() == 3) {
int i = 0;
}
newOpenNode->setG( parentNode->getG() + 10);
newOpenNode->setH( ( abs((m_pEndNode->getRow() - newOpenNode->getRow())) + abs((m_pEndNode->getCol() - newOpenNode->getCol())) - 1) * 10);
newOpenNode->setF(newOpenNode->getG() + newOpenNode->getH());
} AStartNode *AstartMap::_getMinFstartNode() {
_heapSort(m_openNode, m_openNode.size());
int icount = m_openNode.size();
AStartNode *minNode = m_openNode[0];
return minNode;
} void AstartMap::_heapRebuild(std::vector<AStartNode *> &rStartNodeArray, int root, int size)
{
int child = 2 * root + 1;
if(child <= size - 1) {
int rightChild = child + 1;
if(rightChild <= size - 1)
if(rStartNodeArray[child]->getF() < rStartNodeArray[rightChild]->getF())
child = rightChild;
if(rStartNodeArray[root]->getF() < rStartNodeArray[child]->getF())
{
AStartNode *temp = rStartNodeArray[child];
rStartNodeArray[child] = rStartNodeArray[root];
rStartNodeArray[root] = temp;
_heapRebuild(rStartNodeArray, child, size);
}
}
} void AstartMap::_heapSort(std::vector<AStartNode *> &rStartNodeArray, int size)
{
for(int i = size-1; i >= 0; i--){
_heapRebuild(rStartNodeArray,i,size);
} int last=size-1;
for(int i = 1;i <= size; i++, last--) {
AStartNode *temp=rStartNodeArray[0];
rStartNodeArray[0]=rStartNodeArray[last];
rStartNodeArray[last]=temp;
_heapRebuild(rStartNodeArray,0,last);
}
}
//
bool isNum(int inum) { // if the num in(0-9) return true, or return false
if(inum >= 0 && inum <= 9) return true;
return false;
}
速度和准确度之间的选择前不是静态的。你能够基于CPU的速度、用于路径搜索的时间片数、地图上物体(units)的数量、物体的重要性、组(group)的大小、难度或者其它不论什么因素来进行动态的选择。取得动态的折衷的一个方法是,建立一个启示式函数用于假定通过一个网格空间的最小代价是1,然后建立一个代价函数(cost
function)用于測量(scales):
g’(n) = 1 + alpha * ( g(n) – 1 )
假设alpha是0,则改进后的代价函数的值总是1。这样的情况下。地形代价被全然忽略。A*工作变成简单地推断一个网格可否通过。

假设alpha是1,则最初的代价函数将起作用。然后你得到了A*的全部长处。你能够设置alpha的值为0到1的随意值。

你也能够考虑对启示式函数的返回值做选择:绝对最小代价或者期望最小代价。比如,假设你的地图大部分地形是代价为2的草地,其他一些地方是代价为1的道路,那么你能够考虑让启示式函数不考虑道路,而仅仅返回2*距离。
速度和准确度之间的选择并非全局的。在地图上的某些区域,准确度是重要的。你能够基于此进行动态选择。比如。如果我们可能在某点停止又一次计算路径或者改变方向,则在接近当前位置的地方。选择一条好的路径则是更重要的。因此为何要对兴许路径的准确度感到厌烦?或者,对于在地图上的一个安全区域,最短路径或许并不十分重要。可是当从一个敌人的村庄逃跑时,安全和速度是最重要的。
在游戏中。路径潜在地花费了很多存储空间,特别是当路径非常长而且有非常多物体须要寻路时。路径压缩,导航点和beacons通过把多个步骤保存为一个较小数据从而降低了空间需求。Waypoints rely on straight-line segments being common so that
we have to store only the endpoints, while beacons rely on there being well-known paths calculated beforehand between specially marked places on the map.假设路径仍然用了很多存储空间。能够限制路径长度,这就回到了经典的时间-空间折衷法:为了节省空间,信息能够被丢弃,稍后才又一次计算它。

本人cocos2dx
2.x和3.x的源代码淘宝地址(欢迎大家光顾):http://shop115423056.taobao.com/?spm=2013.1.1000126.d21.dMbdyb

不懂的能够加我的QQ群:
239982941(cocos2d-x 3.x学习小组)

版权声明:本文博主原创文章,博客,未经同意不得转载。

Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问的更多相关文章

  1. cocos2d-x学习日志(13) --A星寻路算法demo

    你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢?如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! A星算法简介: A*搜寻算法俗称A星 ...

  2. Cortex-M3学习日志(六) -- ADC实验

    上一次简单的总结了一下DAC方面的知识,好吧,这次再来总结一下ADC方面的东东.ADC即Analog-to-Digital Converter的缩写,指模/数转换器或者模拟/数字转换器.现实世界是由模 ...

  3. Cortex-M3学习日志(五) -- DAC实验

    终于逮了个忙里偷闲的机会,就再学一下LPC1768的外围功能吧,循序渐进是学习的基本规则,也许LPC1768的DAC与8位单片机16位单片机里面集成的DAC操作类似,但是既然这是懒猫的学习日志,就顺便 ...

  4. MobileForm控件的使用方式-用.NET(C#)开发APP的学习日志

    今天继续Smobiler开发APP的学习日志,这次是做一个title.toolbar.侧边栏三种效果 样式一 一.          Toolbar 1.       目标样式 我们要实现上图中的效果 ...

  5. composer的安装和使用 学习日志

    如果你做为一个phper,没有用过composer,那你真的不是一个合格的开发者.那么就来记录一下composer的学习日志 下面分享几个学习源头: composer中文网站:https://www. ...

  6. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一) 写下此文章只为了记录Surging微服务学习过程,并且分享给广大想学习surging的基友,方便广大 ...

  7. GRE学习日志

    发现开博客园真的很有督促作用,今天也顺便开个GRE学习日志吧 2015-02-09:单词 2015-02-10:单词 2015-02-11:单词 2015-03-02:阅读 2015-03-04:阅读 ...

  8. Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行

    Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候 ...

  9. webpack2学习日志

    webpack说容易也容易,说难也难,主要还是看个人,想学到什么样的程度,很多公司可能要求仅仅是会用就行,但是也有一些公司要求比较高,要懂一些底层的原理,所以还是要花一些时间的,看个人需求.这篇仅仅是 ...

随机推荐

  1. WPF界面设计技巧(1)—不规则窗体图文指南

    原文:WPF界面设计技巧(1)-不规则窗体图文指南 初到园子,奉上第一篇入门级教程,请勿见笑. 以往WinForm编程中,实现不规则窗体是有一定难度的,更难的是不规则窗体的边缘抗锯齿及局部透明处理.而 ...

  2. 泛泰A850 (高通8064+720p)刷4.4专用中文recovery TWRP2.7.1.3版

    欢迎关注泛泰非盈利专业第三方开发团队 VegaDevTeam  (本team 由 syhost suky zhaochengw(z大) xuefy(大星星) tenfar(R大师) loogeo cr ...

  3. poj1655 Balancing Act 找树的重心

    http://poj.org/problem? id=1655 Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  4. windows phone 浏览器 (1)

    原文:windows phone 浏览器 (1) windows phone 浏览器主要用的控件是phone:WebBrowser,该控件就是windows phone中的IE,在grid控件嵌套的g ...

  5. graph driver-device mapper-01driver初始化

    // thin device数据结构 type DevInfo struct { Hash string `json:"-"` DeviceId int `json:"d ...

  6. leetcode先刷_Binary Tree Level Order Traversal II

    非常easy标题,在后面,我不认为它不是那么简单的回答更多的.我们将编写,没有人啊. 预购在基层上,加上节省每一层,加上从下往上的输出,是一家vector而一个stack那么问题,没有他,但另一方面- ...

  7. Cocos2d-x 3.0 红孩儿私人义务教育 - 第一章 熟人Cocos2d-x 3.0project

     Cocos2d-x 3.0 红孩儿私家必修 前言: 时光飞逝,每每看到博客上的回复和微博上的鼓舞,总会认为亏欠大家点什么.停下来太久.总是认为不太对劲,哈哈,时习之吧,望以此勉励大家. 红孩儿C ...

  8. 二叉树3种递归和非递归遍历(Java)

    import java.util.Stack; //二叉树3种递归和非递归遍历(Java) public class Traverse { /******************一二进制树的定义*** ...

  9. PHPCMS V9{loop subcat(0,0,0,$siteid) $r}怎么解释?

    {loop subcat(0,0,0,$siteid) $r}{/loop} /** * 获取子栏目  * @param $parentid 父级id   * @param $type 栏目类型  * ...

  10. MVC @Html控件

    传统的Html元素不能和服务端数据进行绑定 HtmlHelper类提供了一系列的方法来生成Html元素 并可以实现与数据绑定在一起 然后生成Html Html.BeginForm(actionName ...