- 1.大致思路
- 1.1 创建文件
- 1.2 想法实现
- 设计一个menu函数,实现建议菜单
- `do while`循环和`switch`分支选择游戏选项
- 创造一个扫雷版面
- 版面的大小最后是要可控的
- 如何存放雷和版面的信息呢?
- 考虑排查雷时候的思路,我们要判断该位置周围8个格子里面是否有雷
- 初始化两个数组
- 实现`InitBoard`
- 实现打印雷盘的函数`DisplayBoard`
- 布置雷
- 排查雷
- 判断有几个雷
- 结束判断胜利函数
- 2. 具体实现
- 3.补充内容
扫雷游戏是我们能实现的较简单的游戏之一,在考虑不使用图形界面的前提下,我们尝试仅使用数组来实现扫雷游戏的基础功能
想要制作一个扫雷游戏我们先得熟悉扫雷游戏的规则,我们可以先试试几把扫雷感受扫雷游戏所要实现的功能
点我传送扫雷游戏
1.大致思路 1.1 创建文件还是老样子先创建3个文件
void menu() { printf("******************n"); printf("*** 1.play ***n"); printf("*** 0.exit ***n"); printf("******************n"); }do while循环和switch分支选择游戏选项
int input = 0; do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出n"); default:printf("选择错误,重新选择"); break; } } while (input);//1为真0为假非0都为真创造一个扫雷版面 版面的大小最后是要可控的 如何存放雷和版面的信息呢?
利用二维数组
- 分别创造2个存放字符的char类型二维数组,一个放置布置好雷的信息,还有一个放置排查出的信息
- 这时候就遇到了情况,也就是如果遇到了最边上的话去直接排查周围8个格子可能会造成数组越界
解决方法就是创建一个更大一个维度(9*9->11*11)的数组,为了严格对应,所以最好创建两个一样大的数组
初始化两个数组game.h宏定义行与列数
#define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2
test.c初始化雷的信息存储
//雷的信息存储 char mine[ROWS][COLS] = { 0 };//布置好雷的信息 char show[ROWS][COLS] = { 0 };//排查好雷的信息 printf("扫雷n"); //通过初始化函数实现初始化 InitBoard(mine, ROWS, COLS, '0');//初始化mine数组为全'0' InitBoard(show, ROWS, COLS, '*');//初始化show数组为全'*'实现InitBoard
game.h初始化雷盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
game.c实现InitBoard
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0, j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; //set巧妙让既可以显示*又可以0 } } }实现打印雷盘的函数DisplayBoard
game.h
void DisplayBoard(char board[ROWS][COLS], int row, int col);
game.c
void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0, j = 0; for (i = 0; i <= col; i++)//打印列号 { printf("%d ", i); } printf("n"); for (i = 1; i <= row; i++)//因为传了ROWS少两个 { printf("%d ", i);//行号 for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("n"); } }布置雷
game.h
#define EASY_COUNT 10 void SetMine(char board[ROWS][COLS], int row, int col);//row和col是要打印或者改变的元素数要 *** 作的是9
test.c
播撒随机种子不用放到函数里面,只要放到主函数里面然后,播撒一次,每次循环游戏就可以实现随机数
srand((unsigned int)time(NULL));
game.c
雷要随机布置,所以要用rand和srand,是雷的话就在信息数组里面对应的格子放上1,此外放0
void SetMine(char board[ROWS][COLS], int row, int col) { int count = EASY_COUNT;//布置雷的数字,本质是一个难度分级的选择,也用宏定义 while (count) { int x = rand()% row+1;//1-9 int y = rand() % col + 1;//1-9 mod9=>0-8 need add 1 if (board[x][y] == '0') { board[x][y] = '1'; count--;//直到0退出 } } }排查雷
game.h
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c
在正常的while循环之下分情况用if实现分支
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0, y = 0; int win = 0; //9 * 9情况下 if (x >= 1 && x <= row&&y >= 1 && y <= col) { //坐标合法前提下 //1.踩雷2.不是雷 if (mine[x][y] == '1')//1.踩雷 { printf("很遗憾,你被炸死了n"); DisplayBoard(mine, row, col);//死了之后调一下给打印出来看一看 break; } else//2.不是雷 { //计算周围有几个雷 int count = get_mine_count(mine,x,y); show[x][y] = count + '0'; DisplayBoard(show, row, col); win++; } } else { printf("输入坐标非法,无法排雷,请重新输入!n"); } } }判断有几个雷
game.c
//思考准备把周围数字加起来看有几个雷 //注意每个存的字符都是字符而ASCII'1' - '0'正好是数字1 int get_mine_count(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'; }
这就是我们要用0和1来表示雷的原因,同时也能实现告诉你周围有几个雷,这样就比较巧妙
结束判断胜利函数这时候我们发现虽然可以正常排雷,但是我们不可以做到胜利的判断,所以我们要在排查雷前面加一个循环,就像这样
while (win < row * col - EASY_COUNT) { printf("请输入排查雷的坐标n"); scanf("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { //坐标合法 //1.踩雷2.不是雷 if (mine[x][y] == '1') { printf("很遗憾,你被炸死了n"); DisplayBoard(mine, row, col); break; } else//不是雷 { //计算周围有几个雷 int count = get_mine_count(mine, x, y); show[x][y] = count + '0'; DisplayBoard(show, row, col); win++; } } else { printf("坐标非法请重新输入!n"); } } if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功n"); DisplayBoard(mine, row, col); } }
最后修改一下主函数就可以了
2. 具体实现game.h
#define _CRT_SECURE_NO_WARNINGS 1 #include#define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define EASY_COUNT 10 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); void DisplayBoard(char board[ROWS][COLS], int row, int col); void SetMine(char board[ROWS][COLS], int row, int col);//row和col是要打印或者改变的元素数要 *** 作的是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" void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0, j = 0; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set;//set 巧妙让既可以显示*又可以0 } } } void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0, j = 0; for (i = 0; i <= col; i++)//打印列号 { printf("%d ", i); } printf("n"); for (i = 1; i <= row; i++)//因为传了ROWS少两个 { printf("%d ", i);//行号 for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("n"); } } void SetMine(char board[ROWS][COLS], int row, int col) { int count = EASY_COUNT; while (count) { int x = rand() % row + 1;//1-9 int y = rand() % col + 1;//1-9 mod9=>0-8 need add 1 if (board[x][y] == '0') { board[x][y] = '1'; count--;//直到0退出 } } } void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0, y = 0; int win = 0; //9 * 9 while (win < row * col - EASY_COUNT) { printf("请输入排查雷的坐标n"); scanf("%d%d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { //坐标合法 //1.踩雷2.不是雷 if (mine[x][y] == '1') { printf("很遗憾,你被炸死了n"); DisplayBoard(mine, row, col); break; } else//不是雷 { //计算周围有几个雷 int count = get_mine_count(mine, x, y); show[x][y] = count + '0'; DisplayBoard(show, row, col); win++; } } else { printf("坐标非法请重新输入!n"); } } if (win == row * col - EASY_COUNT) { printf("恭喜你,排雷成功n"); DisplayBoard(mine, row, col); } } //思考准备把周围数字加起来看有几个雷 //注意每个存的字符都是字符而ASCII'1' - '0'正好是数字1 int get_mine_count(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'; }
test.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void menu() { printf("******************n"); printf("*** 1.play ***n"); printf("*** 0.exit ***n"); printf("******************n"); } void game() {//雷的信息存储 //1.布置好的雷的信息 char mine[ROWS][COLS] = { 0 };//11*11 char show[ROWS][COLS] = { 0 }; //2.排查好的雷的信息 printf("扫雷n"); InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*'); //打印 //DisplayBoard(mine,ROW,COL); DisplayBoard(show, ROW, COL); //布置雷 SetMine(mine, ROW, COL);//9*9 //扫雷 Findmine(mine, show, ROW, COL); } void test() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出n"); default:printf("选择错误,重新选择"); break; } } while (input);//1为真0为假非0都为真 } int main() { test(); return 0; }3.补充内容
如果我要改进,使得空白自动展开,但是由于能力有限空白格子都变成了P显示,暂时没找到哪里出现了问题,如果铁子们解决了欢迎交流
利用递归的方法就是:
void space(char board[ROWS][COLS], char mine[ROWS][COLS], int x, int y) { int i = 0, j = 0; if (get_mine_count(mine, x, y)== 0) { board[x][y]= " "; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) { if (i > 0 && i <= ROW && j > 0 && j <= COL && mine[i][j] != '1' && board[i][j] == '*') { space(board, mine, i,j); } } } } else { board[x][y] =get_mine_count(mine, x, y)+'0'; } }
这个P真是没解决掉
小结:
以上就是一个最简单的扫雷游戏的实现了,希望有收获的老铁们一键三连啊!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)