创作背景
今天又是放元旦假的一天,无聊的我刷够了手机,就跑过去打开电脑······
熟悉的Dev-c++图标又映入我的眼帘,今天编点什么呢······
我绞尽脑汁,冥思苦想,终于想到了一个游戏——走迷宫。
今天的 走迷宫 游戏不会像之前的Blackjack游戏一样复杂,它只是非常简单的一个小游戏,也不太需要脑力,稍微地构造一个整体的框架,然后逐步细化就可以了。
玩法
玩家通过操纵按下键盘上的键(w--上,s--下,a--左,d--右,7--左上,9--右上,1--左下,3--右下,我个人觉得之所以我要用7、9、1、3这四个键,是因为这四个键在有小键盘的键盘上是分别居于左上、右上、左下、右下的位置,也许操控起来会更顺手)来控制移动方向,避开障碍,一直走到终点(迷宫大部分时候不存在迷宫无解的情况,因为我特地加了dfs深搜函数来确保迷宫有解,但我也不知道dfs深搜函数有没有用,如果在运行过程中遇到迷宫无解的情况,请在评论区吐槽,提前谢过)。
思路
首先在main()函数里面要输出 走迷宫 游戏的基本信息,让玩家先作了解;接着获取迷宫边长(1≤n,m≤10,也可以自己增减范围),对输入的n和m作不合法处理;然后根据n和m,随机生成一个迷宫界面;再编写一个dfs深搜函数,用来保证随机生成的迷宫界面有解(若无解就循环生成新的迷宫界面,直到迷宫界面有解),并随机确定起点坐标和终点坐标且令当前位置=起点坐标;再接下来就是走迷宫游戏的主体部分,获取玩家输入信息并作出相应移动;最后就是统计步数,结束游戏。
代码
走迷宫 游戏需要的头文件和宏定义:
#include<bits/stdc++.h>//万能头文件
#include<windows.h>//设置字体颜色
#include<conio.h>//_getch()函数
#define ge srand(static_cast<int>(time(NULL)));//产生随机数种子
走迷宫 游戏数组和变量:
int n/*长*/,m/*宽*/,u/*临时变量*/,sx/*起点x坐标*/,sy/*起点y坐标*/,ex/*终点x坐标*/,ey/*终点y坐标*/,cx/*当前位置x坐标*/,cy/*当前位置y坐标*/,stp/*当前步数*/;
int dx[]={0,-1,-1,-1,0,1,1,1,0}/*x方向*/,dy[]={0,-1,0,1,1,1,0,-1,-1}/*y方向*/;
bool b[11][11]/*标记搜索过*/,sg/*迷宫有解与否*/;
char a[11][11]/*迷宫*/,so,d;
crs(int,int)函数:为x,y作越界判断↓
bool crs(int x,int y){
return (x>0 && x<=n && y>0 && y<=m);//未越界
}
chk()函数:在玩家输入时作输入信息合法性判断↓
bool chk(){
if(d!='w' && d!='s' && d!='a' && d!='d' && d!='7' && d!='9' && d!='1' && d!='3')//不是w,a,s,d,7,9,1或3中的一个
return false;
switch(d){
case 'w':return (crs(cx-1,cy) && a[cx-1][cy]=='-');//↑
case 's':return (crs(cx+1,cy) && a[cx+1][cy]=='-');//↓
case 'a':return (crs(cx,cy-1) && a[cx][cy-1]=='-');//←
case 'd':return (crs(cx,cy+1) && a[cx][cy+1]=='-');//→
case '7':return (crs(cx-1,cy-1) && a[cx-1][cy-1]=='-');//↖
case '9':return (crs(cx-1,cy+1) && a[cx-1][cy+1]=='-');//↗
case '1':return (crs(cx+1,cy-1) && a[cx+1][cy-1]=='-');//↙
case '3':return (crs(cx+1,cy+1) && a[cx+1][cy+1]=='-');//↘
}
}
put()函数:玩家每走一步就输出当前迷宫界面状态↓
void put(){
for(int i=1;i<=n;i++)/*行循环*/{
for(int j=1;j<=m;j++)/*列循环*/{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
if(i==sx && j==sy)//当前位置是起点
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);//红色
if(i==ex && j==ey)//当前位置是终点
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);//绿色
if(i==cx && j==cy)//当前位置是玩家所在位置{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN);//黄色
cout<<"#";
continue;
}
cout<<a[i][j];
}
cout<<endl;//换行
}
}
dfs(int,int)函数:在系统随机生成迷宫界面时判断迷宫有无解并保证当前迷宫界面有解
void dfs(int x,int y){
for(int i=1;i<9;i++)/*枚举8个方向*/{
int xx=x+dx[i],yy=y+dy[i];//当前枚举坐标
if(xx>0 && xx<=n && yy>0 && yy<=m && a[xx][yy]=='-' && !b[xx][yy])/*当前位置可走且未走过*/{
b[xx][yy]=true;//标记当前位置走过
if(xx==ex && yy==ey)/*到达终点,表示此迷宫界面有解*/{
sg=true;//标记有解
return;//返回
}
else//未到达终点
dfs(xx,yy);//继续深搜当前枚举坐标
b[xx][yy]=false;//回溯
}
}
}
main()函数:主函数,游戏主体部分的实现。
符号 | 释义 |
---|---|
- | 起点 |
- | 终点 |
# | 当前位置 |
- | 可以通行 |
* | 不可通行 |
移动方向 | 8个(w↑,s↓,a←,d→,7↖,9↗,1↙,3↘) |
迷宫大小 | 1≤n,m≤10 |
int main(){
memset(b,false,sizeof(b));//初始化数组b
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY);//高亮(灰色)
cout<<"欢迎来到迷宫小游戏\n\n";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
cout<<"'";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);//红色
cout<<"-";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
cout<<"'号表示起点\n\n'";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);//绿色
cout<<"-";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
cout<<"'号表示终点\n\n";
cout<<"'*'号表示不可通行\n\n";
cout<<"'-'号表示可以通行\n\n'";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN);//黄色
cout<<"#";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
cout<<"'号表示现在位置\n\n";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);//红色
cout<<"初始位置在入口处\n\n";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);//绿色
cout<<"你可以往八个方向走动\n\n";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_BLUE);//蓝色
cout<<"迷宫长宽小于等于10\n\n\n";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
do{
cout<<"请输入迷宫大小(N*M):";//询问迷宫大小
cin>>n>>m;
}while(n<1 || n>10 || m<1 || m>10);//对n,m作不合法处理
ge//产生随机数种子(宏定义)
do{
sg=false;
system("cls");//清屏
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
u=rand()%2;
a[i][j]=(!u?'-':'*');//随机生成迷宫界面
}
do{
sx=rand()%n+1;//起点x坐标
sy=rand()%m+1;//起点y坐标
}while(a[sx][sy]=='*');//起点不能在'*'上
do{
ex=rand()%n+1;//终点x坐标
ey=rand()%m+1;//终点y坐标
}while(sx==ex && sy==ey || a[ex][ey]=='*');//起点不能与终点重合且终点也不能在'*'上
dfs(sx,sy);//从起点开始深搜
}while(!sg);//无解
put();//输出当前迷宫界面
cx=sx;//当前位置x坐标=起点x坐标
cy=sy;//当前位置y坐标=起点y坐标
do{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN | FOREGROUND_BLUE);//蓝绿(青)色
cout<<"↑w,↓s,←a,→d,↖7,↗9,↙1,↘3:";//提示8个移动方向
d=_getch();//获取玩家的移动方向
while(!chk())/*此方向不合法*/{
d=_getch();//重新获取玩家的移动方向
cout<<d;
}
a[cx][cy]='-';//之前的位置变为'-'
switch(d){
case 'w':a[--cx][cy]='#';break;//↑
case 's':a[++cx][cy]='#';break;//↓
case 'a':a[cx][--cy]='#';break;//←
case 'd':a[cx][++cy]='#';break;//→
case '7':a[--cx][--cy]='#';break;//↖
case '9':a[--cx][++cy]='#';break;//↗
case '1':a[++cx][--cy]='#';break;//↙
case '3':a[++cx][++cy]='#';//↘
}
stp++;//步数增加1
system("cls");//清屏
put();//输出当前迷宫界面
}while(cx!=ex || cy!=ey);//未到达终点
system("cls");//清屏
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);//白色
cout<<"恭喜你成功走出迷宫!\n用了"<<stp<<"步";
return 0;
}
走迷宫 游戏不算难,但它需要严谨的逻辑和巧妙地编写代码,所以也不可对它掉以轻心。特别是dfs深搜的地方,感觉时间复杂度太大,正在考虑优化。
今天的走迷宫游戏分享就告一段落了,代码中有任何错误或者代码有任何可以优化的地方都请在评论区指出(点赞评论请留下~)。
更多推荐
Dev-c++编写走迷宫游戏 思路和代码 详解
发布评论