用代码实现了三子棋后,我们还可以实现一个简单的小游戏:扫雷
目录
7.游戏如何结束
1.扫雷的实现逻辑
在棋盘上随机设置一定数量的雷,然后选择一个位置坐标进行排雷,如果这个坐标上是一个雷则会被炸死,如果不是雷,则会在这个位置上展示出一个数字,这个数字是以这个坐标为中心的九宫格内的雷的数量,当雷全部排出之后则获得胜利。
2.设置菜单
设置菜单和三子棋一样
void menu() { printf(" 1.开始游戏 \n"); printf(" 0.退出游戏 \n"); }
然后选择方式
do { menu(); printf("请选择模式\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误\n"); break; } } while (input);
这里我们使用两个数组来存放数据,一个数组是用来存放雷的情况:0表示不是雷,1表示是雷,一个数组是用来展示隐藏雷的情况:*表示这个位置没有被排查,相应的雷的数量表示这个位置已经被排查过了。
void initBoard(char arr[ROWS][COLS], int rows, int cols, char ret) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { arr[i][j] = ret; } } }
用ret来接收相应的数组符号,可以避免使用两个函数分别来初始化雷区数组和展示数组。
这里的ROWS和COLS的数据是12,这是因为,展示九宫格内的雷的数量的时候,有可能玩家排查的位置是棋盘的边缘地带,这样我们进行雷的数量统计时,如果设数组的元素大小为9,会导致数组的越界访问。
在这里我们展示一下雷区棋盘,和展示棋盘,两者都是使用这个函数实现,避免玩家自己数几行几列,这里直接给出了每行每列的信息
void DisplayBoard(char arr[ROWS][COLS], int row, int col) { for (int j = 0; j <= col; j++) { printf("%d ", j); } printf("\n"); for (int i = 1; i <= row; i++) { printf("%d ", i); for (int j = 1; j <= col; j++) { printf("%c ", arr[i][j]); } printf("\n"); } printf("-------------------\n"); }
设置雷区的方式和三子棋中电脑下棋的方式一样,采用rand函数采用时间戳发生变化,
void Set_mine(char mine[ROWS][COLS], int row, int col) { int count = Easy_Count; int x = 0; int y = 0; while (count) { x = rand() % row + 1; y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } }
这里的row和col的数据是9,因为实际中玩家是在9×9的棋盘上排查雷所以只需要在9×9的棋盘上设置雷即可。而rand函数模9得到的是0到8的数字,所以这里进行+1。
7.游戏如何结束
玩家通过输入想要排查的雷的坐标来进行排查
void Find_mine(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) { while (1) { printf("请选择要排查的雷\n"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '1') { printf("雷炸了\n"); DisplayBoard(mine, ROW, COL); break; } else { if (show[x][y] != '*') { printf("该位置以排查过,请重新选择\n"); } int count = Mine_Count(mine, x, y); show[x][y] = count + '0'; DisplayBoard(show, ROW, COL); win++; } } else { printf("选择有错\n"); } } break; } if (win == row * col - Easy_Count) { printf("恭喜你排雷成功\n"); DisplayBoard(show, ROW, COL); } }
1)玩家输入坐标
需要判断玩家输入的坐标是否合理也就是是否在数组范围之外,只有坐标合理才会成功排查雷。
2)排雷错误游戏失败结束
如果玩家排查的位置是雷,则游戏结束,展示雷区的分布情况。
3)排雷成功
如果玩家排查的位置不是雷则展示其九宫格范围的数量,这里需要进行统计雷的数量
int Mine_Count(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'; }
4)全部排雷成功游戏结束
雷全部被排出,说明剩下的*号全都是雷,即剩下雷的数量个*;玩家需要排查的方格数量是row*col-所设置的雷的额数量,使用win来记录玩家排查了的方格数量。当win=row*col-所设置的雷的额数量,则全部的雷排查出来了。
扫雷的介绍就到这里,扫雷的重点就是如何用两个数组来设置雷区和展示棋盘,用展示棋盘在覆盖雷区,用展示数组来展示排雷情况,用雷区数组来判断排雷是否成功。
所有代码。
test.c
#include"game.h" void game() { //扫雷游戏的实现 //初始化 char mine[ROWS][COLS] = { 0 }; char show[ROWS][COLS] = { 0 }; initBoard(mine, ROWS, COLS, '0'); initBoard(show, ROWS, COLS, '*'); //布置雷 Set_mine(mine, ROW, COL); //DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL); Find_mine(mine,show, ROW, COL); } void menu() { printf(" 1.开始游戏 \n"); printf(" 0.退出游戏 \n"); } int main() { int input = 0; srand((unsigned)time(NULL)); do { menu(); printf("请选择模式\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误\n"); break; } } while (input); return 0; }
game.h
#include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 9 #define COL 9 #define COLS COL+2 #define ROWS ROW+2 #define Easy_Count 10 //初始化棋盘 void initBoard(char arr[ROWS][COLS], int rows, int cols, char ret); //展示棋盘 void DisplayBoard(char arr[ROWS][COLS], int row, int col); //布置雷 void Set_mine(char mine[ROWS][COLS], int row, int col); //排查雷 void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
#include"game.h" int Mine_Count(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'; } void Find_mine(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) { while (1) { printf("请选择要排查的雷\n"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '1') { printf("雷炸了\n"); DisplayBoard(mine, ROW, COL); break; } else { if (show[x][y] != '*') { printf("该位置以排查过,请重新选择\n"); } int count = Mine_Count(mine, x, y); show[x][y] = count + '0'; DisplayBoard(show, ROW, COL); win++; } } else { printf("选择有错\n"); } } break; } if (win == row * col - Easy_Count) { printf("恭喜你排雷成功\n"); DisplayBoard(show, ROW, COL); } } void Set_mine(char mine[ROWS][COLS], int row, int col) { int count = Easy_Count; int x = 0; int y = 0; while (count) { x = rand() % row + 1; y = rand() % col + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; count--; } } } void initBoard(char arr[ROWS][COLS], int rows, int cols, char ret) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { arr[i][j] = ret; } } } void DisplayBoard(char arr[ROWS][COLS], int row, int col) { for (int j = 0; j <= col; j++) { printf("%d ", j); } printf("\n"); for (int i = 1; i <= row; i++) { printf("%d ", i); for (int j = 1; j <= col; j++) { printf("%c ", arr[i][j]); } printf("\n"); } printf("-------------------\n"); }