* * 日期: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); //遊戲結束判斷
}
}