文章目录
- 前言
- 一、效果图(展示)
- 二、整体结构及功能介绍
- 需要思考的问题
- 三、功能解析及代码实现
- 四、完整源码展示
- 总结
前言
“扫雷”相信小伙伴们都玩过吧,上机课偷偷玩机房的电脑,只有扫雷,纸牌等小游戏,打磨打磨上课的时间哈哈。
经过自己一段时间的学习后,接下来细讲一下我做的扫雷小程序吧!(附加区域展开效果哦~)
一、效果图(展示)
先展示一下程序运行效果图吧
打印菜单+初始化扫雷界面
接着扫雷游戏进行,输入排查坐标(如果该坐标附近区域无雷(全为0)即可展开附近一片)
接着继续输入坐标,如果该坐标是雷,则游戏结束,可选择继续游戏也可选择退出,继续游戏前可以按 2 实现清屏,以防上一局的游戏干扰视线
游戏结束后会展开所有坐标,查看雷或非雷的区域
二、整体结构及功能介绍
要想扫雷,首先得有一块足够埋雷的空间,扫雷时要想想该如何实现如果该格子周围八个格子都没有雷,该区域就会被清空;踩到雷,即游戏结束。
所以我们理清思路开始逐一实现
1、创建雷盘
2、初始化雷盘
3、打印雷盘
4、随机布置你定义的雷的数量
5、展开式排雷
程序文件还是与三子棋同样思路
test.c
;game.c
;game.h
同三子棋
需要思考的问题
对这上一个小游戏三子棋的思想,想完成一个大的平台,我们可以利用二维数组来存放雷的信息。
首先要电脑实现随机分布各个雷的位置、位置信息只有开发者能看到和游戏结束时能看到
三、功能解析及代码实现
创建雷盘、布置雷盘、初始化、打印
最上面和最左边的数字代表的是列与行坐标,'0'
代表没有雷,'1'
则为雷,'*'
表示的是该点坐标还未进行扫雷;
如果9X9 的平台,当输入坐标为 3,1 时,发现左边有三个位置是超出我们定义的 9X9 数组范围的,那么如果解决这个问题呢?
我们可以让9X9的范围行列都向外扩展一圈,此时9X9就变为 11X11的范围了,接着可以把外围的格子初始化为0然后不显示外围的数据,这样就可以避免后续排查雷的判断了。
void init_board(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 display_board(char board[ROWS][COLS], int row, int col)
{int i = 0, j = 0;printf("----------扫雷游戏----------\n");// 列号for ( j = 0; j <= col; j++){printf("%d ", j);}printf("\n");for ( i = 1; i <= row; i++){printf("%d ", i);for ( j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}printf("----------扫雷游戏----------\n");
}void set_mine(char mine[ROWS][COLS], int row, int col)
{// 布置10个雷int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}
}
接着就是扫雷了,这里我没有添加第一次排雷不被炸死功能,此功能可以先用if判断第一次输入的坐标是否为雷,如果是雷则可以在雷盘上重新找一个非雷的位置将开始的雷移到其他地方,小伙伴可以自行实现哦~
扫雷功能实现:玩家输入一个坐标,如果是雷,则游戏结束,如果不是雷,并且该附近区域无雷,则展开一篇,游戏继续,直到下一次排到雷或者所有非雷位置被排查完,则游戏结束
// 统计
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');
}// 递归实现展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数if (count_number == 0){show[x][y] = ' ';if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*'){Spread(mine, show, x - 1, y - 1);}if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*'){Spread(mine, show, x - 1, y);}if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*'){Spread(mine, show, x - 1, y + 1);}if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*'){Spread(mine, show, x, y - 1);}if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*'){Spread(mine, show, x, y + 1);}if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*'){Spread(mine, show, x + 1, y - 1);}if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*'){Spread(mine, show, x + 1, y);}if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*'){Spread(mine, show, x + 1, y + 1);}}else{show[x][y] = count_number + '0';}
}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{// 1. 输入排查的坐标// 2. 检查坐标处是不是雷// (1)是雷 - boom - game over // (2)不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("请输入要排查雷的坐标:");scanf("%d %d", &x, &y);// x -- (1,9) y -- (1,9)//判断坐标的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了!\n");display_board(mine, ROW, COL);break;}else{// 不是雷的情况下,统计x,y坐标周围有几个雷int count = get_mine_count(mine, x, y);show[x][y] = count + '0';Spread(mine, show, x, y);//显示排查出的信息display_board(show, ROW, COL);win++;}}else{printf("该坐标已排查过\n");}}else{printf("坐标输入有误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功!\n");display_board(show, ROW, COL);}
}
四、完整源码展示
test.c
#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void menu()
{printf(" -------------------\n");printf("| 1.play |\n");printf("| 2.clear |\n");printf("| 0.exit |\n");printf(" -------------------\n");
}void game()
{// 设计2个数组存放信息char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };// 初始化棋盘// mine初始化为全'0'// show初始化为全'*'init_board(mine, ROWS, COLS, '0');init_board(show, ROWS, COLS, '*');// 打印棋盘//display_board(mine, ROW, COL);//display_board(show, ROW, COL);// 布置雷set_mine(mine,ROW,COL);// 排雷//display_board(mine, ROW, COL);display_board(show, ROW, COL);find_mine(mine, show, ROW, COL);}int main()
{srand((unsigned)time(NULL));int input = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1:game();break;case 2:system("cls"); // 清屏break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);return 0;
}
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2// 默认雷
#define EASY_COUNT 20// 函数声明// 初始化
void init_board(char board[ROWS][COLS], int rows, int cols,char set);// 打印棋盘
void display_board(char board[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);// 展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
game.c
#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void init_board(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 display_board(char board[ROWS][COLS], int row, int col)
{int i = 0, j = 0;printf("----------扫雷游戏----------\n");// 列号for ( j = 0; j <= col; j++){printf("%d ", j);}printf("\n");for ( i = 1; i <= row; i++){printf("%d ", i);for ( j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}printf("----------扫雷游戏----------\n");
}void set_mine(char mine[ROWS][COLS], int row, int col)
{// 布置10个雷int count = EASY_COUNT;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (mine[x][y] == '0'){mine[x][y] = '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');
}// 递归实现展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数if (count_number == 0){show[x][y] = ' ';if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*'){Spread(mine, show, x - 1, y - 1);}if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*'){Spread(mine, show, x - 1, y);}if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*'){Spread(mine, show, x - 1, y + 1);}if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*'){Spread(mine, show, x, y - 1);}if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*'){Spread(mine, show, x, y + 1);}if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*'){Spread(mine, show, x + 1, y - 1);}if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*'){Spread(mine, show, x + 1, y);}if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*'){Spread(mine, show, x + 1, y + 1);}}else{show[x][y] = count_number + '0';}
}void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{// 1. 输入排查的坐标// 2. 检查坐标处是不是雷// (1)是雷 - boom - game over // (2)不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续int x = 0;int y = 0;int win = 0;while (win < row * col - EASY_COUNT){printf("请输入要排查雷的坐标:");scanf("%d %d", &x, &y);// x -- (1,9) y -- (1,9)//判断坐标的合法性if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾,你被炸死了!\n");display_board(mine, ROW, COL);break;}else{// 不是雷的情况下,统计x,y坐标周围有几个雷int count = get_mine_count(mine, x, y);show[x][y] = count + '0';Spread(mine, show, x, y);//显示排查出的信息display_board(show, ROW, COL);win++;}}else{printf("该坐标已排查过\n");}}else{printf("坐标输入有误,请重新输入\n");}}if (win == row * col - EASY_COUNT){printf("恭喜你,排雷成功!\n");display_board(show, ROW, COL);}
}
总结
以上就是C语言实现扫雷小游戏的分析了,还有部分功能期待小伙伴们能补全!
希望该文章能对小伙伴们有所帮助!留个赞👍再走吧~
(如有错误,望指出)