简单的八方向寻路算法

原创 2006年06月14日 19:29:00

 前几天在图书馆借了一本《游戏程序设计概论》,发现这本书还不错,对游戏有个大概的介绍。学了里面的四方向等高线寻路算法后,把它改成了八方向。大概原理是,从目的点开始向周围一步一步扩展,知道遇到起始点为止。用到了两个队列,一个作为源,一个作为目的。先把目的点放入源队列,在将目的点向八个方向扩展,并放入目的队列,然后交换源与目的,再将源队列中的点向周围扩展,并放入目的队列,如此循环,知道遇到起始点。标记好后,从起始点开始寻找最短路径。

程序代码:

#include <windows.H>
#include <stdio.h>
#include "Queue.h"

#define D_MapWidth 15
#define D_MapHeight 13
#define D_MapSize (D_MapWidth*D_MapHeight)

// 地图数据 15 X 13
// 0 : 不可移动的区域, 1 : 可移动区域.
// 起始坐标 [12,10], 目的坐标 [1,1]

int MapData[D_MapHeight*D_MapWidth] = {
  1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,
  1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,
  1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,
  1,1,1,0,0,1,1,1,1,1,0,1,1,1,1,
  1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,
  1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,
  0,1,1,1,1,1,1,0,0,1,1,1,1,0,0,
  0,1,1,1,1,1,0,0,1,1,1,1,0,0,0,
  0,0,1,1,1,0,0,1,1,1,0,0,0,0,0,
  0,0,0,1,0,0,0,1,1,1,0,1,1,1,1,
  0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,
  0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,
  0,0,0,0,1,1,1,1,1,1,1,0,0,0,0 };

int BackupMap[D_MapHeight*D_MapWidth];
int Path[D_MapHeight*D_MapWidth];
int CountOfPath = 0;

void QuickMapping ( int Posi_Target, int Posi_Start );
void PathRecorder( int StartPosi, int TargetPosi );
int GetStep  ( int Position, int &StepNo );
void ShowPath ( void );

///////////////////////////////////////////////////////////////////////////////

int main(int argc, char* argv[])
{
 int  Posi_Start = (10*D_MapWidth) + 12;
 int  Posi_Target = (1*D_MapWidth) + 1;
 bool Found = false;
 int  Step = 1;
 int  MapSize = D_MapSize;

 memset ( BackupMap, 0, sizeof(int) * MapSize );

 // 由目的点开始绘制"等高线"
 QuickMapping ( Posi_Target, Posi_Start );


 // 显示结果
 for ( int loopy=0 ; loopy<D_MapHeight ; loopy++ )
 {
  for ( int loopx=0 ; loopx<D_MapWidth ; loopx++ )
  {
   printf( " %02d", BackupMap[(loopy*D_MapWidth)+loopx] );
  }
  printf("/n");
 }

 // 计算路径
 PathRecorder( Posi_Start, Posi_Target );

 // 显示路径
 ShowPath();

 getchar();
 return 0;
}

///////////////////////////////////////////////////////////////////////////////

void QuickMapping ( int Posi_Target, int Posi_Start )
{
 clQueue RecA, RecB, *SrcPointer, *DesPointer;
 int  StepNo = 1,
   Position,
   MapSize = D_MapWidth * D_MapHeight,
   CurrentPosi,
   QueueSize;

 // 计算队列所需的容量, 并重新定义队列的大小.
 QueueSize = (D_MapWidth+D_MapHeight)*2;
 RecA.Resize ( QueueSize );
 RecB.Resize ( QueueSize );

 // 初始队列的功能.
 SrcPointer = &RecA;
 DesPointer = &RecB;

 // 先存入第一点的位置.
 SrcPointer->Push ( Posi_Target );
 BackupMap[Posi_Target]=StepNo++;

 for (;;)
 {
  // 当 SrcPointer 是空的时候.
  // 将 SrcPointer 与 DesPointer 对调.
  if ( !SrcPointer->Pop( CurrentPosi ) )//失败后就交换源与目的
  {
   if ( SrcPointer == &RecA ){
    SrcPointer = &RecB;
    DesPointer = &RecA;
   }
   else {
    SrcPointer = &RecA;
    DesPointer = &RecB;
   }
   StepNo++;
   if ( !SrcPointer->Pop( CurrentPosi ) ){
    return;      //如果仍失败则返回
   }
  }

  // 判断是否已经结束.
  if ( CurrentPosi == Posi_Start ) {
   BackupMap [ Posi_Start ] = --StepNo;//标记步数
   return;
  }

  /// 向上展开.
  Position = CurrentPosi - D_MapWidth;
  if ( Position >= 0 )  //是否越界
   if ( MapData[ Position ] != 0 )  //是否可行走
    if ( BackupMap[ Position ] == 0 ||BackupMap[ Position ] > StepNo ) //如果等于零,或步数比当前步数更大    
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }

  /// 向下展开.
  Position = CurrentPosi + D_MapWidth;
  if ( Position < MapSize )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )    
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }

  /// 向左展开.
  Position = CurrentPosi - 1;
  if ( (CurrentPosi%D_MapWidth) > 0 )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )    
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }

  /// 向右展开.
  Position = CurrentPosi+1;
  if ( (Position%D_MapWidth) < D_MapWidth )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )    
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }
  ///向左上
  Position = CurrentPosi-1-D_MapWidth;
  if ( (CurrentPosi%D_MapWidth) > 0&&Position >= 0 )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )     
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }
  ///向右上
  Position = CurrentPosi+1-D_MapWidth;
  if ( (Position%D_MapWidth) < D_MapWidth > 0&&Position >= 0 )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )     
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }
  ///向右下
  Position = CurrentPosi+1+D_MapWidth;
  if ( (Position%D_MapWidth) < D_MapWidth > 0&&Position < MapSize )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )     
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }
  ///向左下
  Position = CurrentPosi-1+D_MapWidth;
  if ( (CurrentPosi%D_MapWidth) >0 > 0&&Position < MapSize )
   if ( MapData[ Position ] != 0 )
    if ( BackupMap[ Position ] == 0 || BackupMap[ Position ] > StepNo )     
    {
     DesPointer->Push ( Position ); // 将展开点的位置存入目的队列.
     BackupMap [ Position ] = StepNo;//标记步数
    }
    
 }

}

///////////////////////////////////////////////////////////////////////////////
//
// 记录最短路径
//

void PathRecorder ( int StartPosi, int TargetPosi )
{
 int Step = BackupMap[ StartPosi ];
 int Index = 0;
 int Posi = StartPosi;

 Path[ Index++ ] = Posi;

 do {
  Posi = GetStep( Posi, Step );
  if ( Posi != -1 ){
   Path[ Index++ ] = Posi;
   if (  Posi == TargetPosi ){
    CountOfPath = Index;
    return;
   }
  }
  else {
   return;
  }
 } while ( true );
}

///////////////////////////////////////////////////////////////////////////////
//
// 选择最近的方向, 并返回位置.
//

int GetStep ( int Position, int &StepNo )
{
 int nUp = Position - D_MapWidth;
 int nDown = Position + D_MapWidth;
 int nLeft = Position - 1;
 int nRight = Position + 1;
 int nUpLeft=Position - D_MapWidth-1;
 int nUpRight=Position - D_MapWidth+1;
 int nDownLeft=Position + D_MapWidth-1;
 int nDownRight=Position + D_MapWidth+1;

 bool Found = false;

 // up.
 if ( nUp >= 0 ){
  if ( BackupMap[ nUp ] != 0 && BackupMap[ nUp ] < StepNo )   
  {
   StepNo = BackupMap[ nUp ];
   return nUp;
  }
 }

 // down.
 if ( nDown < D_MapSize ){
  if ( BackupMap[ nDown ] != 0 && BackupMap[ nDown ] < StepNo )   
  {
   StepNo = BackupMap[ nDown ];
   return nDown;
  }
 }

 // left.
 if ( (Position%D_MapWidth) > 0 ) {
  if ( BackupMap[ nLeft ] != 0 && BackupMap[ nLeft ] < StepNo )   
  {
   StepNo = BackupMap[ nLeft ];
   return nLeft;
  }
 }

 // right.
 if ( (nRight%D_MapWidth) != 0 ) {
  if ( BackupMap[ nRight ] != 0 && BackupMap[ nRight ] < StepNo )   
  {
   StepNo = BackupMap[ nRight ];
   return nRight;
  }
 }
 // UpRight.
 if ( (nUpRight%D_MapWidth) != 0&&nUpRight>= 0 ) {
  if ( BackupMap[ nUpRight ] != 0 && BackupMap[ nUpRight ] < StepNo )   
  {
   StepNo = BackupMap[ nUpRight ];
   return nUpRight;
  }
 }
 // UpLeft.
 if ( (Position%D_MapWidth) > 0 &&nUpLeft>= 0 ) {
  if ( BackupMap[ nUpLeft ] != 0 && BackupMap[ nUpLeft ] < StepNo )   
  {
   StepNo = BackupMap[ nUpLeft ];
   return nUpLeft;
  }
 }
 // DownLeft.
 if ( nDownLeft< D_MapSize &&nDownLeft>= 0 ) {
  if ( BackupMap[ nDownLeft ] != 0 && BackupMap[ nDownLeft ] < StepNo )   
  {
   StepNo = BackupMap[ nDownLeft ];
   return nDownLeft;
  }
 }
 // DownRight.
 if ( (nDownRight%D_MapWidth) != 0 &&nDownRight < D_MapSize ) {
  if ( BackupMap[ nDownRight ] != 0 && BackupMap[ nDownRight ] < StepNo )   
  {
   StepNo = BackupMap[ nDownRight ];
   return nDownRight;
  }
 }

 return -1;
}

///////////////////////////////////////////////////////////////////////////////
///
/// 显示路径
///

void ShowPath ( void )
{
 int Posi;

 memset( BackupMap, 0, sizeof(int) * D_MapSize );

 for ( int loop=0 ; loop<CountOfPath ; loop++ )
 {
  Posi = Path[ loop ];
  BackupMap[ Posi ] = 1;
 }

 printf("/n/n显示路径/n");
 for ( int loopy=0 ; loopy<D_MapHeight ; loopy++ )
 {
  for ( int loopx=0 ; loopx<D_MapWidth ; loopx++ )
  {
   printf( " %02d", BackupMap[(loopy*D_MapWidth)+loopx] );
  }
  printf("/n");
 }
}

用到的队列头文件:

class clQueue
{
private:
 unsigned int mCount;
 unsigned int mBufSize;
          int *mBuffer;
 unsigned int PushIndex;     // Push 数据存入端
    unsigned int  PopIndex;  // Pop 数据取出端

public:
 clQueue() : mCount(0), mBufSize(10), mBuffer(NULL), PushIndex(0), PopIndex(0)
 {
  mBuffer = new int[ mBufSize ];
 }
 ~clQueue()
 {
  if ( mBuffer != NULL ){
   delete [] mBuffer;
   mBuffer = NULL;
  }
 }

 bool Resize ( int NewSize ){
  if ( mBuffer != NULL ){
   delete [] mBuffer;
   mBuffer = NULL;
  }
  mBufSize = NewSize;
  if ( mBufSize == 0 ){ return true; }
  mBuffer = new int [ mBufSize ];
  return ((mBuffer==NULL) ? false : true);
 }

 bool Push ( int nNum )    // 存入数据.
 {
  if ( mCount >= mBufSize ){
   return false;
  }

  mBuffer[ PushIndex ] = nNum;
  PushIndex++;
  if ( PushIndex >= mBufSize ) {
   PushIndex = 0 ;
  }

  mCount++;

  return true;
 }

 bool Pop ( int &nNum )    // 取出数据
 {
  if ( mCount == 0 ){
   return false;
  }

  nNum = mBuffer[ PopIndex ];
  PopIndex ++;
  if ( PopIndex >= mBufSize ){
   PopIndex = 0;
  }

  mCount--;

  return true;
 }

};

程序运行结果:

02 02 02 03 00 00 00 00 00 12 13 14 15 16 17
02 01 02 03 00 00 00 00 11 12 13 14 15 16 17
02 02 02 03 00 00 10 10 11 12 13 14 15 16 17
03 03 03 00 00 09 09 10 11 12 00 14 15 16 17
04 04 00 00 00 08 09 10 00 00 00 15 15 16 17
05 05 05 06 07 08 09 00 00 00 16 16 16 16 00
00 06 06 06 07 08 09 00 00 17 17 17 17 00 00
00 07 07 07 07 08 00 00 18 18 18 18 00 00 00
00 00 08 08 08 00 00 19 19 19 00 00 00 00 00
00 00 00 09 00 00 00 20 20 20 00 24 24 00 00
00 00 00 00 00 22 21 21 21 21 00 23 24 25 00
00 00 00 00 23 22 22 22 22 22 22 23 24 00 00
00 00 00 00 23 23 23 23 23 23 23 00 00 00 00


显示路径
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
00 01 00 00 00 00 00 01 01 01 01 00 00 00 00
00 01 00 00 00 00 01 00 00 00 00 01 00 00 00
00 01 00 00 00 01 00 00 00 00 00 01 00 00 00
00 00 01 01 01 00 00 00 00 00 01 00 00 00 00
00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00 00 00 00 00 00 00 00 00 01 00 00 00 00 00
00 00 00 00 00 00 00 00 00 01 00 01 01 00 00
00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

原理与书上四方向是一样的,只是多了对左上,左下,右上,右下四个方向的处理。

一个高效的A-star寻路算法(八方向)

原帖:http://blog.sina.com.cn/s/blog_53a5865c0102dycw.html 原作者是http://www.codefans.net的JAROD 之所以说这个A-...
  • java886o
  • java886o
  • 2013年05月29日 10:34
  • 1448

A*算法学习笔记-(八方向,非最优解)

大体思路明白一动手就不行了先贴代码 等明白了在我那分析吧现在又有点乱了,因为A*不止一种思路,慢慢来吧--------------------------------------------思路明白了...
  • ibone
  • ibone
  • 2009年07月10日 13:38
  • 1375

一个高效的a *寻路算法(八方向)

http://blog.csdn.net/onafioo/article/details/41089579 这种写法比较垃圾,表现在每次搜索一个点要遍历整个地图那么大的数...
  • y13156556538
  • y13156556538
  • 2017年04月13日 10:27
  • 434

简单的八方向寻路算法

 前几天在图书馆借了一本《游戏程序设计概论》,发现这本书还不错,对游戏有个大概的介绍。学了里面的四方向等高线寻路算法后,把它改成了八方向。大概原理是,从目的点开始向周围一步一步扩展,知道遇到起始点为止...
  • ntwilford
  • ntwilford
  • 2006年06月14日 19:29
  • 1617

转算法方向了

前段时间面试受到了一些打击,也让我明白了我和这些做手机APP或者前端大类的面试官并没有太多共同语言。其实我知道怎么回事。某种意义上说,被拒只是因为我个人有点刚愎自用,性格有点不讨面试官喜欢。移动端开发...
  • wanghesai
  • wanghesai
  • 2016年09月19日 00:59
  • 339

A*寻路算法入门(四)

大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供...
  • mydo
  • mydo
  • 2015年11月22日 07:30
  • 1228

游戏寻路算法的简单实现

提到寻路算法,大家都会想到A*算法。 在度娘找了不少代码,看了不少教程之后,尤其是这个文章中提到的总结:http://www.cppblog.com/christanxw/archive/2006/...
  • Gnorth
  • Gnorth
  • 2013年06月19日 14:53
  • 2531

经典算法

1.河内之塔.. 2.Algorithm Gossip: 费式数列. 3. 巴斯卡三角形 4.Algorithm Gossip: 三色棋 5.Algorithm Gossip: 老鼠走迷官(一...
  • qq_27966627
  • qq_27966627
  • 2016年04月20日 13:57
  • 1066

迷宫问题(八个方向寻找)DFS

迷宫问题(八方向) input: 1 6 8 0 1 1 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 1 1 1 0 1 1 1 0 0 1 1 1 0 0...
  • u013021513
  • u013021513
  • 2014年11月04日 14:16
  • 819

Cocos2d-x 之 八方向小摇杆

Cocos2d-x 之 八方向小摇杆
  • lx417147512
  • lx417147512
  • 2015年08月20日 20:50
  • 3035
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:简单的八方向寻路算法
举报原因:
原因补充:

(最多只允许输入30个字)