头文件: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++实现的更多相关文章

  1. A星寻路算法介绍

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

  2. A*寻路算法探究

    A*寻路算法探究 A*算法常用在游戏的寻路,是一种静态网路中求解最短路径的搜索方法,也是解决很多搜索问题的算法.相对于Dijkstra,BFS这些算法在复杂的搜索更有效率.本文在U3D中进行代码的测试 ...

  3. A*寻路算法

    对于初学者而言,A*寻路已经是个比较复杂的算法了,为了便于理解,本文降低了A*算法的难度,规定只能横竖(四方向)寻路,而无法直接走对角线,使得整个算法更好理解. 简而言之,A*寻路就是计算从起点经过该 ...

  4. 算法:Astar寻路算法改进,双向A*寻路算法

    早前写了一篇关于A*算法的文章:<算法:Astar寻路算法改进> 最近在写个js的UI框架,顺便实现了一个js版本的A*算法,与之前不同的是,该A*算法是个双向A*. 双向A*有什么好处呢 ...

  5. 算法:Astar寻路算法改进

    早前写了一篇<RCP:gef智能寻路算法(A star)> 出现了一点问题. 在AStar算法中,默认寻路起点和终点都是N x N的方格,但如果用在路由上,就会出现问题. 如果,需要连线的 ...

  6. js实现A*寻路算法

    这两天在做百度前端技术学院的题目,其中有涉及到寻路相关的,于是就找来相关博客进行阅读. 看了Create Chen写的理解A*寻路算法具体过程之后,我很快就理解A*算法的原理.不得不说作者写的很好,通 ...

  7. 用简单直白的方式讲解A星寻路算法原理

    很多游戏特别是rts,rpg类游戏,都需要用到寻路.寻路算法有深度优先搜索(DFS),广度优先搜索(BFS),A星算法等,而A星算法是一种具备启发性策略的算法,效率是几种算法中最高的,因此也成为游戏中 ...

  8. A星寻路算法

    A星寻路算法 1.准备一个close关闭列表(存放已被检索的点),一个open开启列表(存放未被检索的点),一个当前点的对象cur 2.将cur设成开始点 3.从cur起,将cur点放入close表中 ...

  9. A*寻路算法的探寻与改良(三)

    A*寻路算法的探寻与改良(三) by:田宇轩                                        第三分:这部分内容基于树.查找算法等对A*算法的执行效率进行了改良,想了解细 ...

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

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

随机推荐

  1. Good Bye 2015 C. New Year and Domino 二维前缀

    C. New Year and Domino   They say "years are like dominoes, tumbling one after the other". ...

  2. 微软VSS的超级BUG

    发现问题:今天一个新同事,无意中发现他直接就登录进VSS了,并且还是“admin”用户: 解决问题:于是开始在网上找度娘和谷歌帮忙,真是不查不要紧,一查吓一跳,VSS本身就存在这个bug,并且是一个超 ...

  3. SQL Server 2008管理工具出现 远程过程调用失败0x800706be解决方法

    解决方法 出现此问题是因为在安装 Visual Studio 2012(VS2012) 时,会自动安装 "Microsoft SQL Server 2012 Express LocalDB& ...

  4. MongoDB 安装,启动与基本使用

    一.MongoDB简介 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种.它在许多场景下可用于替代传统的关系型数据库或键/值存储方式.Mongo使用C++ ...

  5. 李洪强漫谈iOS开发[C语言-004]-开发概述程序设计语言程序编译过程

    汇编语言 指令用特定的名字来标记,这就是汇编语言 人比较容易看懂汇编语言 汇编直接和程序一一对应的 有汇编器把程序翻译成机器码 把高级语言编译成计算机识别的语言 程序编译过程 命令行 UNIX 系统中 ...

  6. phpeclipse常用快捷键

    phpeclipse常用快捷键

  7. *在Win7中安装JDK1.7并配置环境变量

    安装的过程就不废话了. 下面是环境变量的配置. 1. 配置环境变量 单机右键‘计算机--属性’  2.点击高级系统设置  3.点击‘环境变量’ 4.增加"JAVA_HOME"系统变 ...

  8. Spring Loaded is a JVM agent for reloading class file changes

    <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot ...

  9. 数据仓库的自动ETL研究

    但是,在实施数据集成的过程中,由于不同用户提供的数据可能来自不同的途径,其数据内容.数据格式和数据质量千差万别,有时甚至会遇到数据格式不能转换或数据转换格式后丢失信息等棘手问题,严重阻碍了数据在各部门 ...

  10. Linux下安装Python-3.3.2【转】

    # 下载最新版本 cd /usr/local/src/ sudo wget http://www.python.org/ftp/python/3.3.2/Python-3.3.2.tar.bz2 su ...