前言:
要实现扫雷游戏,首先就要先进行分析,扫雷这个游戏可划分为几个大的模块,然后,我们只用对划分的这几个模块进行编码,最后再将其合并即可。
笔者在此将扫雷划分为了五个模块,即,菜单,视图,布置雷,扫雷,合并。
下面笔者将根据这五大模块进行扫雷的讲解。
注:这个完成的是9*9的扫雷游戏。
目录:
-
菜单
-
视图
-
布置雷
-
扫雷
-
合并
一,菜单
菜单的功能就是让玩家进行选择是否参与游戏。我们可以创建一个menu函数进行实现:输入1,玩游戏,输入2,退出,输入其他值,重新输入。这里会用到循环结构。代码如下:
void menu() { while (1) { int k = 0; printf("请选择:\n"); printf(" 1. 玩游戏\n"); printf(" 2. 退出\n"); scanf("%d", &k); if (k == 1) { //扫雷 game(); } else if (k == 2) { break; } else printf("请输入合适的值:\n"); } }
这样菜单就实现了,第一步也就完成了。里面的game()函数表示扫雷游戏,下面笔者讲解如何实现。
二,视图
如何用代码实现扫雷的视图效果呢,大家可以打开一个扫雷游戏,不难发现,它的视图结构就是9x9或者nxn的表格结构。那这样的话我们就可以通过二维数组来实现这个视图。
创建一个in_put()函数,用于输出二维数组,假设我们用0来表示没有雷,代码如下:
int arr[11][11];//存放雷 0 无雷 1 雷 void in_put1(int arr[11][11], int k) { int a = 0; for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) { arr[i][j] = a; } } in_put1(arr, 11);//调用函数
开头我们已经提了,笔者是给大家讲解9*9的扫雷,那么为什么在这里却将二维数组初始化了为11*11呢?
这里先留个悬念,等到排雷的时候笔者会进行详细的讲解。
那么这个输出的结果就是11行11列,且所有的元素都为0的矩阵,这样就算是初始化完成了。
三,布置雷
既然我们已经将视图初始化完成了,那么我们下一步就是进行布置雷,因为只有布置了雷,玩家才能进行游玩,要是没有布置雷就让玩家进行游玩的话,估计,会喷人的。
那么我们要如何布置雷呢?是我们人为的去布置吗?答案是否定的,如果是人为布置的话,太没意思并且麻烦。所以我们要用代码进行布置雷,在这里我们使用了生成随机数的函数rand()。
但在使用rand()函数前,我们要先设置一个种子——srand((unsigned int)time(NULL))。目的是让这个随机值是随时发生变化的,如果不设置种子的话,它这个随机值是固定的,那也就是说,玩游戏背答案就行了,那这样的话,属实没意思,答案都固定了,这可不好,所以我们要设置这个种子,让他发生变化,即每打开一次游戏,雷的位置都与上次的不一样。
那么我们可以创建一个rand_lei()函数来实现,代码如下:
void rand_lei(int arr[11][11], int n) { //雷的个数 int count = 10; while (count != 0) { int x = 0; int y = 0; x = rand() % n + 1;//范围 y = rand() % n + 1; if (arr[x][y] == 0) { arr[x][y] = 1; count--; } else continue; } } //生成雷 rand_lei(arr, 9);//调用函数
雷的个数,大家可以自行设置,rand取随机数是有范围的,大家感兴趣的话可以请了解一下。
雷布置完了,那么我们就可以开始下一步了。
四,扫雷
大家把前三步完成之后,是不是就觉得可以扫雷了呢,答案显然是否定的。大伙可以将其运行一下,可以看下界面是是不是与笔者类似,有1有0。
运行完,大伙一看,这怎么扫,答案都出来了,哪里有雷哪里没有雷,一看就知道了。
所以我们还需要再创建一个视图,而这个视图,是让玩家看的,其内容应该是不会显示哪里有雷,哪里没有雷的。而上面我们运行的那个,应该是让我们内部人员看的,看看雷的个数是否符合我们自己设计的,并作出相应的优化。
那么我们接下来要先创建玩家视图,假设我们用“*”来表示未知
代码如下:
char arr1[11][11];// * 无雷 数字表示周围雷的个数 void in_put2(char arr1[11][11], int k,char ret) { for (int i = 0; i < k; i++) { for (int j = 0; j < k; j++) { if (i == 0) { arr1[i][j] = j; } else if (j == 0) { arr1[i][j] = i; } else { arr1[i][j] = ret; } } } } print_2(arr1, 10);// 函数调用 玩家可见
这个玩家视图创建好后,就该进行扫雷了,我们玩的扫雷游戏,都是进行点击表格进行扫雷的,但是我们目前只学了C语言,并没有学习其它的技术,那么就得换个方式了,换一个用C语言能实现的扫雷。
前面我们都是用二维数组创建的玩家视图,那么我们是不是可以用坐标来表示,我们要点击的位置呢?
答案是肯定的,只是略显麻烦罢了。
既然这样,我们就得在玩家视图上加上行列,代码就是上面的代码。
那么输入的问题解决了,我们可以进行下一步了。大家都知道,我们点击扫雷的话,它会出现数字,而这个数字就是它周围雷的个数,而这个功能我们也是必须要实现的,这样就能让玩家知道它周围有几个雷,可以让游戏变得有趣。
但如果雷在第一行或者是第一列的话,它的周围要是有雷是不是就会产生越界的情况,即它的上面,那么为了避免这种情况,我们只需要让它的数组向上扩充即可,那么扩充几行比较合适呢,结合代码的话,它应该是两行,一行是表示横纵坐标,一行是判断有没有雷,这样就可以了。即9+2,而这个9,它也不是固定不变的,我们这里因为是写的9*9,所以它才是9,那如果是11*11呢?
我们可以通过创建一个clean_lei()函数来实现
int clean_lei(int arr[11][11],char arr1[11][11],int x,int y) { int count = 0; //四周,就是上下左右,东西南北中 for(int i = -1; i < 2; i++) for (int j = -1; j < 2; j++) { if (arr[x + i][y + j] != 0) { count++; //count += arr1[x][y] - '*'; } else continue; } return count; }
那么大家要想一想,这个排雷的过程,clean_lei()函数操作的是哪一个数组,是玩家可见的还是内部人员可见的,而这个返回值又是返回给谁的呢?
答案是显而易见的,判断周围有几个雷,操作的是内部人员可见的程序,因为我们布置雷的对象就是内部人员所创建的数组,而返回值,是给玩家看的,它是个提示玩家周围有几个雷的。
如此准备工作就准备的差不多了,我们可以进行编写输入的函数来进行排雷了,
代码如下:
clean_input(int arr[11][11],char arr1[11][11]) { int x = 0; int y = 0; while (1) { printf("请输入坐标:"); scanf("%d %d", &x, &y); if (arr[x][y] == 1) { printf("请再次选择"); break; } else { //提示周围有几个雷 int a = clean_lei(arr,arr1,x,y); //printf("%d",count) arr1[x][y] = a; print_2(arr1, 10); } } }
至此各个模块的代码算是完成了,那么我们剩下要做的就是合并,其实合并也是很简单的,但是要理清逻辑。
五,合并
我们首先要创建一个主函数,来包含菜单menu()函数,并且设置种子,让雷的位置发生变化
代码如下:
#include<stdio.h> #include<stdlib.h> #include"head.h" int main() { //设置种子 srand((unsigned int)time(NULL)); menu(); return 0; }
运行程序后,程序调用menu()函数,会让我们进行选择,如果我们选择1,是进行游戏,选择2,则是退出游戏。那么我们选择1,
程序执行进行游戏,也就是调用扫雷这个游戏,即game()函数。
代码如下:
void menu() { while (1) { int k = 0; printf("请选择:\n"); printf(" 1. 玩游戏\n"); printf(" 2. 退出\n"); scanf("%d", &k); if (k == 1) { //扫雷 game(); } else if (k == 2) { break; } else printf("请输入合适的值:\n"); } }
那么进入到game()函数后,它会执行什么功能呢?
首先就是先初始化视图,布置雷,雷布置完之后就可以输出视图了,这样玩家就可以进行扫雷了。
代码如下:
void game() { //初始化 int arr[11][11];//存放雷 0 无雷 1 雷 char arr1[11][11];// * 无雷 数字表示周围雷的个数 in_put1(arr, 11); in_put2(arr1, 11, '*'); //生成雷 rand_lei(arr, 9); //打印 print_1(arr, 10); print_2(arr1, 10);//玩家可见 //扫雷 clean_input(arr,arr1); }
如此就这个代码就算是实现了,简单的扫雷也是完成了,一定要记得敲代码才行。