摘要:如果整个游戏的数据设计都基于一个二维数组的话相对来说容易混淆,比如只有一个数组的话,除了要对区分雷区与非雷区加以处理,还有后续排雷的信息要处理。
今天要分享给大家的是扫雷的代码实现,和前几天写的那个三子棋差不多,大体思想就是以二维数组为载体,编写设计函数来实现它的各种功能。我们先来看看最后的成果展示吧(完整代码在文章末尾处~)
首先从这个成果图中可以看出,游戏结束后可以选择再来一次,也可以退出,所以在代码中我们肯定是将整个游戏过程放在一个循环里面,我是采用的do-while循环,大致构思与前面写的三子棋相同。看代码:
void test(){ int input = 0; do { srand((unsigned)time(NULL));//利用时间戳来设置随机种子 menu(); printf("请选择->"); scanf("%d", &input); switch (input) { case 1: printf("扫雷/n"); game(); break; case 0: printf("退出游戏/n"); break; default: printf("输入不合法,请重新输入!/n"); } } while (input);}
在这里补充一下为什么要将input作为while循环的条件哈,因为输入1时,input的值为1,为真,与之对应的是play,开始游戏;输入0时,为假,对应的是exit,刚好也是跳出循环,输入其他值时会被要求重新输入,直到输入0或1。这样安排一举两得哈哈哈。
当输入1后,程序会进入到game()函数,也就是我们游戏的主要设计了。
我主要创建了两个相同的二维数组,mine[ROWS][COLS]数组用来存放雷的信息;show[ROWS][COLS]数组用来展示雷盘,后续的排雷过程也是在此二维数组上来展示。
如果整个游戏的数据设计都基于一个二维数组的话相对来说容易混淆,比如只有一个数组的话,除了要对区分雷区与非雷区加以处理,还有后续排雷的信息要处理。倒也不是说不能用一个二维数组,用2个二维数组是为了使思路更清晰。
创建好了之后就调用以下函数InitBoard()对它们进行初始化
void InitBoard(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; } }}
然后我们可以写一个打印数组的函数DisplayBoard(),用来模拟玩游戏时出现在界面上的雷盘。
void DisplayBoard(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; for (i = 0; i <=row; i++) { printf(" %d ", i); } printf("/n"); for (i = 1; i <=col; i++) { printf(" %d ", i); for (j = 1; j <=col; j++) { printf(" %c ", board[i][j]); } printf("/n"); }}
之后我们要开始对mine数组进行埋雷了,因为mine数组是用来存放雷的信息的,而show是来展示的,所以不需要对show数组埋雷。雷区用字符‘1’来表示,非雷区用字符‘0’来表示。这里用的是SetMine()函数,下面是代码实现:
void SetMine(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int count = COUNT; while(count)//雷的个数 { i = rand() % row + 1; j = rand() % col + 1; if (board[i][j] == "0") { board[i][j] = "1"; count--; } }}
下面函数是用来统计某个非雷区周围有几个雷区的,用get_mine_count()函数实现。很简单,我们直接看代码:
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";}
以上基本就是准备工作,接下来就是排雷操作了。主要用 FindMine()函数来实现。排雷操作我主要是对show数组的数据进行更改。因为展现在大家面前的就是show数组来模拟的一个棋盘。因为mine数组和show数组的格式是相同且一一对应的。然后大致思想就是将用户要排查的坐标在mine数组进行比对,如是否踩到雷或其周围有几个雷等,然后将结果反映到show数组对应的坐标上。让我们来看代码是怎样实现的:
void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int n = 0; while (n < (ROW * COL - COUNT)) { printf("请输入要排查的坐标->"); scanf("%d %d", &i, &j); if (i >= 1 && i <= 9&& j >= 1 && j <= 9&& board2[i][j]=="*") { if (board1[i][j] == "1") { printf("很遗憾,,你被炸死了/n"); DisplayBoard(board1, ROW, COL); break; } else// { spread(board1, board2, i, j); DisplayBoard(board2, row, col); n++; } } else printf("输入不合法,请重新输入!"); } if (n == row * col - COUNT) printf("排雷成功!!!/n");}
这里有个spread()函数必须要讲一下,这也是游戏设计中较难的一点。其作用就是若以输入坐标为中心,若其周围8个坐标都没有雷则将这8个坐标全部展开。再以展开的坐标依次为中心,判断其周围8个坐标是否不存在雷(已展开的坐标不用再判断,否则会形成死递归),若不存在则再展开它周围的8个坐标,然后再对这8个坐标依次进行判断......以此类推,直到不能再展开为止。我们先来看一看它的具体代码:
void spread(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y){ if (0 == get_mine_count(mine, x, y)) { show[x][y] = " "; int i = 0; int j = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) if (show[i][j] == "*" && i >0 && j > 0 && i <=ROW && j <= COL) spread(mine, show, i, j); } } else { int m = get_mine_count(mine, x, y); show[x][y] = m + "0"; } }
这段代码是怎样实现上述功能的呢?不难看出,这里用到了递归思想。我是先对传进来的坐标进行判断,若此坐标对应的mine数组的坐标的周围8个坐标都没有雷,则将该坐标对应的show数组的元素置为字符‘ ’,再对它周围的8的坐标一一排查,若排查到某一个坐标的周围也都没有雷,则再将这某一个坐标置为‘ ’,然后再对这某一个坐标的周围8个坐标一一进行排查.......直到排查的某一个坐标的周围8个坐标的周围都至少有一个雷时停止,然后将这些不能被置为‘ ’的坐标对应的show数组的元素置为数字字符,有几个雷就显示数字字符几。
最后再补充一下,我是怎样用数字字符来显示某个非雷区的周围有几个雷的。因为数组定义的是字符数组,所以不能直接用数字来表示。那如果某个非雷区周围有3个雷的话我们怎么重置该字符数组元素好让玩家知道呢?这里就不得不先来看一下这个ASCII表:
数字3不能用来表示,但我们可以用字符‘3’来表示,通过上图可以看出若想得到字符‘3’,则只需要在字符‘0’上加上数字3即可,字符‘0’对应的ASCII码值为48,加上3就是51,刚好对应字符‘3’。同样的,若想得到字符‘2’,则只需要用‘0’+2就行了,即用‘0’+数字就可以得到与数字相同的字符了。
好了好了,到这里实现各功能的函数就大致讲完了,觉得还可以个小伙伴就给个赞吧,三连当然是最好啦。最后在这里附上全部代码。test.c里面是游戏实现逻辑,game.c里面是游戏各函数实现逻辑,game.h里面是头文件的包含,各函数、符号的声明。至于为什么这么设计欢迎看我前几天写的三子棋哈,里面有讲解。
game.h
#pragma once//头文件的包含#include#include#include//符号的的声明#define ROW 9#define COL 9#define COLS COL+2#define ROWS ROW+2#define COUNT 10//函数的声明void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化棋盘void DisplayBoard(char bodrd[ROWS][COLS], int row, int col);//打印棋盘void SetMine(char[ROWS][COLS], int row, int col);//布置雷void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col);//排查雷
game.c
//游戏各函数实现逻辑#define _CRT_SECURE_NO_WARNINGS #include "game.h"#define _CRT_SECURE_NO_WARNINGS //初始化棋盘void InitBoard(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; } }}//打印棋盘void DisplayBoard(char board[ROWS][COLS], int row, int col){ int i = 0; int j = 0; for (i = 0; i <=row; i++) { printf(" %d ", i); } printf("/n"); for (i = 1; i <=col; i++) { 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 i = 0; int j = 0; int count = COUNT; while(count)//雷的个数 { i = rand() % row + 1; j = rand() % col + 1; if (board[i][j] == "0") { board[i][j] = "1"; count--; } }}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";}/*若以输入坐标为中心,其周围8个坐标都没有雷则全部展开。再以展开的坐标依次为中心,判断其周围8个是否存在雷(已展开的坐标不用再判断,否则会形成死递归)以此类推,直到不能再展开为止。*/void spread(char mine[ROWS][COLS],char show[ROWS][COLS], int x, int y){ if (0 == get_mine_count(mine, x, y)) { show[x][y] = " "; int i = 0; int j = 0; for (i = x - 1; i <= x + 1; i++) { for (j = y - 1; j <= y + 1; j++) if (show[i][j] == "*" && i >0 && j > 0 && i <=ROW && j <= COL) spread(mine, show, i, j); } } else { int m = get_mine_count(mine, x, y); show[x][y] = m + "0"; } }void FindMine(char board1[ROWS][COLS], char board2[ROWS][COLS], int row, int col){ int i = 0; int j = 0; int n = 0; while (n < (ROW * COL - COUNT)) { printf("请输入要排查的坐标->"); scanf("%d %d", &i, &j); if (i >= 1 && i <= 9&& j >= 1 && j <= 9&& board2[i][j]=="*") { if (board1[i][j] == "1") { printf("很遗憾,,你被炸死了/n"); DisplayBoard(board1, ROW, COL); break; } else//统计雷的个数 { spread(board1, board2, i, j); DisplayBoard(board2, row, col); n++; } } else printf("输入不合法,请重新输入!"); } if (n == row * col - COUNT) printf("排雷成功!!!/n");}
test.c
#define _CRT_SECURE_NO_WARNINGS #include"game.h"void menu(){ printf("************************/n"); printf("******** 1.play ********/n"); printf("******** 0.exit ********/n"); printf("************************/n");}void game(){ char mine[ROWS][COLS] = { 0 };//布置雷的棋盘 char show[ROWS][COLS] = { 0 };//排查雷的棋盘,也就是用户端看到的棋盘 InitBoard(mine, ROWS, COLS, "0");//初始化mine数组全为"0" InitBoard(show, ROWS, COLS, "*");//c初始化show数组全为’*‘ SetMine(mine, ROW, COL);//布置雷 //DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL);//打印雷的棋盘 FindMine(mine,show,ROW,COL);//排雷}void test(){ int input = 0; do { srand((unsigned)time(NULL));//利用时间戳来设置随机种子 menu(); printf("请选择->"); scanf("%d", &input); switch (input) { case 1: printf("扫雷/n"); game(); break; case 0: printf("退出游戏/n"); break; default: printf("输入不合法,请重新输入!/n"); } } while (input);}int main(){ test(); return 0;}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/123505.html
摘要:函数游戏菜单请选择扫雷游戏退出游戏选择错误解析函数内部利用时间戳,形成随机数,主要目的是实现游戏中地雷的随机埋放。 前言 本篇文章使用C语言实现简单小游戏---扫雷。(文章最后有完整代码链接) 想必大多数人都玩过或者了解过扫雷的游戏规则,但是在这里,我们在一起重温一下扫雷的游戏规则,也更好...
摘要:目录前言前言前期的准备前期的准备游戏代码的具体实现游戏代码的具体实现完整版的扫雷小游戏代码完整版的扫雷小游戏代码总结总结前言扫雷是一款大众类的益智小游戏,于年发行。 目录 前言 前期的准备 游戏代码的具体实现 1、text.c 2、game.h 3、game.c 完整版的扫雷小游戏代码: 1...
摘要:展示雷盘和初始化雷盘不一样,展示雷盘只需要用即可,并不需要将都展示出来,只是为了我们更好的计算扫雷的位置周围的雷的数量。 目录 1、需求分析 2、程序架构 3、代码实现(分函数呈现) (1)主函数代码实现 分析: 异常处理: (2)游戏主函数实现 分析: (3)初始化函数的实现 分析: (4...
摘要:玩家选择开始游戏后,出现雷盘,并且随机布置雷。雷盘的数组大小为,方便计算扫雷时周围雷的数量,并防止数组越界。放置布置的雷的信息放置排查出雷的信息初始化雷盘初始化展示界面打印展示界面效果如下布置雷随机在数组中让十个变成作为雷。 目录 前言 一、游戏思路 二、游戏框架 1.菜单界面 1.菜单:...
摘要:写在前面我们已经写过了三子棋小游戏肯定没玩过瘾,我们再写个扫雷小游戏吧目录写在前面认识游戏游戏规则游戏框架游戏实现效果展示全部代码文件文件文件认识游戏相信大家对扫雷都不陌生每台电脑必备的小游戏游戏规则就是在规定的时间将 ...
阅读 2094·2021-11-16 11:45
阅读 1130·2021-10-22 09:53
阅读 3955·2021-09-07 10:26
阅读 1181·2021-09-06 15:00
阅读 2053·2019-08-28 18:09
阅读 2769·2019-08-26 14:06
阅读 3892·2019-08-26 13:48
阅读 1279·2019-08-26 12:11