【转】A*寻路算法 C++实现
头文件:AStarPathFinding
#ifndef ASTARPATHFINDING_H
#define ASTARPATHFINDING_H
#include <queue>//为了使用优先级队列priority_queue
#include <stack>
#include <vector>
//迷宫地图中节点类型标记
enum{
NODE_EMPTY,//可以通过的节点
NODE_OBSTACLE,//障碍物,不可通过
NODE_PATH//路径上的点
};
//记录路径上的点的坐标
typedef struct tagpathNode{
int x,y;
}PathNode;
//节点数据结构定义
typedef struct tagNode{
int x,y;//当前点在迷宫中的位置坐标
int g;//起始点到当前点实际代价
int h;//当前节点到目标节点最佳路径的估计代价
int f;//估计函数:f = g + h。
struct tagNode *father;//指向其父节点的指针
}Node;
//定义STL优先队列的排序方式
class HeapCompare_f{
public:
bool operator()(Node* x,Node* y) const
{
return x->f > y->f;//依据估价函数进行排序:升序排列
}
};
//迷宫寻路:A*算法
class AStarPathFinding{
public:
private:
char *m_mapFileName;//存储地图信息的文件名
int m_rows,m_cols;//迷宫的高度和宽度
int **m_maze;//迷宫布局
int m_startX,m_startY;//起始点坐标
int m_endX,m_endY;//目标点坐标
],dy[];//8个子节点移动方向:上、下、左、右、左上、右上、右下、左下
Node *startNode,*endNode;//起始节点和目标节点
int **m_path;//记录路径信息
int m_steps;//搜索所花费的总步数
//OPEN表:采用C++ STL中vector实现优先级队列功能
//注意:存储的是Node*指针
std::vector<Node*> OPENTable;
//CLOSED表:存储的也是Node*指针
std::vector<Node*> CLOSEDTable;
public:
//构造函数
AStarPathFinding(char* mapFileName);
~AStarPathFinding();//析构函数
void init();//初始化
//读取地图信息
bool readMap();
//寻路主函数
bool pathFinding();
//产生路径信息
void generatePath();
//打印路径信息
void printPath();
//估计当前点到目标点的距离:曼哈顿距离
int judge(int x,int y);
//判断某一节点是否合法
bool isIllegle(int x,int y);
};
#endif
源文件:
#include "AStarPathFinding.h"
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <fstream>
using namespace std;
;
AStarPathFinding::AStarPathFinding(char* mapFileName)
:m_steps()
{
m_mapFileName = () * sizeof(char));
strcpy(m_mapFileName,mapFileName);
}
AStarPathFinding::~AStarPathFinding()
{
free(m_mapFileName);
//千万不能有这句代码,因为startNode已加入OPEN表,会在释放OPEN表
//的时候释放,否则会造成重复释放,出现bug
//delete startNode;
delete endNode;
////释放迷宫布局数组:注意多维数组空间释放
;i < m_rows;++i)
{
delete[] m_maze[i];
}
delete[] m_maze;
;i < m_rows;++i)
{
delete[] m_path[i];
}
delete[] m_path;
//释放OPEN表以及CLOSED表内存空间
vector<Node*>::iterator iter;
for (iter = OPENTable.begin();iter != OPENTable.end();++iter)
{
delete (*iter);
}
OPENTable.clear();
vector<Node*>::iterator iter2;
for (iter2 = CLOSEDTable.begin();iter2 != CLOSEDTable.end();++iter2)
{
delete (*iter2);
}
CLOSEDTable.clear();
}
void AStarPathFinding::init()
{
dx[] =dx[] = dx[] = -;
dx[] =dx[] = ;
dx[] =dx[] = dx[] = ;
dy[] = dy[] = dy[] = -;
dy[] =dy[] = ;
dy[] =dy[] = dy[] = ;
readMap();
//分配空间
m_path = new int *[m_rows];
;i < m_rows;++i)
{
m_path[i] = new int[m_cols];
}
startNode = new Node;
startNode->x = m_startX;
startNode->y = m_startY;
startNode->g = ;
startNode->h = judge(startNode->x,startNode->y);
startNode->f = startNode->g + startNode->h;
startNode->father = NULL;
endNode = new Node;
endNode->x = m_endX;
endNode->y = m_endY;
endNode->father = NULL;
}
bool AStarPathFinding::pathFinding()
{
//判断起始点和目标点是否是同一点
if (m_startX == m_endX && m_startY == m_endY)
{
cout << "WARNNING : The start point is the same as th destination " << endl;
return true;
}
OPENTable.push_back(startNode);//起始点装入OPEN表
//对vector中元素进行排序:将最后一个元素加入原本已序的heap内
push_heap(OPENTable.begin(),OPENTable.end(),HeapCompare_f());
Node *tempNode = new Node;
//开始遍历
for (;;)
{
if (OPENTable.empty())//判断OPEN表是否为空
{
cout << "ERROR : unable to find the destination" << endl;
return false;
}
tempNode = OPENTable.front();//注意:OPEN表为空会导致未定义行为
++m_steps;
//将第一个元素移到最后,并将剩余区间重新排序,组成新的heap
pop_heap(OPENTable.begin(),OPENTable.end(),HeapCompare_f());
OPENTable.pop_back();//删除最后一个元素
//判断是否已经搜寻到目标节点
if (tempNode->x == m_endX && tempNode->y == m_endY)
{
cout << "OK : success to find the destination" << endl;
endNode->g = tempNode->g;
endNode->h = tempNode->h;
endNode->f = tempNode->f;
endNode->father = tempNode->father;
generatePath();
return true;
}
;i < ;++i)//针对每个子节点
{
int nextX = tempNode->x + dx[i];
int nextY = tempNode->y + dy[i];
if (isIllegle(nextX,nextY))
{
//注意:障碍物角落不能直接通过
== *(*(m_maze + tempNode->x) + nextY) ||
== *(*(m_maze + nextX) + tempNode->y))
{
continue;
}
//计算此子节点的g值
int newGVal;
if (!dx[i] && !dy[i])//位于对角线上
{
newGVal = tempNode->g + ;
}
else
newGVal = tempNode->g + ;
//搜索OPEN表,判断此点是否在OPEN表中
vector<Node*>::iterator OPENTableResult;
for (OPENTableResult = OPENTable.begin();
OPENTableResult != OPENTable.end();++OPENTableResult)
{
if ((*OPENTableResult)->x == nextX &&
(*OPENTableResult)->y == nextY)
{
break;
}
}
//此子节点已经存在于OPEN表中
if (OPENTableResult != OPENTable.end())
{
//OPEN表中节点的g值已经是最优的,则跳过此节点
if ((*OPENTableResult)->g <= newGVal)
{
continue;
}
}
//搜索CLOSED表,判断此节点是否已经存在于其中
vector<Node*>::iterator CLOSEDTableResult;
for (CLOSEDTableResult = CLOSEDTable.begin();
CLOSEDTableResult != CLOSEDTable.end();++CLOSEDTableResult)
{
if ((*CLOSEDTableResult)->x == nextX &&
(*CLOSEDTableResult)->y == nextY)
{
break;
}
}
//此节点已经存在于CLOSED表中
if (CLOSEDTableResult != CLOSEDTable.end())
{
//CLOSED表中的节点已经是最优的,则跳过
if ((*CLOSEDTableResult)->g <= newGVal)
{
continue;
}
}
//此节点是迄今为止的最优节点
Node *bestNode = new Node;
bestNode->x = nextX;
bestNode->y = nextY;
bestNode->father = tempNode;
bestNode->g = newGVal;
bestNode->h = judge(nextX,nextY);
bestNode->f = bestNode->g + bestNode->h;
//如果已经存在于CLOSED表中,将其移除
if (CLOSEDTableResult != CLOSEDTable.end())
{
delete (*CLOSEDTableResult);
CLOSEDTable.erase(CLOSEDTableResult);
}
//如果已经存在于OPEN表,更新
if (OPENTableResult != OPENTable.end())
{
delete (*OPENTableResult);
OPENTable.erase(OPENTableResult);
//重新建堆,实现排序。注意不能用sort_heap,因为如果容器为空的话会出现bug
make_heap(OPENTable.begin(),OPENTable.end(),HeapCompare_f());
}
OPENTable.push_back(bestNode);//将最优节点放入OPEN表
push_heap(OPENTable.begin(),OPENTable.end(),HeapCompare_f());//重新排序
}
}
CLOSEDTable.push_back(tempNode);
}
return false;
}
void AStarPathFinding::generatePath()
{
Node *nodeChild = endNode;
Node *nodeParent = endNode->father;
do
{
*(*(m_path + nodeChild->x) + nodeChild->y) = NODE_PATH;//标记为路径上的点
nodeChild = nodeParent;
nodeParent = nodeParent->father;
} while (nodeChild != startNode);
*(*(m_path + startNode->x) + startNode->y) = NODE_PATH;//标记为路径上的点
}
void AStarPathFinding::printPath()
{
cout << "The path is " << endl;
;i < m_rows;++i)
{
;j < m_cols;++j)
{
if (NODE_PATH == *(*(m_path + i) + j))
{
cout << "# ";
}
else
cout << *(*(m_maze + i) + j) << " ";
}
cout << endl;
}
cout << "搜索总步数:" << m_steps << endl;
}
bool AStarPathFinding::readMap()
{
//从文本文件读取迷宫布局信息
ifstream mapFileStream(m_mapFileName);
if (!mapFileStream)
{
cerr << "ERROR : unable to open map file" << endl;
return false;
}
mapFileStream >> m_rows >> m_cols;
//多维数组空间分配
m_maze = new int *[m_rows];
;i < m_rows;++i)
{
m_maze[i] = new int[m_cols];
}
mapFileStream >> m_startX >> m_startY;
mapFileStream >> m_endX >> m_endY;
;i < m_rows;++i)
{
;j < m_cols;++j)
{
mapFileStream >> *(*(m_maze + i) + j);
}
}
return true;
}
int AStarPathFinding::judge(int x, int y)
{
* (abs(m_endX - x) + abs(m_endY - y)));
}
bool AStarPathFinding::isIllegle(int x, int y)
{
&& x < m_rows &&
y >= && y < m_cols &&
*(*(m_maze + x) + y) == )
return true;
else
return false;
}
int main()
{
AStarPathFinding astar("map.txt");
astar.init();
astar.pathFinding();
astar.generatePath();
astar.printPath();
;
}
地图文件:
以上三个文件放在同一个目录下
打开终端:
g++ AStarPathFinding.cpp
./a.out
【转】A*寻路算法 C++实现的更多相关文章
- A星寻路算法介绍
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢? 如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! 在网上已经有很多篇关于A星寻路算法 ...
- A*寻路算法探究
A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...
- A*寻路算法
对于初学者而言,A*寻路已经是个比较复杂的算法了,为了便于理解,本文降低了A*算法的难度,规定只能横竖(四方向)寻路,而无法直接走对角线,使得整个算法更好理解. 简而言之,A*寻路就是计算从起点经过该 ...
- 算法:Astar寻路算法改进,双向A*寻路算法
早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢 ...
- 算法:Astar寻路算法改进
早前写了一篇<RCP:gef智能寻路算法(A star)> 出现了一点问题. 在AStar算法中,默认寻路起点和终点都是N x N的方格,但如果用在路由上,就会出现问题. 如果,需要连线的 ...
- js实现A*寻路算法
这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我很快就理解A*算法的原理.不得不说作者写的很好,通 ...
- 用简单直白的方式讲解A星寻路算法原理
很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...
- A星寻路算法
A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...
- A*寻路算法的探寻与改良(三)
A*寻路算法的探寻与改良(三) by:田宇轩 第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细 ...
- cocos2d-x学习日志(13) --A星寻路算法demo
你是否在做一款游戏的时候想创造一些怪兽或者游戏主角,让它们移动到特定的位置,避开墙壁和障碍物呢?如果是的话,请看这篇教程,我们会展示如何使用A星寻路算法来实现它! A星算法简介: A*搜寻算法俗称A星 ...
随机推荐
- (2)jni编程学习笔记
先说说NDK和jni的关系吧,这两个看起来挺容易搞混的 我到网上也查了一些资料: java的jni提供了一个调用c语言函数的接口,其实就是一个java函数,这个函数没有任何内容,这个函数调用时直接进入 ...
- 正则表达式(RegExp)
正则表达式(RegExp) 如何按一定规则快速查找到需要找寻的内容,js的设计者们给我们提供了一个叫正则表达式(RegExp对象),专门用于处理类似问题. RegExp对象表示正则表达式,它是对字符串 ...
- 李洪强经典iOS面试题11
#import 跟#include 又什么区别,@class呢, #import<> 跟 #import””又什么区别? #import是Objective-C导入头文件的关键字, ...
- 关于python中模块的import路径
前两天被一个同事问了一个python的问题: 为什么一个目录里的python文件引用不要另一个兄弟目录的python文件,但是这两个目录的父母录运行时是可以引用到了.当时感觉一直是模块和包的机制问题, ...
- TCP释放连接的四次挥手过程
TCP断开连接的过程:TCP四次挥手. 数据传输结束后,通信的双方都可释放连接.现在A和B都处于ESTABLISHED状态.A的应用进程先向TCP发出连接释放报文段,主动关闭TCP连接.A把连接释放报 ...
- swift:入门知识之泛型
在尖括号里写一个名字来创建一个泛型函数或者类型 例如<T>.<Type> 可以创建泛型类.枚举和结构体 在类型后使用where来指定一个需求列表.例如,要限定实现一个协议的类型 ...
- Linux命令-free
显示系统内存使用情况 free [-m / -g / -h] [root@localhost test]# free -m total used free shared buff/cache ava ...
- UE中使用正则表达式的一些技巧
UE中使用正则表达式的一些技巧 2010-12-24 10:33:19 分类: Linux 以下是网上摘录的UE 技巧 1)删除空行: 替换 %[ ^t]++^p 为 空串 2)删除行尾空格: 替换 ...
- 自己动手实现java中cache
实现思路: 创建一个静态Hashtable用于保存key和value,对于cache过期后的方法回调,在cache过期后,再访问cache的时候进行,避免了使用定时器轮询过期时间,进行cache清除的 ...
- javascript把IP地址转为数值几种方案,来挑战一下效率吧
先看看什么是IP地址: IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节).IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~25 ...