【转】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星 ...
随机推荐
- shell脚本替换文件中字符
1.将当前目录下包含jack串的文件中,jack字符串替换为tom sed -i "s/jack/tom/g" `grep "jack" -rl ./` 2.将 ...
- 李洪强漫谈iOS开发[C语言-005]-程序结构分析
- 多页面打印--web print
背景:项目中要求做在一个页面中通过选择网址来打印多个页面的内容的功能 原理:通过iframe把各网址的页面内容加载进来,通过iframe.contentWindow拿到iframe的window对象, ...
- PHP 反射机制Reflection
简介 PHP Reflection API是PHP5才有的新功能,它是用来导出或提取出关于类.方法.属性.参数等的详细信息,包括注释. class Reflection { } interface R ...
- JavaWeb项目开发案例精粹-第6章报价管理系统-05Action层
0. <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC &quo ...
- ubuntu下搭建cocos2dx编程环境-下
前两篇介绍了cocos2d-x 下linux开发环境配置和android 环境配置问题.在这其中遇到很多问题,所以最后一篇分享一下在处理这些问题时,我是如何解决的,是怎么想的.同时总结一些解 ...
- Highcharts属性详解
Highcharts的基本属性和方法详解 Highcharts 是一个用纯JavaScript编写的一个图表库, 能够很简单便捷的在web网站或是web应用程序添加有交互性的图表,并且免费提供给个人学 ...
- Intellij Idea 15 生成serialVersionUID的方法
默认情况下Intellij IDEA是关闭了继承了Serializable接口的类生成serialVersionUID的警告.如果需要ide提示生成serialVersionUID,那么需要做以下设置 ...
- RMI、Hessian、Burlap、Httpinvoker、WebService的比较
RMI.Hessian.Burlap.Httpinvoker.WebService的比较 2(转) [2]Java远程调用方法性能比较 [IT168技术]现在,Java远程调用方法很多,各种方 ...
- Web Server 使用WebClient 发送https请求 The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel
使用WebClient 发送https请求 使用WebClient发送请求时,并且是以https协议: WebClient webClient = new WebClient(); string re ...