这篇文章是给学完并学懂了C语言的分支(选择和循环)结构和二维数组的朋友看的。
要做一个游戏或者程序先要想好有那些要求,以下是我认为一个迷宫必带的要求:
首先我们要打印出地图,因为地图有长和宽的长度,所以我们要用二维数组来定义一个地图,代码如下:
char map[50][50]={
"######",//申请50*50的二维字符串当迷宫地图,但这里是6*6的地图
"#O # ",//'#'是墙(不可以走的地方)
"# ## #",//'O'是起点(可控制)
"# # #",//' '是空气(可以走的地方)
"## #",
"######",//横竖都是012345,012345(数组下标从0开始)
};
定义完二维数组,就要把它打印出来,代码如下:
int i,j;
for(i=0;i<6;i++)//i循环用来控制打印地图的行数
{
for(j=0;j<6;j++)//j循环用来控制打印地图的列数
{
printf("%c",map[i][j]);//打印每次i和j的行数和列数
}
printf("\n");//一行打印完毕需要换行
}
上面这段代码是通过双重循环打印出地图的每行每列。
如果学过puts函数来输出字符数组的朋友可以这样写,代码如下:
int i;
for(i=0;i<6;i++)//从0到5,共进行了6次循环,依次输出迷宫的第0至5行
puts(map[i]);//表示输出每一行的字符串
是不是简单了许多,不懂puts函数的朋友也没关系,你用第一种方法就行,对于puts函数你只需要知道:
然后再定义起点和终点的X、Y轴位置(当然上面定义二维数组时已经看得出来了),代码如下:
int x,y,p,q;//x,y为小球(起点"O")初始位置竖横轴
//p,q为空白(终点" ")结束位置竖横轴
x=1;y=1;//x为竖轴初始位置为1,y为初始横轴位置为1
p=1;q=5;//p为竖轴结束位置为1,q为结束横轴位置为5
目前为止,我们做了定义地图、打印地图、定义起点终点的X、Y轴,目前全部代码如下:
#include//printf("");的头文件
#include//system("");的头文件
#include//Sleep();的头文件
int m1ain(void)
{
char map[50][50]={
"######",//申请50*50的二维字符串当迷宫地图,但这里是6*6的地图
"#O # ",//'#'是墙(不可以走的地方)
"# ## #",//'O'是起点(可控制)
"# # #",//' '是空气(可以走的地方)
"## #",
"######",//横竖都是012345,012345(数组下标从0开始)
};
int i,x,y,p,q;//x,y为小球(起点"O")初始位置竖横轴
//p,q为空白(终点" ")结束位置竖横轴
int ch;//申请需要输入的字符(名称是ch),当移动(w,a,s,d)
x=1;y=1;p=1;q=5;//x为竖轴初始位置为1,y为初始横轴位置为1
//p为竖轴结束位置为1,q为结束横轴位置为5
for(i=0;i<6;i++)//从0到5,共进行了6次循环,依次输出迷宫的第0至5行
puts(map[i]);//表示输出每一行的字符串
Sleep(5000);//上面代码全部执行完毕后过五秒自动关闭程序
return 0;
}
现在我们就要想办法控制小球了,这里利用键盘上的'w''s''a''d'四个键来控制这个小球进行上、下、左、右移动,当然你如果喜欢,也可以用别的按键。
第一步:先来控制小球向下移动,也就是当你按下's'键时,小球向下移动一步。
那么如何获得's'这个按键呢,换句话说:当你按下's'键时,我们的程序怎样知道你按的是's'键呢?
很简单,因为你按下's'键时,本质上是输入了1个字符's',我们只需要读取这个字符's'就可以了,读取一个字符有4种方法:
char ch;
scanf("%c",&ch);//读取一个字符,输入后等待用户按"Enter"键结束(带回显)
ch=getchar;//读取一个字符,输入后等待用户按"Enter"键结束(带回显)
ch=getche;//读取一个字符,输入后立即获取字符,不用按"Enter"键结束(带回显)
ch=getch;//读取一个字符,输入后立即获取字符,不用按"Enter"键结束(不带回显)
而我们并不想显示输入的字符,并且希望输入的字符可以立即被程序获得,而不用在敲击一个字符后再敲击一个"Enter"键。
因此我们选用最后一个语句ch=getch();。
接下来,我们要把在键盘上敲击的字符存储在字符变量ch中,再接下来实现当敲击's'时。让小球向下移动一步,代码如下:
if(ch=='s')//判断你是否输入(按)'s'这个字符
{
if(map[x+1][y]!='#')//确认输入(按)的是's'时,就执行[x+1][y](往下走,x为竖轴,+1为往下,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往下走不是墙时,把当前的'O'输出成' '
x++;//为向下走
map[x][y]='O';//确认往下走不是墙时,把下一步的' '输出成'O'
}
}
在上面代码中,我们通过if语句来判断敲击的字符是否是字符's',如果是字符's',我们就让小球向下移动一步,但在小球向下移动之前,需要首先判断下面一步是否能移动,只有下一步不是墙'#'时小球才能移动。
也就是说当if(map[x+1][y]!='#')条件成立时,就表示下一步不是墙,小球可以移动。
可能有些朋友会问:为什么[x+1][y]就表示向下走一部的格子呢?
其实很简单:向下移动时,小球当然还在当前这个列,不过不在这一行,而是在下一行,因此向下移动是y不变,x加1。
如果是向右边移动,很显然还是在同一行,所以x不变,但是小球已经不在刚才那一竖列了,而在右边的一个竖列,因此y需要加1。
接下来我们来讲解下面这3句话的意思:
map[x][y]=' ';//确认往下走不是墙时,把当前的'O'输出成' '
x++;//为向下走
map[x][y]='O';//确认往下走不是墙时,把下一步的' '输出成'O'
让小球向下移动,就是让小球原本位置上的'O'变成空格,而让下一个空格变成'O'。
第一句:map[x][y]=' ';(注意此处两个单引号之间中间有一个空格)就是让小球的当前位置变为空格,
第二句:x++;这句话非常重要,它表示更改小球的位置,因为小球向下运动只需要x++就可以了,y不变。
第三句:a[x][y]='O';语句就是将小球新位置上的内容替换为小球'O'。
请注意上面一个代码,可不能写成:
map[x][y]=' ';
map[x+1][y]='O';
至于为什么,大家自己去想想吧!
因为小球的位置有了变化,因此还需要将新迷宫的状态重新打印一次,在打印之前记得要将之前的屏幕清屏,代码如下:
int i;
system("cls");//每次移动了小球就清屏一次
for(i=0;i<6;i++)//清屏了再次循环输出新的地图
puts(map[i]);//清屏了再次输出新的地图
#include//printf("");的头文件
#include//system("");的头文件
#include//Sleep();的头文件
#include//getch();的头文件
int main(void)
{
char map[50][50]={
"######",//申请50*50的二维字符串当迷宫地图,但这里是6*6的地图
"#O # ",//'#'是墙(不可以走的地方)
"# ## #",//'O'是起点(可控制)
"# # #",//' '是空气(可以走的地方)
"## #",
"######",//横竖都是012345,012345(数组下标从0开始)
};
int i,x,y,p,q;//x,y为小球(起点"O")初始位置竖横轴
//p,q为空白(终点" ")结束位置竖横轴
int ch;//申请需要输入的字符(名称是ch),当移动(w,a,s,d)
x=1;y=1;p=1;q=5;//x为竖轴初始位置为1,y为初始横轴位置为1
//p为竖轴结束位置为1,q为结束横轴位置为5
for(i=0;i<6;i++)//从0到5,共进行了6次循环,依次输出迷宫的第0至5行
puts(map[i]);//表示输出每一行的字符串
ch=getch();//这语句表示给ch变量输入的字符可以立即被程序获取(不用按任意键继续),也不会回显
if (ch=='s')//判断你是否输入(按)'s'这个字符
{
if (map[x+1][y]!='#')//确认输入(按)的是's'时,就执行[x+1][y](往下走,x为竖轴,+1为往下,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往下走不是墙时,把当前的'O'输出成' '
x++;//为向下走
map[x][y]='O';//确认往下走不是墙时,把下一步的' '输出成'O'
}
}
system("cls");//每次移动了小球就清屏一次
for(i=0;i<6;i++)//清屏了再次循环输出新的地图
puts(map[i]);//清屏了再次输出新的地图
Sleep(5000);//上面代码全部执行完毕后过五秒自动关闭程序
return 0;
}
运行一下,然后按一下's'键,是不是已经可以看到小球向下移动了一步了呢?
但是你只能移动一步,如何实现连续移动呢?
很简单,实现连续移动我们可以通过while循环来解决问题:
#include//printf("");的头文件
#include//system("");的头文件
#include//Sleep();的头文件
#include//getch();的头文件
int m1ain(void)
{
char map[50][50]={
"######",//申请50*50的二维字符串当迷宫地图,但这里是6*6的地图
"#O # ",//'#'是墙(不可以走的地方)
"# ## #",//'O'是起点(可控制)
"# # #",//' '是空气(可以走的地方)
"## #",
"######",//横竖都是012345,012345(数组下标从0开始)
};
int i,x,y,p,q;//x,y为小球(起点"O")初始位置竖横轴
//p,q为空白(终点" ")结束位置竖横轴
int ch;//申请需要输入的字符(名称是ch),当移动(w,a,s,d)
x=1;y=1;p=1;q=5;//x为竖轴初始位置为1,y为初始横轴位置为1
//p为竖轴结束位置为1,q为结束横轴位置为5
for(i=0;i<6;i++)//从0到5,共进行了6次循环,依次输出迷宫的第0至5行
puts(map[i]);//表示输出每一行的字符串
while(1)//暂时无限循环
{
ch=getch();//这语句表示给ch变量输入的字符可以立即被程序获取(不用按任意键继续),也不会回显
if(ch=='s')//判断你是否输入(按)'s'这个字符
{
if(map[x+1][y]!='#')//确认输入(按)的是's'时,就执行[x+1][y](往下走,x为竖轴,+1为往下,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往下走不是墙时,把当前的'O'输出成' '
x++;//为向下走
map[x][y]='O';//确认往下走不是墙时,把下一步的' '输出成'O'
}
}
system("cls");//每次移动了小球就清屏一次
for(i=0;i<6;i++)//清屏了再次循环输出新的地图
puts(map[i]);//清屏了再次输出新的地图
}
Sleep(5000);//上面代码全部执行完毕后过五秒自动关闭程序
return 0;
}
暂时先使用while(1)无限循环来解决这个问题,好了,运行一下吧。
此时小球是不是可以连续移动了?
当然,目前小球还只能朝一个方向运动,接下来我们来实现小球向其它3个方向的运动。
向其它3个方向移动其实和"向下移动"是差不多的,只要注意是x在变化还是y在变化,是加1还是减1就可以了。无限移动4个方向代码如下:
#include//printf("");的头文件
#include//system("");的头文件
#include//Sleep();的头文件
#include//getch();的头文件
int m1ain(void)
{
char map[50][50]={
"######",//申请50*50的二维字符串当迷宫地图,但这里是6*6的地图
"#O # ",//'#'是墙(不可以走的地方)
"# ## #",//'O'是起点(可控制)
"# # #",//' '是空气(可以走的地方)
"## #",
"######",//横竖都是012345,012345(数组下标从0开始)
};
int i,x,y,p,q;//x,y为小球(起点"O")初始位置竖横轴
//p,q为空白(终点" ")结束位置竖横轴
int ch;//申请需要输入的字符(名称是ch),当移动(w,a,s,d)
x=1;y=1;p=1;q=5;//x为竖轴初始位置为1,y为初始横轴位置为1
//p为竖轴结束位置为1,q为结束横轴位置为5
for (i=0;i<6;i++)//从0到5,共进行了6次循环,依次输出迷宫的第0至5行
puts(map[i]);//表示输出每一行的字符串
while(1)//暂时无限循环
{
ch=getch();//这语句表示给ch变量输入的字符可以立即被程序获取(不用按任意键继续),也不会回显
if(ch=='s')//判断你是否输入(按)'s'这个字符
{
if(map[x+1][y]!='#')//确认输入(按)的是's'时,就执行[x+1][y](往下走,x为竖轴,+1为往下,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往下走不是墙时,把当前的'O'输出成' '
x++;//为向下走
map[x][y]='O';//确认往下走不是墙时,把下一步的' '输出成'O'
}
}
if(ch=='w')//判断你是否输入(按)'w'这个字符
{
if(map[x-1][y]!='#')//确认输入(按)的是'w'时,就执行[x-1][y](往上走,x为竖轴,-1为往上,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往上走不是墙时,把当前的'O'输出成' '
x--;//为向上走
map[x][y]='O';//确认往上走不是墙时,把下一步的' '输出成'O'
}
}
if(ch=='a')//判断你是否输入(按)'a'这个字符
{
if(map[x][y-1]!='#')//确认输入(按)的是'a'时,就执行[x][y-1](往左走,y为横轴,-1为往左,x不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往左走不是墙时,把当前的'O'输出成' '
y--;//为向左走
map[x][y]='O';//确认往左走不是墙时,把下一步的' '输出成'O'
}
}
if(ch=='d')//判断你是否输入(按)'d'这个字符
{
if(map[x][y+1]!='#')//确认输入(按)的是'd'时,就执行[x][y-1](往右走,y为横轴,+1为往右,x不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往右走不是墙时,把当前的'O'输出成' '
y++;//为向右走
map[x][y]='O';//确认往右走不是墙时,把下一步的' '输出成'O'
}
}
system("cls");//每次移动了小球就清屏一次
for(i=0;i<6;i++)//清屏了再次循环输出新的地图
puts(map[i]);//清屏了再次输出新的地图
}
Sleep(5000);//上面代码全部执行完毕后过五秒自动关闭程序
return 0;
}
好了,你是不是已经成功走出了迷宫?
可是貌似程序并没有让你很惊喜,因为没有判定你已经成功走出迷宫。
最后我们来写一个"获胜"的检测部分,其实只需要将我们之前写的while(1)改为while(x!=p||y!=q)就可以了。
还记得吗,之前我们用p和q分别存储了迷宫出口的坐标位置,当然了,在最后我们需要打印"你获胜了"。完整代码如下:
#include//printf("");的头文件
#include//system("");的头文件
#include//Sleep();的头文件
#include//getch();的头文件
int m1ain(void)
{
printf("欢迎来到迷宫小游戏\n");//介绍这个迷宫游戏
printf("操作方式:\nw为往上走\ns为往下走\na为往左走\nd为往右走\n");//介绍操作方式
char map[50][50]={
"######",//申请50*50的二维字符串当迷宫地图,但这里是6*6的地图
"#O # ",//'#'是墙(不可以走的地方)
"# ## #",//'O'是起点(可控制)
"# # #",//' '是空气(可以走的地方)
"## #",
"######",//横竖都是012345,012345(数组下标从0开始)
};
int i,x,y,p,q;//x,y为小球(起点"O")初始位置竖横轴
//p,q为空白(终点" ")结束位置竖横轴
int ch;//申请需要输入的字符(名称是ch),当移动(w,a,s,d)
x=1;y=1;p=1;q=5;//x为竖轴初始位置为1,y为初始横轴位置为1
//p为竖轴结束位置为1,q为结束横轴位置为5
for(i=0;i<6;i++)//从0到5,共进行了6次循环,依次输出迷宫的第0至5行
puts(map[i]);//表示输出每一行的字符串
while (x!=p||y!=q)//只要x的值不等p或y的值不等q就无限循环
{
ch=getch();//这语句表示给ch变量输入的字符可以立即被程序获取(不用按任意键继续),也不会回显
if(ch=='s')//判断你是否输入(按)'s'这个字符
{
if(map[x+1][y]!='#')//确认输入(按)的是's'时,就执行[x+1][y](往下走,x为竖轴,+1为往下,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往下走不是墙时,把当前的'O'输出成' '
x++;//为向下走
map[x][y]='O';//确认往下走不是墙时,把下一步的' '输出成'O'
}
}
if(ch=='w')//判断你是否输入(按)'w'这个字符
{
if(map[x-1][y]!='#')//确认输入(按)的是'w'时,就执行[x-1][y](往上走,x为竖轴,-1为往上,y不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往上走不是墙时,把当前的'O'输出成' '
x--;//为向上走
map[x][y]='O';//确认往上走不是墙时,把下一步的' '输出成'O'
}
}
if(ch=='a')//判断你是否输入(按)'a'这个字符
{
if(map[x][y-1]!='#')//确认输入(按)的是'a'时,就执行[x][y-1](往左走,y为横轴,-1为往左,x不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往左走不是墙时,把当前的'O'输出成' '
y--;//为向左走
map[x][y]='O';//确认往左走不是墙时,把下一步的' '输出成'O'
}
}
if(ch=='d')//判断你是否输入(按)'d'这个字符
{
if(map[x][y+1]!='#')//确认输入(按)的是'd'时,就执行[x][y-1](往右走,y为横轴,+1为往右,x不变),提前是还要判断往下走是否为'#'(墙)
{
map[x][y]=' ';//确认往右走不是墙时,把当前的'O'输出成' '
y++;//为向右走
map[x][y]='O';//确认往右走不是墙时,把下一步的' '输出成'O'
}
}
system("cls");//每次移动了小球就清屏一次
for(i=0;i<6;i++)//清屏了再次循环输出新的地图
puts(map[i]);//清屏了再次输出新的地图
}
system("cls");//最后通关后清屏
printf("恭喜你赢了!\n");//最后通关后提示输出语句
Sleep(5000);//上面代码全部执行完毕后过五秒自动关闭程序
return 0;
}