- 一.游戏介绍
- 二.游戏步骤及实现的功能
- 1.初始化雷盘
- 2.打印雷盘
- 3.随机布置雷
- 4.玩家排雷
- 5.防止玩家第一次被炸死
- 6.统计所选位置周围八个位置中雷的个数
- 7.递归拓展已选位置周围的区域
- 8.标记雷及取消标记
看到这张图片,相信很多小伙伴都非常熟悉,很多小伙伴都玩过扫雷这个小游戏,扫雷是一款益智类游戏,在放松娱乐的同时可以锻炼各位小伙伴的智商。
游戏规则:如上图,玩家需要在不被炸死的前提下找出图中雷的位置,若能找出所有雷,则游戏胜利,若不幸踩到雷则被炸死。
注:先介绍程序实现的主要功能,后文会有完整代码
二.游戏步骤及实现的功能(一) 游戏步骤
- 程序开始执行时玩家需要选择是否开始游戏,输入1则游戏开始,输入0则退出游戏
- show地图出现后玩家开始选择进行选择,输入1则开始选择区域,输入2则可以标记自己认为是雷的区域,输入3则可以取消原先被标记的区域
- 当所有非雷区域全部被排出来后则游戏胜利
//遍历show地图,以便判断最后的胜利 int Travel(char show[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int win = 0; for (i = 1; i <= row; i++) { for (j = 1; j <= col; j++) { if (show[i][j] == '*' || show[i][j] == '!') { win++; } } } return win; }
以下为效果图:
(二)实现的功能
- 初始化雷盘
- 打印雷盘
- 随机布置雷
- 玩家开始排雷
- 防止玩家第一次被雷炸死.
- 统计所选位置周围八个位置中雷的个数
- 递归拓展已选位置周围的区域
- 标记雷及取消标记
初始化雷盘时需要构造两个二维数组,一个数组(mine数组)里面是存放雷的,用于实现各种功能,另一个数组(show数组)是给玩家 *** 作时看的,看不到雷的具体位置。
由于需要统计每个位置周围八个区域中雷的个数,在统计最边缘的位置时为了利于功能的实现,在初始化雷盘时构建的二维数组mine数组的行和列比show数组多两行两列。
//初始化雷盘 //主函数中函数的调用 //Initboard(mine, ROWS, COLS,'0'); //Initboard(show, ROWS, COLS, '*'); 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; } } }
初始化雷盘时,mine数组全部初始化为字符‘0’,show数组全部初始化为字符‘*’。
2.打印雷盘玩家需要通过打印出的show数组雷盘进行游戏,打印雷盘时将行号和列号全部打印出来有利于玩家进行 *** 作
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++) { printf("%d ", i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("n"); } }
雷盘打印如下:
在show数组中,用字符‘0’表示无雷区域,用字符‘1’表示有雷区域,由于第一个步骤中已经将show数组全部初始化为字符‘0’了,故只需使用srand和rand函数生成随机数,使得雷的分布为随机位置。
//随机布置雷 void SetMine(char board[ROWS][COLS], int row, int col) { int x = 0, y = 0; int count = EASY_COUNT; while (count) { x = rand() % row+1; y = rand() % col+1; if (board[x][y] != '1') { board[x][y] = '1'; count--; } } }4.玩家排雷
玩家根据show数组展示出的地图开始排雷,选择自己认为不是雷的区域
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int ch = 0; int flag_count = 0; int win = 0; int fch = 1;//用来标记玩家是否为第一次排雷 while (1) { menu1(); scanf("%d", &ch); if (ch == 1) { int x = 0, y = 0; printf("请开始排雷:>"); scanf("%d%d", &x, &y); //判断坐标合法 if (x <= row && x > 0 && y > 0 && y <= col) { //判断玩家是否是第一次排雷 if (fch == 1 && mine[x][y] == '1') { //是第一次排雷 ChangePlace(mine, row, col, x, y); fch++; } else { //判断是否踩雷 if (mine[x][y] == '1') { printf("游戏结束n"); printf("恭喜你,踩到雷了n"); DisplayBoard(mine, row, col); break; } else { broad(mine, show, x, y); DisplayBoard(show, row, col); } fch++; } } else { printf("输入坐标不合法,请重新输入n"); } } else if (ch == 2) { printf("请开始标记雷:>n"); //标记雷的函数 Flagmine(show, row, col, flag_count); DisplayBoard(show, row, col); } else if (ch == 3) { printf("请选择要取消标记的位置:>n"); //取消标记的函数 Cancelflag(show, row, col, flag_count); DisplayBoard(show, row, col); } //遍历show地图(改进) win=Travel(show, row, col); if (win == EASY_COUNT) break; } if (win == EASY_COUNT) { printf("恭喜你,游戏胜利n"); } }5.防止玩家第一次被炸死
如果玩家第一次就踩雷,则提示玩家重新选择,并将该位置的雷重新随机布置。
//防止玩家第一次排雷被炸死 void ChangePlace(char mine[ROWS][COLS], int row, int col, int x, int y) { x = rand() % row; y = rand() % col; mine[x][y] = '1'; printf("第一次就踩雷了,重新选择n"); }6.统计所选位置周围八个位置中雷的个数
统计已选位置周围八个位置中含有雷的个数,并在该位置上数字的形式打印出来。
//计算坐标周围雷的个数 int get_mine(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'; }
此处由于数组mine中存放的是字符’0’,而不是数字0,故当统计完八个位置后需要减去字符’0’之后返回为数字。
7.递归拓展已选位置周围的区域以递归的方式拓展式排雷。
//拓展周围不是雷的区域 void broad(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { //判断坐标是否越界 if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1) return; //判断是否已经被排除 if (show[x][y] != '*') { return; } int count = get_mine(mine, x, y); if (count > 0) { show[x][y] = count + '0'; return; } //递归拓展地图 else if (count == 0) { show[x][y] = '0'; broad(mine, show, x - 1, y); broad(mine, show, x - 1, y - 1); broad(mine, show, x, y - 1); broad(mine, show, x + 1, y - 1); broad(mine, show, x + 1, y); broad(mine, show, x + 1, y + 1); broad(mine, show, x, y + 1); broad(mine, show, x - 1, y + 1); } }
如果只能一个一个雷的排,将会使得此游戏无法进行,故当选择一个位置a后对a周围八个区域进行排除,若其中一个位置b周围八个位置仍没有雷,就继续对b周围的八个位置进行排雷,以此递归的方式不断排除。
效果如下:
玩家可以通过输入坐标对自己觉得是雷的位置进行标记,标记后为‘!’,如果觉得不是也可以取消标记,取消标记后恢复为‘*’。
//标记雷 void Flagmine(char show[ROWS][COLS], int row, int col,int flag_count) { int x = 0, y = 0; //判断标记数与雷数是否相等 if (flag_count == EASY_COUNT) { printf("标记的雷数和实际存在的雷数相等,无法再标记n"); return; } printf("请输入你要标记位置的坐标:>n"); scanf("%d%d", &x, &y); //判断坐标是否合法 if (x > 0 && x <= row && y > 0 && y <= col) { //判断该坐标是否仍未被排除 if (show[x][y]=='*') { show[x][y] = '!'; flag_count++; } else { printf("该位置不可能是雷,请重新输入n"); } } else { printf("该坐标不合法,请重新输入:>n"); } } //取消标记 void Cancelflag(char show[ROWS][COLS], int row, int col, int flag_count) { int x = 0; int y = 0; scanf("%d%d", &x, &y); //判断坐标是否合法 if (x > 0 && x <= row && y > 0 && y <= col) { //判断该位置是否被标记过 if (show[x][y] == '!') { show[x][y] = '*'; flag_count--; } else printf("该位置未被标记过,无需取消标记n"); } else { printf("该坐标不合法,请重新输入:>n"); } }
图中‘!’即为标记区域
综上,此程序基本实现了扫雷小游戏的功能,有一定的娱乐性,各位小伙伴感兴趣的话可以玩一把。
源代码链接:扫雷完整版源代码
感兴趣的小伙伴也可以直接点击此处开始玩游戏,体验一把扫雷.exe,赶紧开始你的扫雷之旅吧。
各位大佬有建议可以多多交流,欢迎评论区讨论。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)