4.2 初始化棋盘函数
定义InitBorad()函数,代码实现:
void InitBorad(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; int j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } }
首先我们对埋雷的数组进行初始化为字符 0 ,(非雷用字符 0 表示,雷用字符 1 表示),对显示棋盘的数组全部用 * 将埋雷的数组覆盖起来,因此在game()函数里对 InitBorad()函数调用两次。
4.3 打印棋盘函数
定义DisplayBorad()函数,代码实现:
void DisplayBorad(char board[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf("########扫雷#######\n"); 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"); } }
效果展示:
埋雷棋盘(mine)
展示棋盘(show)
我们可以看见和我们当初构思的是一样的,我们只需要将show棋盘展示给用户就好了。
4.4 布置雷
定义SetMine()函数,代码实现:
void SetMine(char mine[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }
代码分析:
Q:我们怎样才能将雷随机的布置在 9*9 棋盘中呢?
A:我们使用 rand 函数,利用时间戳生成随机数,再对生成的随机数取模行、列(9)并加一,就能实现在中间的 9*9 的棋盘里放入 10 颗随机的雷。
int x = rand() % row + 1;//随机数取模于row得到0~8,+1处理后得到的是1~9 int y = rand() % col + 1;//随机数取模于col得到0~8,+1处理后得到的是1~9
我们设定 count 个雷,埋下一个就减一,并进行判断,这个位置是否为字符 '0' ,是就将字符 '0' 改为字符 '1' ,不是字符 '0' 就再生成一个合法的随机位置,使其合法的放入 9*9 的棋盘里面,这样就不会出现重复埋雷了。在使用 while 循环,直到减到 count 为 0 时,while 不在循环,10 颗雷正好埋完。
4.5 排查雷
定义FindMine()函数,代码实现:
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0; while (win<row*col-EASY_COUNT) { printf("请输入要排查的坐标:>"); scanf("%d %d", &x, &y); if ((x >= 1 && x <= row) && (y >= 1 && y <= col)) { if (mine[x][y] == '1') { printf("很遗憾,你被炸死了\n"); DisplayBorad(mine, ROW, COL); break; } else { //此坐标不是雷,就要统计此坐标附近雷的个数 int count = GetMineCount(mine, x, y); show[x][y] = count + '0'; DisplayBorad(show, ROW, COL); win++; } } else { printf("排查的坐标非法,请重新输入\n"); } } if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); DisplayBorad(mine, ROW, COL); } }
其中添加了计算附近雷的GetMineCount()函数,代码实现:
int GetMineCount(char mine[ROWS][COLS], int x, int y) { return (mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0'); }
我们对这两段代码进行解析:
首先我们对玩家输入的坐标位置进行判断是否合法,坐标必须在 1~row/col 之间(包含 1 和 row/col),如果不在此范围,代码会走第一个 else 语句,提醒玩家“排查的坐标非法,请重新输入”的字样。
如果合法就会走第一个 if 语句,进去之后我们对该位置进行判断,看是否该位置为字符 '1',如果是字符 '1' 就是踩到了雷,就会提醒玩家“很遗憾,你被炸死了”的字样,并将雷的分布图给玩家呈现出来
如果是字符 '0' 就走 else 语句,对该位置的周围 8 个格子的雷的个数进行计算并标注出来,这时我们就调用GetMineCount()函数来计算,我们看一下内容是什么:
return (mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] - 8 * '0');
我们可以看到这是对该坐标周围的 8 个坐标的字符加起来的,我们知道字符 '1' 和字符 '0' 对应的ASCII码值是相连的,因此我们将周围 8 个的字符加起来减去 8 个字符 '0' ,这样我们就可以得到字符 '1' 的个数,也就是雷的个数。
效果展示:
为了能快速看到,我们将雷的部分数组也展示出来,可以直观的看到。
mine棋盘
show棋盘:
如果我们一步都没有失误,直到整个雷全部排完,就会执行以下代码:
if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功!\n"); DisplayBorad(mine, ROW, COL); }
排雷成功后,我们会再次对雷的布局图进行打印。我们为了方便展示,布置 80 个雷测试一下。
效果展示:
至此,两个小游戏就全部讲完了。
完整代码在代码仓库,入口在这:>