10.数组的应用实例2:扫雷游戏 (综合之前学习的知识代码)
(重点都在注释中)
扫雷游戏的实现:
1. 游戏不退出,继续玩下一把(循环)
2. 应用多文件的形式写代码
game.h -- 游戏函数的声明
#pragma once //该文件存放 游戏函数声明 的代码 #include <stdio.h> #include <stdlib.h> #include <time.h> //游玩时显示的数组大小 #define ROW 9 #define COL 9 //实际数组大小 #define ROWS ROW+2 #define COLS COL+2 //简单版本的雷个数 #define EASY_COUNT 10 //1. InitBoard() -- 初始化棋盘 函数声明 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); //2. DisplayBoard() -- 打印棋盘 //传过来的数组是 11*11 的数组,但(访问)显示的只是其中的 9*9 void DisplayBoard(char board[ROWS][COLS], int row, int col); //3. SetMine() -- 布置雷 void SetMine(char board[ROWS][COLS], int row, int col); //4. FindMine() -- 排查雷(在mine数组中找信息,信息放到show数组中,操作的也是9*9) void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c -- 游戏函数的实现
#define _CRT_SECURE_NO_WARNINGS 1 //该文件存放 游戏实现 的代码 #include "game.h" //1. InitBoard() -- 初始化棋盘 函数实现 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; //遍历行: for (i = 0; i < rows; i++) { //遍历列: int j = 0; for ( j = 0; j < cols; j++) { board[i][j] = set; //直接把棋盘初始化成传过来的 set } } } //2. DisplayBoard() -- 打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { //行和列都是从0开始的,要打印 9*9 ,只需要从第1行和列开始打印就好 int i = 0; printf("---------扫雷游戏--------\n"); for (i = 0; i <= col; i++) //打印列序号 { printf("%d ", i); } printf("\n"); //换行,防止上面和下面的循环在同一行 for (i = 1; i <= row; i++) //从第一行开始 { printf("%d ", i); //打印行序号 int j = 0; for ( j = 1; j <= col; j++) //从第一列开始 { printf("%c ", board[i][j]); } printf("\n"); } } //3. SetMine() -- 布置雷 void SetMine(char board[ROWS][COLS], int row, int col) { //布置10个雷 //生成随机的坐标,布置雷 int count = EASY_COUNT; //布置的雷的数量 while (count) //只要还有雷(非0),就继续布置 { //雷在行列中都是布置在 1-9 //用rand()函数生成随机的x和y坐标 int x = rand() % row + 1; //取余后(row=9)是 0-8 ,再+1后是 1-9 int y = rand() % col + 1; if (board[x][y] == '0') //当前位置无雷才能布置 { board[x][y] = '1'; //布雷 count--; //布雷成功后,布雷数减1 } //直到count = 0;跳出循环 } } //3.5 --- GetMineCount()函数:统计mine数组坐标为x y的位置上雷的个数 int GetMineCount(char mine[ROWS][COLS], int x, int y) { return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1] - 8 * '0'); //把xy坐标周围8个坐标的字符 0(无雷) 或 1(有雷) 加起来, //再 - 8 * '0' ,把字符 0 或 1 转化为 数字(整型)0 或 1 } //4. FindMine() -- 排查雷(在mine数组中找信息,信息放到show数组中,操作的也是9*9) 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) //输入的坐标正确:1-9 { if (mine[x][y] == '1') //踩到雷了 { printf("很遗憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL); //结束后查看游戏情况 break; //这轮游戏结束 } else //没踩到雷的话,统计周围雷的个数 { int count = GetMineCount(mine, x, y); //把周围雷个数传给count //GetMineCount():用于统计周围雷的个数 //统计mine数组中该坐标周围有几个雷,所以要把mine传过去 //雷的个数传到show数组相同x y坐标上 show[x][y] = count + '0'; //show是字符数组,count是数字,+‘0’后转化为字符 //假设count = 3,加上0的ACSII值 48 后,即 51 //ASCII码值51 对应的就是 字符3(ASCII码值为51) DisplayBoard(show, ROW, COL); //打印查看排雷情况 win++; //找到不是雷的位置就++ } } else { printf("坐标非法,重新输入\n"); } } //被炸死 或者 排完雷后 到这位置 if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功\n"); DisplayBoard(mine, ROW, COL); //查看棋盘 } }
1. InitBoard() -- 初始化棋盘 函数实现
2. DisplayBoard() -- 打印棋盘
3. SetMine() -- 布置雷
3.5 --- GetMineCount()函数:统计mine数组坐标为x y的位置上雷的个数
4. FindMine() -- 排查雷(在mine数组中找信息,信息放到show数组中,操作的也是9*9)
test.c -- 测试游戏
#define _CRT_SECURE_NO_WARNINGS 1 //实现扫雷游戏代码 //该文件为 测试游戏 的代码 // 设计要点: //1. 扫雷游戏要存储布置好的雷的信息,需要一个二维数组 //2. 给两个二维数组: 一个存放雷的信息 ; 另一个存放布置好的雷的信息 //3. 为了防止在统计坐标周围的雷的额个数的时候越界,我们让给数组设计为 11 * 11; //4. 数组是 11 * 11,并且是字符数组 #include "game.h" void menu() { printf("***********************************\n"); printf("********** 1.play ***********\n"); printf("********** 0.exit ***********\n"); printf("***********************************\n"); } void game() //在自定义game()函数中实现扫雷游戏的执行 { char mine[ROWS][COLS]; //存放布置好的雷 char show[ROWS][COLS]; //存放排查出的雷的信息 //1. 初始化棋盘 //(1). mine数组最开始全是‘0’; //(2). show数组最开始全是‘#’; InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*'); // 第四个参数为想要初始化成的 符号 //2. 打印棋盘(玩的时候只显示 9*9 ,所以打印 9*9 就可以了) //DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL); //实际显示的棋盘 //3. 布置雷(布置在 9*9 中) SetMine(mine, ROW, COL); //雷是布置在mine数组上的 //DisplayBoard(mine, ROW, COL); //4. 排查雷(在mine数组中找信息,信息放到show数组中,操作的也是9*9) FindMine(mine, show, ROW, COL); } int main() { int input = 0; //使用rand前要设置srand。设置随机数起点 //用time()函数返回时间戳 //返回类型为 无符号整型 srand((unsigned int)time(NULL)); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); //在自定义game()函数中实现扫雷游戏的执行 break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,重新选择\n"); break; } } while (input); //如果选择了0退出游戏,则刚好判断为0退出循环 //非0则继续循环 return 0; }
void menu() --- 打印菜单