通过数组可以做到很多的事情,你甚至可以使用数组来做一款简易的游戏,下面教大家使用二维数组实现一款简易的迷宫游戏。
项目代码放在了码云(gitee)上,有兴趣的可以下载看看。
https://gitee.com/YHF_200623/C_mazeGame
迷宫游戏
先简单介绍一下游戏,游戏玩法和传统的走迷宫一样,控制角色走到出口游戏结束。
玩家操作的角色用 @ 表示,墙壁用 # 表示,道路用空格表示。
定义并初始化数据
需要的定义的数据有:
- 迷宫数组
- 角色当前坐标
- 终点坐标
角色当前坐标和终点坐标没啥好说的直接定义就可以了
int x = 3,y = 1; // 角色当前坐标(根据迷宫地图初始化)
int final_x = 3, final_y =9; // 终点坐标(根据迷宫地图初始化)
主要是迷宫数组的定义,因为已经确定了玩家操作的角色用 @ 表示,墙壁用 # 表示,道路用空格表示。
可以有两种表现方式:
第一种是直接在迷宫数组中写字符的ASCII码,使用 %c 的格式符输出对应字符。
第二种是在迷宫数组中用0、1、2指代各种符号,在打印时判断输出对应的字符。
这里为了便于在代码中观察地图,我使用第二种方法。
//迷宫数组 墙壁=0 路=1 角色=2
int arr[10][10] = {
{0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,1,0},
{0,2,0,0,0,0,0,0,1,1},
{0,1,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,0,1,0},
{0,1,1,0,0,0,1,0,1,0},
{0,1,1,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};
下面写一下显示地图语句。
显示地图
显示地图其实就是遍历迷宫数组,在打印时判断输出对应的字符,用两层for循环加switch语句即可
//显示迷宫
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
switch(arr[i][j])
{
case 0: printf("# ");break;
case 1: printf(" ");break;
case 2: printf("@ ");break;
}
}
printf("\n");
}
将上述代码组合在一起,我们就有了如下代码,并可以通过运行,显示出迷宫地图。
#include<stdio.h>
int main(int argc,const char* argv[])
{
//迷宫数组 墙壁=0 路=1 角色=2
int arr[10][10] = {
{0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,1,0},
{0,2,0,0,0,0,0,0,1,1},
{0,1,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,0,1,0},
{0,1,1,0,0,0,1,0,1,0},
{0,1,1,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};
int x = 3,y = 1; // 角色当前坐标(根据迷宫地图初始化)
int final_x = 3, final_y =9; // 终点坐标(根据迷宫地图初始化)
//显示迷宫
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
switch(arr[i][j])
{
case 0: printf("# ");break;
case 1: printf(" ");break;
case 2: printf("@ ");break;
}
}
printf("\n");
}
}
运行结果:
清屏
每次显示地图时,上一次的地图会残留在终端上,看着很难受。linux系统可以使用函数system调用系统命令clear,实现清屏效果,需要调用头文件stdlib.h。windows系统可以使用windows.h头文件也可以使用stdlib.h,但里面的清屏命令需要改成cls。
system("clear");
获取键盘输入
可以使用getchar等函数获取键盘的输入,但是为了界面美观。使用了一个getch.h的头文件,用来获取键盘输入,并隐藏窗口的输入信息。
百度网盘链接(getch.h)
提取码:1111
如果是windows系统,可以使用自带的 conio.h 中的,getch()方法,但是因为方向键会返回两个值,所以需要调用两次。
#include<stdio.h>
#include<conio.h>
int main(int argc,const char* argv[])
{
while(1)
{
printf("%d\n",getch()+getch());
}
}
使用 linux 系统的朋友,只需要把getch.h头文件与程序代码放在同一个目录下即可,可以通过#include"getch.h"方式调用,也可将getch.h的内容复制到程序中。
#include<stdio.h>
#include"getch.h"
int main(int argc,const char* argv[])
{
while(1)
{
printf("%d\n",getch());
}
}
windows系统中返回值与linux系统中的略有不同。建议使用前自己测试一下方向键的返回值。
方向键 | window | linux |
---|---|---|
向上 | 296 | 183 |
向下 | 304 | 184 |
向左 | 299 | 186 |
向右 | 301 | 185 |
顺便提一下#include""与#include<>的区别:
- #include<> 是从系统指定的路径下加载头文件(操作系统是通过设置环境变量来指定加载头文件的路径)
- #include “” 先从当前路径(文件路径)下加载头文件,如果找不到,再去系统指定的路径下加载
使用虚拟机的朋友可以放在共享文件夹中(程序+头文件)
玩法实现
地图有了,输入也有了,如何把通过输入控制角色(@)移动呢?角色移动其实就是通过对二维数组中的内容进行操作。
打个比方,当我按向上键时,getch函数返回给我一个值,我通过对这个返回值进行判断,执行角色向上走的操作。这个时候需要思考如何什么情况下角色可以往上走?当遇到上方是墙的时候,角色是不能移动的,只有当上方是路的时候,角色才能向上移动,这时把上方的值设为角色,把下方的值设为路,并且更新角色坐标,就实现了角色的移动,其他的操作也是如此。
代码如下
//玩法实现
switch(getch())
{
case 183:
if(arr[x-1][y] == 1)
{
arr[x-1][y] = 2;
arr[x][y] = 1;
x--;
}
break;
case 184:
if(arr[x+1][y] == 1)
{
arr[x+1][y] =2;
arr[x][y] = 1;
x++;
}
break;
case 185:
if(arr[x][y+1] == 1)
{
arr[x][y+1] = 2;
arr[x][y] = 1;
y++;
}
break;
case 186:
if(arr[x][y-1] == 1)
{
arr[x][y-1] = 2;
arr[x][y] = 1;
y--;
}
break;
}
确定获胜条件
什么时候游戏算结束了呢,当角色到达出口时,游戏就结束了,在程序中就是角色坐标等于终点坐标。因此可以写出游戏结束的条件:
//结束判断
if(x == final_x && y == final_y)
{
printf("游戏结束\n");
return 0;
}
组合代码
我们现在已经实现的功能有:
- 显示地图
- 清屏
- 获取键盘输入
- 玩法实现
- 确定获胜条件
一个游戏大部分的代码都在这里了,我们需要对它们进行组装使用即可。先捋一捋游戏流程:
- 清屏
- 显示地图
- 判断获胜条件
- 获取键盘输入
- 控制角色移动
- 回到第一步
根据游戏流程,可以看出需要使用死循环。在每次循环清屏并显示地图。然后判断获胜条件,如果获胜就退出,否则游戏继续。通过获取键盘输入的返回值,执行对应的角色移动操作。然后进入下一次循环。
组合代码(linux)如下:
#include<stdio.h>
#include<stdlib.h>
#include"getch.h"
int main(int argc,const char* argv[])
{
//迷宫数组 墙壁=0 路=1 角色=2
int arr[10][10] = {
{0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,1,0},
{0,2,0,0,0,0,0,0,1,1},
{0,1,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,0,1,0},
{0,1,1,0,0,0,1,0,1,0},
{0,1,1,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};
int x = 3,y = 1; // 角色当前坐标(根据迷宫地图初始化)
int final_x = 3, final_y =9; // 终点坐标(根据迷宫地图初始化)
//游戏开始
while(1)
{
//清屏
system("clear");
//显示迷宫
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
switch(arr[i][j])
{
case 0: printf("# ");break;
case 1: printf(" ");break;
case 2: printf("@ ");break;
}
}
printf("\n");
}
//结束判断
if(x == final_x && y == final_y)
{
printf("游戏结束\n");
return 0;
}
//玩法实现
switch(getch())
{
case 183:
if(arr[x-1][y] == 1)
{
arr[x-1][y] = 2;
arr[x][y] = 1;
x--;
}
break;
case 184:
if(arr[x+1][y] == 1)
{
arr[x+1][y] = 2;
arr[x][y] = 1;
x++;
}
break;
case 185:
if(arr[x][y+1] == 1)
{
arr[x][y+1] = 2;
arr[x][y] = 1;
y++;
}
break;
case 186:
if(arr[x][y-1] == 1)
{
arr[x][y-1] = 2;
arr[x][y] = 1;
y--;
}
break;
}
}
}
windows 需要调用conio.h头文件,并且调用两次getch()函数。同时,不同系统的键值不同,需要修改键值。最后,系统命令清屏,里面的清屏命令改成cls。
组合代码(window)如下:
#include<stdio.h>
#include<conio.h>
#include<windows.h>
int main(int argc,const char* argv[])
{
//迷宫数组 墙壁=0 路=1 角色=2
int arr[10][10] = {
{0,0,0,0,0,0,0,0,0,0},
{0,1,0,0,0,0,0,0,1,0},
{0,1,0,0,0,0,0,0,1,0},
{0,2,0,0,0,0,0,0,1,1},
{0,1,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,0,1,0},
{0,1,1,0,0,0,1,0,1,0},
{0,1,1,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0}
};
int x = 3,y = 1; // 角色当前坐标(根据迷宫地图初始化)
int final_x = 3, final_y =9; // 终点坐标(根据迷宫地图初始化)
//游戏开始
while(1)
{
//清屏
system("cls");
//显示迷宫
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
switch(arr[i][j])
{
case 0: printf("# ");break;
case 1: printf(" ");break;
case 2: printf("@ ");break;
}
}
printf("\n");
}
//结束判断
if(x == final_x && y == final_y)
{
printf("游戏结束\n");
return 0;
}
//玩法实现
switch(getch()+getch())
{
case 296:
if(arr[x-1][y] == 1)
{
arr[x-1][y] = 2;
arr[x][y] = 1;
x--;
}
break;
case 304:
if(arr[x+1][y] == 1)
{
arr[x+1][y] = 2;
arr[x][y] = 1;
x++;
}
break;
case 301:
if(arr[x][y+1] == 1)
{
arr[x][y+1] = 2;
arr[x][y] = 1;
y++;
}
break;
case 299:
if(arr[x][y-1] == 1)
{
arr[x][y-1] = 2;
arr[x][y] = 1;
y--;
}
break;
}
}
}
如果需要显示时间,只需要在记录下游戏开始的时间以及游戏结束的时间,两者相减即可,这里就不作演示了。
结语
希望这篇文章对你有所帮助