迷宮

迷宮
/* 源碼名稱:迷宮
* * 日期:2012.10.27
 * 程序功能:迷宮遊戲
* * 作者:侯興鼎
 */
#include
using namespace std;
//
//customspass:迷宮當前所在關關數,默認爲第1關;
//count:將數據(x,y)入棧次數的累加
//
int customspass=1,count=0;
//
//設置迷宮數組的最大範圍
//如需改變關數,可通過改變SIZE值來增加或減小範圍
//
#define SIZE 20
/*
* * 方向結點結構體
 */
template 
struct Node
{
 T data1,data2; //data1(x),data2(y)
    Node *next;  //此處也可以省略
};
/*
* * 迷宮通路存儲棧
 */
class MazeStack
{
public:
    MazeStack( );    //置空鏈棧
    ~MazeStack();    //釋放鏈棧中各結點的存儲空間
 void Push(int x,int y);  //將元素x,y入棧
    void Pop();    //將棧頂元素出棧
 private:
  Node *top;   //棧頂指針即鏈棧的頭指針
};
/*
* * 迷宮類
 */
class Maze     
{
public:
 Maze();
 ~Maze(){} 
 void Display();    //迷宮圖顯示函數 
protected:
 char M[SIZE][SIZE];   //迷宮圖存儲
};
/*
* * 迷宮行走方向類
 */
class Move:public Maze  
{
public:
 Move(int X=1,int Y=1):
  x(X),y(Y){}
 void Remove(MazeStack &t);  //行走函數
 void AutoMatic(MazeStack &t); //自動行走函數
protected:
 intx,y;      //行走方向座標數據(x,y)
}; 
/*
* * 迷宮圖構造函數
 */
Maze::Maze()    
{
 //
 //第一關迷宮圖定義
 //
 if(customspass==1)
 {
  char m[10][10]={
  {1,1,1,1,1,1,1,1,1,1}, //0
  {1,12,1,1,1,0,1,1,1,1}, //1
  {1,1,0,1,0,1,1,1,1,1}, //2
  {1,0,1,0,0,0,0,0,0,1}, //3
  {1,0,1,1,1,0,1,1,1,1}, //4
  {1,1,0,0,1,1,0,0,0,1}, //5
  {1,0,1,1,0,0,1,1,0,1}, //6
  {1,1,0,1,1,1,0,0,1,1}, //7
  {1,0,1,0,1,1,1,1,3,1}, //8
  {1,1,1,1,1,1,1,1,1,1}}; //9
    //0  2  4  6  8 
  //
  //通過關數(customspass)來判斷迷宮圖的寬和高
  //給迷宮圖數組初始化
  //
  for(int y=0;y<5*(customspass+1);y++)
   for(int x=0;x<5*(customspass+1);x++)
    M[y][x]=m[y][x];
 }
 //
 //第二關迷宮圖定義
 //
 if(customspass==2)     
 {
  char m[15][15]={
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, //0
  {1,12,1,0,0,1,0,1,0,1,0,0,1,0,1}, //1
  {1,1,0,1,1,0,1,0,1,0,1,1,0,1,1}, //2
  {1,0,1,1,0,1,0,1,1,1,1,0,1,0,1}, //3
  {1,1,0,1,0,1,0,1,1,0,1,0,1,1,1}, //4
  {1,1,0,1,0,1,1,0,0,1,0,1,1,0,1}, //5
  {1,1,1,0,1,0,1,1,1,1,1,0,0,1,1}, //6
  {1,1,0,1,1,1,0,1,1,0,1,1,1,0,1}, //7
  {1,0,1,0,1,1,1,1,1,1,0,1,0,1,1}, //8
  {1,1,1,1,0,1,0,1,0,1,1,0,1,0,1}, //9
  {1,1,0,0,1,0,1,0,1,0,1,1,0,1,1}, //10
  {1,0,1,0,1,1,1,1,1,1,1,1,0,1,1}, //11
  {1,1,0,1,1,0,1,0,1,0,1,0,1,0,1}, //12
  {1,0,1,0,0,1,0,1,0,1,0,1,0,3,1}, //13
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}; //14
    //0  2  4  6  8 10  12  14
  //
  //通過關數(customspass)來判斷迷宮圖的寬和高
  //給迷宮圖數組初始化
  //
  for(int y=0;y<5*(customspass+1);y++)
   for(int x=0;x<5*(customspass+1);x++)
    M[y][x]=m[y][x];
 }
 //
 //第三關迷宮圖定義
 //
 if(customspass==3)    
 {
  char m[20][20]={
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, //0
  {1,12,1,1,1,0,1,1,0,1,1,0,0,1,0,1,1,1,0,1}, //1
  {1,1,0,1,0,1,1,1,0,1,0,1,1,0,1,0,1,0,1,1}, //2
  {1,0,1,0,0,0,0,0,1,1,0,1,0,1,1,1,0,1,0,1}, //3
  {1,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,0,1,0,1}, //4
  {1,1,0,0,1,1,0,0,0,1,1,0,1,1,0,1,0,1,0,1}, //5
  {1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,0,1,1,0,1}, //6
  {1,1,0,1,1,1,0,1,1,0,1,0,1,1,0,1,0,1,1,1}, //7
  {1,1,1,0,1,1,1,1,0,1,0,1,1,0,1,1,1,0,1,1}, //8
  {1,1,0,1,1,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1}, //9
  {1,0,1,1,1,0,1,0,1,1,1,1,1,0,1,1,1,1,1,1}, //10
  {1,1,1,0,1,0,1,1,0,1,0,1,0,1,1,0,0,0,1,1}, //11
  {1,1,0,1,0,1,0,1,1,0,1,0,1,1,0,1,1,1,1,1}, //12
  {1,0,1,1,1,1,0,0,1,1,1,1,1,0,1,1,0,0,1,1}, //13
  {1,1,0,0,0,0,1,1,0,1,1,1,1,0,1,0,1,1,0,1}, //14
  {1,1,0,1,1,1,1,0,1,1,0,1,1,0,1,0,1,0,1,1}, //15
  {1,0,1,1,1,0,1,1,1,0,1,0,0,1,0,1,1,1,0,1}, //16
  {1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1}, //17
  {1,1,1,0,1,1,1,0,0,1,1,1,1,0,1,1,1,1,3,1}, //18
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}}; //19
    //0  2  4  6  8 10  12  14  16  18
  //
  //通過關數(customspass)來判斷迷宮圖的寬和高
  //給迷宮圖數組初始化,
  //
  for(int y=0;y<5*(customspass+1);y++)
   for(int x=0;x<5*(customspass+1);x++)
    M[y][x]=m[y][x];
 }
}
/*
* * 迷宮圖顯示函數
 */
void Maze::Display()     
{
 //
 //通過關數(customspass)來判斷顯示迷宮圖
 //
 for(int y=0;y<5*(customspass+1);y++)
 {
  for(int x=0;x<5*(customspass+1);x++)
   cout<<" "<<M[y][x];
  cout<<endl;
 }
}
/*
* * 方向顯示函數:通過座標顯示方向,便於用戶觀看
 */
void Direction(int x,int y)
{
 if(x==1&&y==0)
  cout<<"右"<<' ';
 if(x==1&&y==1)
  cout<<"右下"<<' ';
 if(x==0&&y==1)
  cout<<"下"<<' ';
 if(x==-1&&y==1)
  cout<<"左下"<<' ';
 if(x==-1&&y==0)
  cout<<"左"<<' ';
 if(x==-1&&y==-1)
  cout<<"左上"<<' ';
 if(x==0&&y==-1)
  cout<<"上"<<' ';
 if(x==1&&y==-1)
  cout<<"右上"<<' ';
}
/*
* * 迷宮行走函數
 */
void Move::Remove(MazeStack & t)    
{
 //
 //abscissa:表示當前位置的橫座標;
 //ordinate:表示當前位置的縱座標
 //charnumber:表示行走方向的字符型編碼
 //
 int abscissa=1,ordinate=1;
 char charnumber; 
 //
 //行走方向數組
 //
 Move move[8]={
  Move(1,0),  //0右
  Move(1,1),  //1右下
  Move(0,1),  //2下
  Move(-1,1),  //3左下
  Move(-1,0),  //4左
  Move(-1,-1), //5左上
  Move(0,-1),  //6上
  Move(1,-1)}; //7右上
 //
 //行走判斷功能
 //
 while(1)
 {
  cout<<"請輸入您下一步要走的方向編碼(0~7):"<<endl;
  cout<<"(編碼:右:0/右下:1/下:2/左下:3/左:4/左上:5/上:6/右上:7)"<<endl;
  cin>>charnumber; //輸入字符型方向編碼
  //
  //判斷輸入行走方向符合要求
  //
  if(charnumber>='0'&&charnumber<='7')     
  { 
   //
   //intnumber:表示整型方向編碼
   //將輸入的字符型編碼轉化爲整型編碼
   //
   int intnumber=charnumber-48;
   //
   //判斷是障礙物
   //
   if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==1)  
    cout<<"此處無路!"<<endl; 
   //
   //判斷不是障礙物
   //
   else
   {
    //
    //終點判斷
    //
    if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==3) 
    {
     M[ordinate][abscissa]=0;      //清除行走痕跡
     //行走前進顯示
     M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]=12;
     Display();
     t.Push (move[intnumber].x,move[intnumber].y ); //行走方向數據入棧
     count++;          //棧內數據信息總數加1
     cout<<"恭喜您順利通過第"
      <<customspass<<"關!"<<'\a'
      <<'\a'<<'\a'<<endl;
     break;           //結束本關遊戲
    }
    M[ordinate][abscissa]=0;       //清除行走痕跡
    abscissa+=move[intnumber].x;      //改變當前位置橫座標值
    ordinate+=move[intnumber].y;      //改變當前位置縱座標值
    M[ordinate][abscissa]=12;       //行走前進顯示
    t.Push(move[intnumber].x,move[intnumber].y);  //行走方向數據入棧
    Display();
    count++;           //棧內數據信息總數加1
    cout<<'\a'; 
   }
  }
  //
  //判斷輸入行走方向不符合要求
  //
  else
   cout<<"輸入錯誤!"<<endl;
 }
}
/*
* * 系統自動行走
 */
void Move::AutoMatic(MazeStack & t)
{
 //
 //abscissa:表示當前位置的橫座標;
 //ordinate:表示當前位置的縱座標
 //intnumber:表示行走方向編碼
 //mark給死路做個標記
 //
 int abscissa=1,ordinate=1;
 int intnumber=0; 
 int mark=0;   
 //
 //行走方向數組
 //
 Move move[8]={
  Move(1,0),  //0右
  Move(1,1),  //1右下
  Move(0,1),  //2下
  Move(-1,1),  //3左下
  Move(-1,0),  //4左
  Move(-1,-1), //5左上
  Move(0,-1),  //6上
  Move(1,-1)}; //7右上
 //
 //行走判斷功能
 //
 while(1)
 { 
  //
  //判斷是倒走
  //
  if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==16) 
  {
   //
   //判斷是無路可走
   //爲了確保每個方向都走過,把無路標記mark定義爲2
   //
   if(mark==2)
   { //倒退一步顯示
    M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]=12;
    M[ordinate][abscissa]=33;  //標記無路記號
    cout<<"清除走過路徑存儲:";
    t.Pop();      //清除走過路徑方向數據
    abscissa+=move[intnumber].x; //改變當前位置橫座標值
    ordinate+=move[intnumber].y; //改變當前位置縱座標值
    count--;      //棧內數據信息總數減1
    intnumber=0;     //方向編碼初始化
    mark=0;       //無路標記初始化
   }
   //
   //判斷不是無路可走
   //
   else
   { //
    //判斷方向編碼沒有超出範圍
    //
    if(intnumber!=7)
    {
    mark++;    //無路標記加1
    intnumber++;  //方向編碼加1
    }
    //
    //判斷方向編碼超出範圍
    //
    else
    {
     mark=2;   //無路標記設置爲2實現無路功能
     intnumber=0; //方向編碼初始化
    }
   }
  }
  //
  //判斷不是倒走
  //
  else
   {
    //
    //判斷是障礙物
    //
    if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==1)  
    {
     //
     //判斷方向編碼達到最後一個方向編碼
     //
     if(intnumber==7) 
      intnumber=0; //方向編碼初始化
     //
     //判斷方向編碼達到最後一個方向編碼
     //
     else
      intnumber++; //進入下一方向
    } 
    //
    //判斷不是障礙物
    //
    else
    {
     //
     //終點判斷
     //
     if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==3) 
     {
      M[ordinate][abscissa]=16;      //走過標記
      //行走前進顯示
      M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]=12; 
      Display();
      t.Push (move[intnumber].x,move[intnumber].y); //行走方向數據入棧
      count++;          //棧內數據信息總數加1
      cout<<"恭喜您順利通過第"
      <<customspass<<"關!"<<'\a'
      <<'\a'<<'\a'<<endl;
      break;           //結束本關遊戲
     }
     //
     //有路可走
     //
     if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==0)
     {
      M[ordinate][abscissa]=16;      //給走過的路徑做下標記
      abscissa+=move[intnumber].x;     //改變當前位置橫座標值
      ordinate+=move[intnumber].y;     //改變當前位置縱座標值
      M[ordinate][abscissa]=12;      //行走前進顯示
      t.Push(move[intnumber].x,move[intnumber].y); //行走方向數據入棧
      count++;          //棧內數據信息總數加1
      intnumber=0;         //行走方向編碼初始化
      mark=0;           //無路標記初始化
     }
     //
     //判斷是死路
     //
     if(M[ordinate+move[intnumber].y][abscissa+move[intnumber].x]==33)
     {
      cout<<"此方向是死路!"<<endl;
      //
      //判斷方向編碼沒有達到最後一個方向編碼
      //
      if(intnumber!=7)
       intnumber++;  //行走方向編碼加1進入下一方向
      //
      //判斷方向編碼達到最後一個方向編碼
      //
      else
      {
       intnumber=0;  //行走方向編碼初始化
       mark=2;    //無路標記設置爲2實現無路功能
      }
     }
    }
   }
 }
}
/*
* * 迷宮通路存儲棧初始化
 */
MazeStack::MazeStack( )
{
 top=NULL; //迷宮棧初始化
}
/*
* * 迷宮通路存儲棧清除數據
 */
MazeStack::~MazeStack( )
{
 while (top)
 {
  Node *p;
  p=top->next;
        delete top;
        top=p;
 }
}
/*
* * 迷宮通路存儲棧行走方向(x,y)入棧
 */
void MazeStack::Push(int x,int y)
{
    Node *s;
 s=new Node;   
    s->data1 = x;  //申請一個數據域爲data1的結點s
    s->data2 = y;  //申請一個數據域爲data2的結點s
 s->next = top;
 top=s;    //將結點s插在棧頂
}
/*
* * 迷宮通路存儲棧行走方向(x,y)出棧
 */
void MazeStack::Pop( )
{  
    Node *p;
 int x,y;     //定義x,y用以存儲出棧的數據信息
    if (top==NULL)throw"下溢";
 x=top->data1;    //暫存棧頂元素data1
 y=top->data2;    //暫存棧頂元素data2
 p=top;
 top=top->next;    //將棧頂結點摘鏈
    delete p;
 Direction(x,y);    //調用方向顯示函數,方便用戶觀看
}
/*
* * 遊戲規則菜單顯示
 */
void Mune1()    
{
 //
 //a:顯示起點圖標及行走圖標;b:顯示終點圖標;c:顯示障礙物
 //
 char a=12,b=3,c=1;
 cout<<endl<<"**********************"<<endl<<endl;
 cout<<"  迷宮遊戲規則:"<<endl<<endl;
 cout<<"  起點:“"<<a<<"”"<<endl
  <<"  終點:“"<<b<<"”"<<endl
  <<"  “"<<c<<"”爲障礙物"<<endl
  <<"  空白處爲路。"<<endl;
 cout<<"方向編碼爲:"<<endl<<"  向右:0,向右下:1,"<<endl
  <<"  向下:2,向左下:3,"<<endl
  <<"  向左:4,向左上:5,"<<endl
  <<"  向上:6,向右上:7."<<endl<<endl;
 cout<<"**********************"<<endl;
}
/*
* * 遊戲選擇菜單顯示
 */
void Mune2()    
{
 cout<<endl<<"******************"<<endl<<endl;
 cout<<"請選擇:"<<endl
  <<"  1.下一關;"<<endl
  <<"  2.本關;"<<endl
  <<"  3.上一關;"<<endl
  <<"  4.遊戲重新開始;"<<endl
  <<"  5.導出路徑"<<endl<<endl;
 cout<<endl<<"******************"<<endl<<endl;
}
/*
* * 通關選擇
 */
void Mune3(int sign,MazeStack &ms)    
{
 char choose; //通關選擇編號
 cout<<"請輸入您的選擇編號(輸入:1~5)"<<endl;
 cin>>choose; //輸入選擇編號
 //
 //判斷是通關選擇範圍
 //
 if(choose<='5'&&choose>='1')
 {
  //
  //通關選擇
  //
  switch(choose)
  {
   //
   //下一關
   //
   case '1':
    //
    //判斷是最後一關
    //
    if(customspass>=SIZE/5-1)
    {
     cout<<"對不起!您已通過了最後一關!"<<endl;
     Mune3(sign,ms);  //重新輸入選擇
    }
    //
    //判斷不是最後一關
    //
    else
    {
     cout<<"你真棒,勇於挑戰!"<<endl;
     customspass++;  //關數加1
     count=0;   //入棧信息總數清零
    }
    break;
   //
   //本關
   //
   case '2': 
    cout<<"請不要害怕,繼續加油!"<<endl;
    count=0;    //入棧信息總數清零
    break;
   //
   //上一關
   //
   case '3':
    //
    //判斷是第一關
    //
    if(customspass<=1)
    {
     cout<<"對不起!您已經在第一關了!"<<endl;
     Mune3(sign,ms);  //重新輸入選擇
    }
    //
    //判斷不是第一關
    //
    else
    {
     cout<<"請不要退縮,想想就能過去!"<<endl;
     count=0;   //入棧信息總數清零
     customspass--;  //關數減1
    }
    break;             
   //
   //遊戲重新開始
   //
   case '4':
    cout<<"沒關係,我們從頭再來!"<<endl;
    count=0;    //入棧信息總數清零
    customspass=1;   //關數初始化
    break;
   //
   //導出路徑
   //
   case '5':
    if(sign==0)
    {
     cout<<"路徑(終點-起點):"<<count<<endl;
     for(int i=count;i>0;i--)
     ms.Pop();   //導出行走方向
     count=0;   //入棧信息總數清零
     sign++;    //sign加1,表示導出過路徑
    }
    else
     cout<<"路徑信息已被清除!"<<endl;
    Mune2();    //遊戲選擇菜單顯示
    Mune3(sign,ms);   //通關選擇
    break;
  }
 }
 //
 //判斷不是通關選擇範圍
 //
 else
 {
  cout<<"輸入錯誤!"<<endl;
  Mune3(sign,ms);   //通關選擇
 }
}
/*
* * 判斷是否要退出遊戲
 */
int ExitProcess(int exit,MazeStack &ms)
{
 char quit;    //遊戲是否退出判斷
 int sign=0;    //sign:標記有沒有導出過路徑
 cout<<endl<<endl;
 //
 //選擇判斷
 //
 while(1)
 {
  cout<<"是否退出遊戲?(是:“Y”;否:“N”)"<<endl;
  cin>>quit;
  //
  //判斷退出遊戲
  //
  if(quit=='Y')
  {
   exit=0;    //遊戲結束
   return exit;
  }
  //
  //判斷繼續遊戲
  //
  if (quit=='N')
  {
   Mune2();   //遊戲選擇菜單顯示
   Mune3(sign,ms);  //通關選擇
   break;
  }
  //
  //不在判斷範圍
  //
  else
   cout<<"輸入錯誤!"<<endl;
 }
}
/*
* * 迷宮自主通關和系統通關選擇
 */
void Choose(Maze &ma,Move &mo,MazeStack &ms)
{
 char choose;     //遊戲通關方式命令
 cout<<endl
  <<"****歡迎進入迷宮遊戲第"
  <<customspass<<"關!****"
  <<'\a'<<'\a'<<'\a'<<endl<<endl;
  ma.Display();    //顯示第n關迷宮圖
  cout<<"您要自己走迷宮,還是看看系統走迷宮?回答:Y(是),N(否)"<<endl;
  //
  //迷宮自主通關和系統通關選擇判斷
  //
  while(1)
  {
   cin>>choose;
   //
   //判斷是自主通關
   //
   if(choose=='Y')
   {
    mo.Remove(ms);  //調用自主通關算法
    break;
   }
   //
   //判斷是系統通關
   //
   if(choose=='N')
   {
    mo.AutoMatic(ms); //調用系統通關算法
    break;
   }
   //
   //不在判斷範圍
   //
   else
   {
    cout<<"輸入錯誤!"<<endl;
    cout<<"請重新輸入:"<<endl;
   }
  }
}
/*
* * 迷宮運行主函數
 */
void main()

 intexit;       //遊戲結束判斷標記
 Mune1();       //遊戲規則菜單顯示
 //
 //進入迷宮系統
 //
 while(exit)
 {
  //
  //類對象定義在循環裏纔可以實現多關
  //
  Maze ma;      //迷宮圖對象
  Movemo;      //迷宮行走對象
  MazeStackms;     //迷宮存儲棧對象
  Choose(ma,mo,ms);    //迷宮自主通關和系統通關選擇
  exit=ExitProcess(exit,ms);  //遊戲結束判斷
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章