前言
扫雷即数组于游戏之中的应用,与三字棋不同,其难点在于排雷之时细节的繁琐和打印数组时丧失全无的方向感,而产生的小错误往往很难发现。因此在写的时候必须十分谨慎,不然找错误的时候就会非常痛苦。希望这个博客能都对大家有点帮助。
1.菜单
一样,怎么好看怎么来,为了我们玩完一把之后还能再玩下去,do while循环就是因此而存在的,因其特性可以至少运行一次,然后我们再使用input作为参数当input为0时循环结束。同样我们这次也是要使用随机值来布雷,因而要在主函数中对rand用时间戳进行定义。然后用switch来进行选择,根据input的不同语句的入口也不一样,使用break 将各各区域分隔开,避免走入其他语句之中。
2.初始化
跟三字棋一样,为了更好的管理,我们建立test.c game.c 和 game.h 文件来将内容分隔开,这样更加方便与不同语句的处理和应用。
这时候让我们回想一下扫雷游戏的基本内容,有一个游戏界面在格子内部还藏有地雷,当我们要将界面打印,又要在内部藏有地雷,就需要使用到二维数组;显然只有一个数组是不够的。我们可以用一个数组来存储地雷,一个数组打印出来给玩家观看。同时玩家选择一个坐标之后,对该坐标是否为地雷进行判断,那么问题来了,在判断的时候沿边缘坐标的格子我们如何判断其周围的地雷数量呢?那我们得将棋盘拓展开来方便于我们的判断,但实际打印出来的得还是9X9的棋盘。
所以刚开始我们对两个数组先进行初始化。
然后在game.h内进行声明,记得引头文件~(自己的头文件用双引号)~可以把stdio.h放在game.h里面就不用引好多次了。
ROW COL 为原来棋盘大小,ROWS COLS为拓展棋盘大小
小提示
在game.h里面定义需要用大写(血和泪的教训)如果自己定义常量的时候记得这一点!!!!!
此时我们的界面还是空的,现在要对这个数组进行初始化,我们需要传四个参数,各个数组、行数、列数、初始化所定义的字符,我们这里将内数组 雷定义为1非雷定义为0,将外数组全定义为 * 号打印出来作为我们的游戏界面。
设置一个函数,在game.h声明,在game.c中定义。用row col 和set 来接收我们传过来的行、列、要定义的字符。
两个for循环全选整个数组并将其定义成我们想要的字符
这样我们数据的初始化就完成了!!
3.打印游戏画面
如果只是普通的把数组打印出来的话,只需要两个for循环全选然后一个一个打印就可以了,但是我们想在标头加上行号和列号的话,就要加上一些修饰。需要在两个for循环前在加上一个循环用于打印列号,在每一列的打印中加上行号的打印。并且要打印的是9X9的游戏界面,所以用的row和col也是9而不是11。
如果没有换行的操作的话,就会变成这样
或者 这样
还有可能出现这种情况
是由于把%c顺手打成了%d
4.布雷
只需要根据设置雷的数量生成该数量的随机数,并检测其合法性之后将其放置在内侧的数组之中,就是这个常量的设置,在头文件中要用大写来定义,害我写的时候老是报错。
5.排雷
之后就来到扫雷游戏中最关键的一步了。提示玩家排雷后,接收玩家输入的坐标进行进一步的检测。
1.确认坐标的合法性
当下我们打印出来的界面是这个样子的,即坐标从1开始到9结束,即我们坐标的合法范围。
2.检测是否已经为已排坐标
同时还要检查是否已排,需从外数组检查该坐标的字符是否为 * 即使阻止通过不断循环来寻找程序的漏洞。
3.判断是否为炸弹
外数组于内数组是相互对应的,在内数组检测该坐标是否为炸弹,若是则退出游戏并打印内界面让玩家死得明白(doge)
4.显示数字
经过三轮选择后的数据,即是可以继续走下去的数据,我们需要找出他周围的炸弹数并将其打印在外界面上。同时,我们数组之中存放的是字符类型的数据。一个数加上字符0的ASCII码值之后就是该数字的字符形式了。
同时我们在这个函数上实现检测地雷数的函数。
一个一个将数列内值取出,外函数中每有一个1,我们刚好用数列将其表达出来减去8个0即转换成ASCII码传回原函数之后再找回相对应的数并替换到外数组上,再将画面打印给玩家看,我们一次排雷便算完成了。
5.游戏结束声明
一次游戏,一共有row X col的格子扣掉地雷的数量便得到了一共需要排雷几次,将参数带入循环,则成为了游戏结束的凭据。
最后祝贺玩家取得胜利,并打印出内界面,告诉玩家地雷的位置。如此我们的扫雷游戏就写完了。将完整的代码放在下面供参考。
test.c
game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void iniboard(char board[ROWS][COLS], int row, int col,int set) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = set; } } } void display_board(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; for (j = 0; j <= col; j++) { printf("%d ", j); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } } void putboom(char board[ROWS][COLS], int row, int col) { int n = EASY_COUNT; while (n) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] == '0') { board[x][y] = '1'; n--; } } } int showaround(char back[ROWS][COLS], int x, int y) { return (back[x + 1][y] + back[x][y + 1] + back[x + 1][y + 1] + back[x - 1][y - 1] + back[x - 1][y + 1] + back[x + 1][y - 1] + back[x - 1][y] + back[x][y - 1]-8*'0'); } void checkboom(char back[ROWS][COLS], char out[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = 0; while (1) { printf("请排雷:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (out[x][y] = '*') { if (back[x][y] == '1') { printf("很遗憾,游戏结束。\n"); display_board(back, ROW, COL); break; } else { int ret = showaround(back, x, y); out[x][y] = ret + '0'; display_board(out, ROW, COL); count++; } } else { printf("该坐标已经被排查过了。"); } } else printf("输入错误,请重新输入\n"); if (row * col - EASY_COUNT == count) { printf("恭喜你,取得胜利!\n"); display_board(back, ROW, COL); break; } } }
game.h