【C语言小游戏】走迷宫
#include<bits/stdc++.h>
#include<>
#include<>
using namespace std;
#define MAXN 50//迷宫大小
typedef struct//BFS寻路用
{
int x,y;
int step;
}Pos;
Pos start,finish,path[2500];//起点,终点,路径
int k;//BFS路径标记
int Rank=10;//控制难度,Rank越小难度越大
int maze[MAXN][MAXN];
int bookBFS[MAXN][MAXN];//用于BFS是否访问标记
int visit[MAXN][MAXN];//标记BFS的过程
void BFS();//BFS最短路径寻路
void Gamer();//用户操作界面
void DrawMaze();//绘制迷宫
void DrawPath();//绘制路径
void choice_level();//选择关卡
void CreateMaze(int,int,int);//创建迷宫
void gotoxy(int,int);//坐标函数
void InitMaze();//初始化迷宫
void load_cartoon();//加载动画
void HideCursor();//隐藏光标
void ShowCursor();//显示光标
//加载动画
char cartoon1[20][150] = {
{" /~/~/ "},
{" /~/~/ "},
{" Microsotf@ ~ ~ __ XP "},
{" \\ /\\ / - _ _| _ _ _ /_ "},
{" \\/ \\/ | | | |_| |_| \\/\\/ __/ "},
{" "},
{" _____________________ "},
{" │ │ "},
{" └────────────────────┘ "},
{" "},
{" "},
{" "},
{" "},
{" "},
{" "},
{" Copyright ΘMicrosoft Corporation Microsoft* "},
};
char cartoon2[40][150]={
{" 健 康 游 戏 忠 告 "},
{" "},
{" "},
{" "},
{" "},
{" 抵 制 不 良 游 戏 , 拒 绝 盗 版 游 戏。 "},
{" "},
{" "},
{" "},
{" "},
{" 注 意 自 我 保 护 , 谨 防 受 骗 上 当。 "},
{" "},
{" "},
{" "},
{" "},
{" 适 度 游 戏 益 脑 , 沉 迷 游 戏 伤 身。 "},
{" "},
{" "},
{" "},
{" "},
{" 合 理 安 排 时 间 , 享 受 健 康 生 活。 "},
};
//Logo
char logo[30][100]={
{" BBBBB BBBBBP BBBBBBB "},
{" SBBBM BQBBBQ BBBBBBB "},
{" BBBBBBB. iEBBBI BBBBQE gBBQP: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "},
{" uBBBBBBv 1BBBBBB BBBBBb BQBBBBJ BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "},
{" :BBBBBBQ .BBBBBB. BBQBBd iBBBBBB BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "},
{" .BQBB5. BQBQBB BBBBBq IBBBBBZ BBBBBB BBBBBB "},
{" d. BBBr BBBBBq :RBBi BBBBBB BBBBBB "},
{" BBBBB2 BBBBBDBBQBBBBBBBBBBBQBBBBBBBBBQBQBBBBBBB "},
{" Ivv7vr77j. 1BBBBBMBBBBBBBBBBBBBQBRQBBBBBR BQBBBBBBBQBBBBBQBBBBBBBBBQBB "},
{" :BBBBBBBBB7 KBBQBBBBBBBBBQBQBQBQBBBQBQBBBB BBBBBB BBBBBB "},
{" :BBBBBBBBB: 2BQBBBBBQBBBBBBBBBBBBBBBBBBBBQ BBBBBB BBBQBE "},
{" .BQbQBBBBBi QBBBBBBB1 BBBBBB BBBBBB "},
{" .BBBBBi 7QBBBQBQBBL BB: BBBBBBBBBQBBBBBBBBBBBBBQBBBQ "},
{" iBBBBBi :BBBBBBBBBBBBBBBBBs BBBBBBBBBBBBQBBBBBBBBBBBQBBM "},
{" iBBBBB: :BBBBQBg MBQBBMEBBBBBQd "},
{" rBBBBB: iBBBQBBBU BBBBBj .BQBBBBBM: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "},
{" iBBBBB. BBBBBBBB. BBQBBb :QBBBBBBK BBBBQBBBBBBBBBQBQBBBBBBBBBBBBBQBBB "},
{" :QBBBQ. .QBBBBY BBBBBd iBBBBr BBBBBBBBBBBQBBBBBBBQBBBQBBBBBBBBBB "},
{" LBBBBB7 :B2 QBBBBg sZ BBBBBB BBBBQB "},
{" rBBBBBBBBM. BBBQB1 BQBBBB BBBBBB "},
{" iBBBBBBBQBBBBBE BBBBQB BBBBBB "},
{" .BBBBQBSBBBBBBBQBQBBBBBBBBBBBBBBBBBBBBBBBB. BBBBBQBBBBBQBBBQBBBBBBBBBBBBBBBBBB "},
{" vBBQB. rBBQBQBQBBBQBBBQBBBBBQBBBBBBBBBBv BBQBBBBBQBBBBBQBQBBBBBBBBBBBQBBBBB "},
{" BBr sPDQMQBBBBBBBBBBBBBBQBBBBBBB BQBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB "},
{" BBBBBB BBBBBB "},
{" "},
{" 制 作 "},
{" "},
{" 山 河 "}
};
//坐标函数
void gotoxy(int x, int y)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
//隐藏光标
void HideCursor()
{
CONSOLE_CURSOR_INFO cursor_info={1,0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
//显示光标
void ShowCursor()
{
CONSOLE_CURSOR_INFO cursor_info={1,1};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
}
//初始化迷宫
void InitMaze()
{
for(int i=0;i<MAXN;i++)
for(int j=0;j<MAXN;j++)
maze[i][j]=1;
for(int i=0;i<MAXN;i++)
{
maze[i][0]=0;
maze[0][i]=0;
maze[MAXN-1][i]=0;
maze[i][MAXN-1]=0;
}
k=0;
memset(bookBFS,0,sizeof(bookBFS));
memset(path,0,sizeof(path));
memset(visit,0,sizeof(visit));
}
//创建仅有一条路径的迷宫
void CreateMaze(int x, int y,int Rank) {
maze[x][y] = 0;
//确保四个方向随机
//每一次挖的顺序不同,如前左右,右前左
int dir[4][2] = { { 1,0 },{ -1,0 },{ 0,1 },{ 0,-1 } };
for (int i = 0; i < 4; i++) {
int r = rand() % 4;
//随机交换
int temp = dir[0][0];dir[0][0] = dir[r][0];dir[r][0] = temp;
temp = dir[0][1];dir[0][1] = dir[r][1];dir[r][1] = temp;
}
//向四周开挖
for (int i = 0; i < 4; i++) {
int dx = x;
int dy = y;
//控制挖的距离,由Rank来调整大小
int range = 1 + (Rank == 0 ? 0 : rand() % Rank);
while (range>0) {
dx+=dir[i][0];
dy+=dir[i][1];
//排除掉回头路
if (maze[dx][dy] == 0) break;
//判断是否挖穿路径
int count = 0;
for (int j = dx - 1; j < dx + 2; j++)
for (int k = dy - 1; k < dy + 2; k++)
if (abs(j - dx) + abs(k - dy) == 1 && maze[j][k] == 0) count++;
if (count > 1)
break;
//确保不会挖穿时,前进
range--;
maze[dx][dy] = 0;
}
if (range <= 0)
CreateMaze(dx,dy,Rank);
}
}
void DrawMaze()
{
//入口
maze[2][1]=0;
start.x=2;start.y=1;start.step=0;
//出口
for(int i=MAXN-3;i>=0;i--)
if(maze[i][MAXN-3]==0){
maze[i][MAXN-2]=0;
finish.x=i;finish.y=MAXN-2;finish.step=0;
break;
}
for(int i=0;i<MAXN;i++){
for(int j=0;j<MAXN;j++){
if(maze[i][j]==1)cout<<"■";
else cout<<" ";
}
cout<<endl;
}
}
//迷宫寻路BFS,当迷宫只有一条路径,用BFS更省时
void BFS()
{
queue<Pos>q;
q.push(start);
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
bookBFS[start.x][start.y]=1;
int flag=0;
while(q.size()!=0)
{
Pos t=q.front();
q.pop();
if(t.x==finish.x&&t.y==finish.y)//找到终点
{
flag=1;
finish.step=t.step;
Pos t=finish;//倒推路径
while(!(t.x==start.x&&t.y==start.y))//不在起点的时候
{
path[k].x=t.x;path[k++].y=t.y;
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
for(int i=0;i<4;i++){
Pos s=t;
s.x+=dx[i];s.y+=dy[i];
if(s.x<=0||s.x>MAXN-2||s.y<=0||s.y>MAXN-2||maze[s.x][s.y]==1)continue;//超出范围
if(visit[s.x][s.y]==visit[t.x][t.y]-1){t.x=s.x;t.y=s.y;break;}//倒退回去
}
}
path[k]=start;//放入起点
}
if(flag==1)break;
//向四个方向扩展
for(int i=0;i<4;i++)
{
Pos p=t;
p.x+=dx[i];p.y+=dy[i];p.step++;
if(p.x<=0||p.x>MAXN-2||p.y<=0||p.y>MAXN-2||maze[p.x][p.y]==1||bookBFS[p.x][p.y]==1)
continue;
bookBFS[p.x][p.y]=1;
visit[p.x][p.y]=p.step;
q.push(p);
}
}
}
//绘制最短路径BFS
void DrawPath()
{
//路径坐标
int flag=0;
int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};
string road;
for(int i=k;i>=0;i--)
{
if(flag==0){flag=1;road="──";}//第一次进入
Pos t=path[i];//当前打印位置
if(flag==1&&i!=0){
Pos s=path[i+1];//存储上一个位置
Pos p=path[i-1];//存储下一个位置
int tx1,tx2,ty1,ty2;
tx1=t.x-s.x;ty1=t.y-s.y;
tx2=t.x-p.x;ty2=t.y-p.y;
//"┘""┐""└""┌""──""│"
if((tx1==-1&&tx2== 1&&ty1== 0&&ty2== 0)||(tx1== 1&&tx2==-1&&ty1== 0&&ty2== 0))road="│";
if((tx1== 0&&tx2== 0&&ty1== 1&&ty2==-1)||(tx1== 0&&tx2== 0&&ty1==-1&&ty2== 1))road="──";
if((tx1== 0&&tx2==-1&&ty1== 1&&ty2== 0)||(tx1==-1&&tx2== 0&&ty1== 0&&ty2== 1))road="┐";
if((tx1== 1&&tx2== 0&&ty1== 0&&ty2==-1)||(tx1== 0&&tx2== 1&&ty1==-1&&ty2== 0))road="└";
if((tx1==-1&&tx2== 0&&ty1== 0&&ty2==-1)||(tx1== 0&&tx2==-1&&ty1==-1&&ty2== 0))road="┌";
if((tx1== 1&&tx2== 0&&ty1== 0&&ty2== 1)||(tx1== 0&&tx2== 1&&ty1== 1&&ty2== 0))road="┘";
}
if(i==0)road="─";//出口位置
gotoxy(2*t.y,t.x);//每个方格占两个单位
cout<<road;
}
}
//玩家控制界面
void Gamer()
{
int x=2;int y=1;//maze行,列
int posx=2;int posy=2;//横着每次变化2,竖着每次移动变化1,这个是坐标
int stepx=2*MAXN+19,stepy=26;//步数刷新的位置
char ch1,ch2;
int gamerstep=0;//玩家走的步数
//隐藏光标
HideCursor();
//绘制
gotoxy(posx,posy);cout<<"●";//绘制起点
gotoxy(2*MAXN+5,2);cout<<"当前关卡:"<<10-Rank;
gotoxy(2*MAXN+5,5);cout<<"方 向 控 制";
gotoxy(2*MAXN+10,9);cout<<"W";
gotoxy(2*MAXN+7,11);cout<<"A S D";
gotoxy(2*MAXN+10,15);cout<<"或";
gotoxy(2*MAXN+10,19);cout<<"↑";
gotoxy(2*MAXN+6,22);cout<<"← ↓ →";
gotoxy(2*MAXN+3,26);cout<<"您 走 的 步 数:";
gotoxy(2*MAXN+3,30);cout<<"按下列选项序号即可呼出选择";
gotoxy(2*MAXN+3,34);cout<<"1 .查看最短路径";
gotoxy(2*MAXN+3,38);cout<<"2 .重新选择关卡";
gotoxy(2*MAXN+3,42);cout<<"3 .退出游戏";
while(!(x==finish.x&&y==finish.y)){
//同时启用wasd和方向键
ch1=getch();
if(ch1==-32)//方向键为双键值
{
ch2=getch();
switch(ch2)
{
case 72:ch1='w';break;//上
case 80:ch1='s';break;//下
case 75:ch1='a';break;//左
case 77:ch1='d';break;//右
default: break;
}
}
switch(ch1)
{
case 'w':
case 'W':
if(maze[x-1][y]==0){
gotoxy(posx,posy);cout<<" ";
x--;posy--;gamerstep++;
gotoxy(posx,posy);cout<<"●";
gotoxy(stepx,stepy);cout<<gamerstep;//实时刷新走的步数
}break;
case 's':
case 'S':
if(maze[x+1][y]==0){
gotoxy(posx,posy);cout<<" ";
x++;posy++;gamerstep++;
gotoxy(posx,posy);cout<<"●";
gotoxy(stepx,stepy);cout<<gamerstep;
}break;
case 'a':
case 'A':
if(maze[x][y-1]==0&&y-1>=1){
gotoxy(posx,posy);cout<<" ";
y--;posx-=2;gamerstep++;
gotoxy(posx,posy);cout<<"●";
gotoxy(stepx,stepy);cout<<gamerstep;
}break;
case 'd':
case 'D':
if(maze[x][y+1]==0){
gotoxy(posx,posy);cout<<" ";
y++;posx+=2;gamerstep++;
gotoxy(posx,posy);cout<<"●";
gotoxy(stepx,stepy);cout<<gamerstep;
}break;
case '1':
BFS();DrawPath();
gotoxy(2*MAXN+3,46);cout<<"最少要走:"<<finish.step<<"步";break;
case '2':
choice_level();return ;
case '3':
system("cls");
return ;
}
}
system("cls");
int grade=100-(gamerstep-finish.step),choice=0;
if(grade<=0)grade=0;
gotoxy(79,12);
cout<<"恭喜你通过了本关";
gotoxy(80,16);
cout<<"您的得分为:"<<grade;
gotoxy(70,20);
cout<<"温馨提示:用的步数越少,得分越高哦^.^!"<<endl;
gotoxy(79,24);
cout<<"是否继续下一关";
gotoxy(79,28);
cout<<"1. 是 2.否";
gotoxy(82,32);
cin>>choice;
if(choice==1){
InitMaze();
CreateMaze(2,1,--Rank);
system("cls");
DrawMaze();
Gamer();
}
else{
system("cls");
return;
}
}
void load_cartoon()
{
//动态加载页面
int i,l, j;
gotoxy(25, 15);
for (i = 0; i <= 16; i++)
{
cout<<cartoon1[i];
gotoxy(25,16+i);
Sleep(100);
}
for (l = 0; l < 3; l++)
{ //动态加载开机页面
for (i = 53; i <= 71; i = i + 2)
{
for (j = i - 4; j <= i; j = j + 2)
{
if (j >= 53 && j <= 70)
{
gotoxy(j+25, 22);
printf("[]");
}
Sleep(100);
}
for (j = i - 4; j <= i; j = j + 2)
{
if (j >= 53 && j <= 70)
{
gotoxy(j+25, 22);
printf(" ");
}
}
}
}
//隐藏光标
HideCursor();
//游戏忠告
system("cls");
for (i = 0; i <= 20; i++)
{
gotoxy(25, 10+i);
cout<<cartoon2[i];
}
Sleep(4000);
//展示logo
system("cls");
for (i = 0; i <30; i++)
{ gotoxy(40,10+i);
cout<<logo[i];
}
Sleep(3000);
}
//关卡选择界面
void choice_level()
{
ShowCursor();
system("cls");
int level;
gotoxy(75,20);
cout<<"请输入你要选择的关卡(1-10):";
cin>>level;
Rank=10-level;
InitMaze();
CreateMaze(2,1,Rank);
//重新初始化
system("cls");
DrawMaze();
Gamer();
}
int main()
{
srand((unsigned)time(NULL));//用时间做随机数种子
system("mode con cols=200 lines=100");
system("color 00");
load_cartoon();
system("color 70");
choice_level();
gotoxy(75,20);
system("pause");
return 0;
}