数据结构:栈和队列-迷宫问题求解

类别:编程语言 点击:0 评论:0 推荐:

//--------------------文件名:Maze.cpp------------------------
//----------------------By SunxySong-------------------------
//说明:本程序以迷宫问题进行演示,了解栈和链表的数据结构.
//运行过程:随机生成迷宫地图(由于未详细设计算法,故地图较简单),
//         并演示找到出口路径的过程.
////////////////////////////////////////////////////////////
//主要算法思想:
// 1.初始化迷宫,构造辅助运行栈和结果链表
// 2.从入口开始
// do
// {
//  if (当前位置可通)
//  {
//   当前位置入栈
//   if (当前位置是出口)
//   {
//    结束
//   }
//   else
//   {
//    取得当前位置当前方向上的下一位置为当前位置
//    将新当前位置入栈
//   }
//  }
//  else
//  {
//   从栈中弹出栈顶元素为当前位置
//   while(当前位置已无下一有效位置 && 栈不为空)
//   {
//    将当前位置标记为无效
//    弹出栈顶元素为当前位置
//   }
//   if (当前位置还有下一有效位置时)
//   {
//    当前位置方向调整
//    当前位置进栈
//    取得取得当前位置当前方向上的下一位置为当前位置
//   }
//  }
// }while(栈不为空时);
// 未找到出口
// 3.生成新地图
// 4.显示地图
//////////////////////////////////////////////////////////////
//源代码在VC6+WIN2000sp2下编译通过

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <list>
#include <stack>
#include <time.h>

using namespace std;


//class:MazePos-----------------------------------------
//迷宫通道块类型
class MazePos
{
public:
 int wx,ly; //块的X,Y坐标 
 int path; //块的类型;0:空块,-1:墙壁,1:出口路径
 bool pass; //是否曾经过(对墙壁无意义);false:没有,true:曾经过
 bool operator==(const MazePos pos)
 {
  return (wx==pos.wx && ly==pos.ly );
 };
 MazePos operator=(const MazePos pos)
 {
  
  wx=pos.wx;
  ly=pos.ly;
  pass=pos.pass;
  path=pos.path;
  return *this;
 };
};
//End:MazePos---------------------------------------


//class:SElemType-----------------------------------------
//辅助栈元素类型
class SElemType
{
public:
 int ord; //迷宫通道块路径上的序号
 MazePos seat;  //通道块在迷宫中的位置坐标
 int di;  //从此通道块走向下一通道块的方向
    //0:无效,1:东,2:南,3:西,4:北
 bool operator==(const SElemType et)
 {
  return (seat==et.seat); 
 };
 SElemType operator=(const SElemType et)
 {
  ord =et.ord ;
  seat =et.seat ;
  di =et.di ;
  return (*this);
 };
};
//End:SElemType--------------------------------------


//struct:MazeMap-------------------------------------
//由通道块组成的迷宫地图
#define MAPWIDTH 10
#define MAPHEIGHT 10

typedef struct MazeMap
{
 //由通道块矩阵构成
 MazePos mazemap[MAPWIDTH][MAPHEIGHT];
}MazeMap;
//End:MazeMap---------------------------------------


//struct::MazeWay----------------------------------------
//辅助出口路径链表元素类型
typedef struct MazeWay
{
 int wx,ly;
}MazeWay;
//End:MazeWay--------------------------------------------


//Class:Maze----------------------------------------
//主体类,迷宫路径问题求解
class Maze
{
public:
 Maze(int width=MAPWIDTH,int height=MAPHEIGHT); //生成迷宫地图
 ~Maze();
 void DoMaze(); //找出出口路径并显示
private:
 bool InitOK; //初始化成功标志
 MazeMap map; //迷宫地图
 MazePos start,end; //迷宫的入口和出口
 bool FindPath(); //主要函数,寻找出口路径
 list<MazeWay> mazeway; //存放出口路径的临时链表
 void RandMap(); //随机生成迷宫地图函数
 bool CreateMap(bool init); //在初始和找到出口路径后生成相应地图函数
 bool pass(MazePos curpos); //当前路径通道块是否可通(即是不是未经过的空块)
 MazePos NextPos(MazePos curpos,int di); //取得当前通道块当前方向上的下一个通道块
 bool Invalide(SElemType e); //使当前通道块标记为不可通
 void DisplayMaze(); //显示迷宫地图

};

Maze::Maze(int width,int height)
{
 //
 //随机生成迷宫地图
 CreateMap(true);
 //显示地图
 DisplayMaze();
}

Maze::~Maze()
{
 //Add codes here
}

bool Maze::FindPath ()
{
 //
 //寻找出口,并生成出口路径链表
 if(InitOK)
 {
  //MazeStack mstack;
  stack<SElemType,list<SElemType> > mstack;
  MazePos curpos=start;
  int curstep=1; //经过的步数
  MazeWay mw; //出口路径块元素
  unsigned mwsize=mazeway.size (); //为显示运行过程而设
  do
  {
   if(pass(curpos))
   {
    //如果当前位置可通(即是未走过的空块)

    //封装栈元素,将当前位置进栈
    SElemType e;
    e.ord =curstep;
    e.seat =curpos;
    e.di =1;
    mstack.push (e);

    //保存当前位置到出口路径链表
    mw.wx =e.seat .wx ;
    mw.ly =e.seat .ly ;
    mazeway.push_back (mw);


    //如果是出口,则结束
    if(curpos==end)
     return true;

    //不然就将得到下一个通道块
    curpos=NextPos(curpos,e.di );
    curstep++;
   }
   else
   {
    //当前位置不可通,则在栈内找到下一个位置
    if(!mstack.empty())
    {
     SElemType e;
     e=mstack.top ();
     mstack.pop ();
     
     //调整出口路径链表
     mazeway.pop_back ();

     while((e.di==0 || e.di ==4) && !mstack.empty ())
     {
      Invalide(e);  //标记刻通道块不能通过
      e=mstack.top ();
      mstack.pop (); //退回一步

      //调整出口路径链表
      mazeway.pop_back ();

     }
     if(mstack.empty ())
      return false;
     else if( e.di<5)
     {
      e.di++;
      e.di=e.di%5;

      mstack.push (e);

      //保存当前位置到出口路径链表
      mw.wx =e.seat .wx ;
      mw.ly =e.seat .ly ;
      mazeway.push_back (mw);

      curpos=NextPos(e.seat ,e.di );
     }
     
    }
   }
   ///*//显示运行过程
   if(mwsize!=mazeway.size () )
   {
    CreateMap(false);
    DisplayMaze();
    mwsize=mazeway.size ();
    Sleep(800); //要包含windows.h头文件
   }
   //*
  }while(!mstack.empty ());
 }
 return false;
}

MazePos Maze::NextPos(MazePos curpos,int di)
{
 //
 MazePos pos;
 switch(di)
 {
 case 1:
  pos=map.mazemap [curpos.wx+1][curpos.ly ] ;
  break;
 case 2:
  pos=map.mazemap [curpos.wx][curpos.ly+1 ] ;
  break;
 case 3:
  pos=map.mazemap [curpos.wx-1][curpos.ly] ;
  break;
 case 4:
  pos=map.mazemap [curpos.wx][curpos.ly-1] ;
  break;
 }
 return pos;
}

bool Maze::pass(MazePos curpos)
{
 //
 //通过MazePos类型参数传递的信息检查MazeMap map;
 if(curpos.wx <0 ||
  curpos.wx >=MAPWIDTH ||
  curpos.ly <0 ||
  curpos.ly >=MAPHEIGHT)
  return false;
 return (map.mazemap [curpos.wx ][curpos.ly ].path ==0 &&
   map.mazemap [curpos.wx ][curpos.ly ].pass ==false );
 
}

void Maze::DoMaze ()
{
 //
 if(!InitOK)
  return;
 if(FindPath())
 {
  CreateMap(false);
  DisplayMaze();
 }
 else
 {
  cout<<endl<<"NO PATH!"<<endl;
 }
}

void Maze::RandMap ()
{
 //
 //只能生成从左上到右下的迷宫地图
 MazeWay curway; //随机生成的当前正处理的出口路径块(组成mw)
 list<MazeWay> mw; //随机生成的出口路径(由curway组成)
 list<MazeWay>::iterator iter; //容器适配器

 curway.wx =0;
 curway.ly =1;
 mw.push_back (curway);

 curway.wx ++;
 mw.push_back (curway);

 srand(time(0)); //取得当前时间作为随机数种子

 while(curway.wx <MAPWIDTH-1 && curway.ly <MAPHEIGHT-1)
 {
  if(rand()%2==1)
  {
   //生成随机X坐标上的路径块
   curway.wx ++;
   
   mw.push_back (curway);
  }
  else
  {
   //生成随机Y坐标上的路径块
   curway.ly ++;
   mw.push_back (curway);
  }
 }

 srand(time(0));
 for(int y=0;y<MAPHEIGHT;y++)
 {
  for(int x=0;x<MAPWIDTH;x++)
  {
   //填充每个通道块
   map.mazemap [x][y].wx =x;
   map.mazemap [x][y].ly =y;
   map.mazemap [x][y].pass =false;
   if(x==0||y==0||x==MAPWIDTH-1||y==MAPHEIGHT-1)
   {
    //生成四周墙壁
    map.mazemap [x][y].path =-1;
    //map.mazemap [x][y].pass =true;
   }
   else
   {
    if(rand()%10>=6) //数值越小,墙壁越多
    {
     map.mazemap [x][y].path =-1; //随机生成墙壁
     //map.mazemap [x][y].pass =true;
    }
    else
    {
     map.mazemap [x][y].path =0; //生成空的通道块
     //map.mazemap [x][y].pass =false;
    }
   } 
  }
 }
 //生成出口路径
 for(iter=mw.begin ();iter!=mw.end ();iter++)
 {
  map.mazemap [(*iter).wx ][(*iter).ly ].path =0;
  //map.mazemap [(*iter).wx ][(*iter).ly ].pass =false;
 }
 //生成入口和出口

 start=map.mazemap [mw.front ().wx][mw.front ().ly];
 end=map.mazemap [mw.back ().wx][mw.back ().ly];
 //初始化成功
 InitOK=true;
}

bool Maze::CreateMap (bool init)
{
 //
 if(init)
 {
  RandMap();
 }
 else
 {
  for(int y=0;y<MAPHEIGHT;y++)
   for(int x=0;x<MAPWIDTH;x++)
   {
    if(map.mazemap [x][y].path ==0)
     map.mazemap [x][y].pass =0;
   }
  list<MazeWay>::iterator  iter;
  for(iter=mazeway.begin ();iter!=mazeway.end ();iter++)
  {
   map.mazemap [(*iter).wx][(*iter).ly ].path =1;
  }
 }
 return true;
}

bool Maze::Invalide (SElemType e)
{
 //
 //通过SElemType类型参数传递的信息修正MazeMap map;
 if(e.seat .wx<0 ||
  e.seat .wx>=MAPWIDTH ||
  e.seat .ly<0 ||
  e.seat .ly>=MAPHEIGHT)
  return false;
 map.mazemap [e.seat .wx][e.seat .ly ].pass =true;
 return true;
}

void Maze::DisplayMaze ()
{
 //
 cout<<endl;
 for(int y=0;y<MAPHEIGHT;y++)
 {
  for(int x=0;x<MAPWIDTH;x++)
  {
   switch (map.mazemap [x][y].path)
   {
   case -1:
      cout<<"█";break; //墙壁图案
   case 0:
      cout<<"  ";break; //空块图案
   case 1:
      cout<<"==";break; //出口路径图案
   }
    
  }
  cout<<endl;
 }
 cout<<endl; 
}
//End:Maze----------------------------------------

//main--------------------------------------------
//主函数,迷宫求解演示
int main(int argc, char* argv[])
{
 //
 cout<<"下面是随机生成的迷宫:"<<endl;
 Maze mymaze; //生成迷宫
 cout<<"按任意键演示迷宫解法!"<<endl;
 system("pause");
 mymaze.DoMaze (); //生成出口路径
 cout<<"演示结束."<<endl;
 system("pause");
 return 0;
}
//End:main--------------------------------------------

下图为演示抓图

本文地址:http://com.8s8s.com/it/it21793.htm