头文件: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. WCF分布式开发步步为赢(4):WCF服务可靠性传输配置与编程开发

    今天继续WCF分布式开发步步为赢系列的第4节:WCF服务可靠性传输配置与编程开发.这个章节,我们要介绍什么是WCF服务的可靠性传输,随便介绍网络协议的概念,Web Service为什么不支持可靠性传出 ...

  2. spring_150805_datasource

    实体类: package com.spring.model; public class DogPet { private int id; private String name; private in ...

  3. 一个tomcat上放多个webapp问题,那这多个webapp会不会竞争端口呢?不会!安全两码事

    1.一个tomcat上放多个webapp问题,那这多个webapp会不会竞争端口呢?不会!安全两码事

  4. Spring框架学习之第8节

    <bean id=”foo” class=”…Foo”> <property name=”属性”> <!—第一方法引用--> <ref bean=”bean对 ...

  5. Hibernate笔记——Hibernate介绍和初次环境配置

    Hibernate简介 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate ...

  6. iOS URL中汉字的编码和解码

    发现NSString类中有内置的方法可以实现.他们分别是: - (NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncod ...

  7. hadoop安装配置——伪分布模式

    1. 安装 这里以安装hadoop-0.20.2为例 先安装java,参考这个 去着下载hadoop 解压 2. 配置 修改环境变量 vim ~/.bashrc export HADOOP_HOME= ...

  8. 原生javascript-常用的函数

    [一]添加监听事件 addHandler:function(node,type,fn){if(node.addEventListener){ node.addEventListener(type,fn ...

  9. Android处理Bitmap的一些方法

    http://www.it165.net/pro/html/201305/5795.html # 文件与Bitmap间的方法 1. 从文件载入Bitmap 01./** 02.* @brief 从文件 ...

  10. JQUERY与JS的区别

    JQUERY与JS的区别 <style type="text/css"> #aa { width:200px; height:200px; } </style&g ...