本文使用C语言简单完成扫雷游戏的超级简单版本
实现功能:
实现简单版本的扫雷游戏,可以通过控制输入坐标显示该坐标周围有几个雷
游戏可以通过菜单实现继续玩或者退出游戏
默认随机布置10个雷
扫雷游戏网页版 - Minesweeperhttps://www.minesweeper.cn/分析:
如图片所示,这是一个 9*9 的简单版扫雷游戏,我们随便点击一个位置就显示出来周围有几个雷
如果我们点击(4,5)的位置我们可以显示周围八个位置雷的个数,但如果是(9,9)周围八个的位置的访问就会越界,所以我们自己实际设计的棋盘行和列都要扩充两位
采用 11*11 的棋盘这样统计雷的个数就不会越界,首先我们用两个二维数组,minu数组是装雷的信息(这个棋盘是内部棋盘是记录雷的位置和非雷的位置),show数组是装入排除雷的信息(这个棋盘会一直显示给用户看还),用户通过show数组显示的信息选择坐标访问minu数组的坐标将选择的结果传入show数组显示给用户看
首先我们设置两个棋盘(11*11类型)
//用两个数组来表示两个棋盘.一个棋盘装雷的信息一个棋盘装排除雷的信息,用char类型,因为这边我们用'0'初始化第一个数组,'*'初始化第二个数组
char minu[Rows][Cols] = { 0 };
char show[Rows][Cols] = { 0 };
然后对这两个二维数组进行初始化让minu数组里面全是字符串‘0’,show数组里面全是字符串‘*’
//初始化棋盘
void Initboard(char board[Rows][Cols], int row, int col, char set) {
int i = 0;
int j = 0;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
board[i][j] = set;//set是初始化的值如果是minu数组set就是'0',如果是show数组set就是'*'
}
}
}
然后打印棋盘可让用户方便选择坐标
//打印棋盘
void DisplayBoard(char board[Rows][Cols], int row, int col) {
int i = 0;
int j = 0;
printf("--------扫雷---------\n");
for (i = 0; i <= row; i++) {
printf("%d ", i);//打印坐标的行
}
printf("\n");
for (i = 1; i <=row; i++) {//因为这里打印的棋盘是真正的棋盘所以是9*9
printf("%d ", i);//打印坐标的列
for (j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------扫雷---------\n");
}
然后就开始布置雷的位置这里用到srand和rand函数在minu数组里生成十个不同的随机数
//布置雷
void SetMine(char board[Rows][Cols], int row, int col) {
//因为雷有十个
int count = Easycose;
while (count) {
//生成随机下标
int x = rand() % row +1;
int y = rand() % col +1;
if (board[x][y] != '1') {
board[x][y] = '1';
count--;
}
}
}
然后统计用户选择的非雷坐标周围雷的个数再在show数组上面显示
//排查雷
void FindMine(char minu[Rows][Cols], char show[Rows][Cols], int row, int col) {
int x = 0;
int y = 0;
int win = 0;
while (win < Row * Col - Easycose) {//这里Row * Col - Easycose是统计非雷的个数,当win=Row * Col - Easycose时就是排查雷结束的时候
//DisplayBoard(minu, Row, Col);
printf("请输入你选的下标:");
scanf("%d %d", &x, &y);
if (x >=1 && x <= Row && y>=1 && y <= Col) {
if (minu[x][y] == '1') {
printf("此处是雷,你失败了\n");
DisplayBoard(minu, Row, Col);
break;
}
else {
//统计附近有多少雷
int c= CountMinu(minu, x, y);//统计选择的非雷坐标周围的雷的个数
show[x][y] = c + '0';
DisplayBoard(show, Row, Col);
win++;//不是雷的位置减少
}
}
else {
printf("选的下标超出界限,请重新输入:\n");
}
}
if (win == Row * Col - Easycose) {
printf("恭喜你排雷成功\n");
DisplayBoard(minu, Row, Col);
}
}
如何实现统计非雷坐标周围雷的个数?
只要将这八个位置的字符串的值转换一下统计
因为一开始雷是字符串'1',非雷是字符串'0',这里只要拿字符串‘1’-‘0’就等于数字1了
//统计附近雷的个数
int CountMinu(char minu[Rows][Cols], int x, int y) {
return (minu[x - 1][y - 1] + minu[x - 1][y] + minu[x - 1][y + 1] + minu[x][y - 1] + minu[x][y + 1] + minu[x + 1][y - 1] + minu[x + 1][y] + minu[x + 1][y + 1] - 8 * '0');
}
到这里我们就可以完成整个代码
首先搞一个头文件test.h这里定义实际棋盘大小和显示棋盘大小还有雷的个数还有各种函数的声明
//test.h文件
#define _CRT_SECURE_NO_WARNINGS 1
#define Col 9//棋盘的宽
#define Row 9//棋盘的长
#define Easycose 10//定义有十个雷
#define Cols Col+2//防止数组溢出
#define Rows Row+2//防止数组溢出
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//初始化棋盘
void Initboard(char board[Rows][Cols], int row, int col, char set);
//打印棋盘
void DisplayBoard(char board[Rows][Cols], int row, int col);
//布置雷
void SetMine(char board[Rows][Cols], int row, int col);
//排查雷
void FindMine(char minu[Rows][Cols], char show[Rows][Cols], int row, int col);
//统计周围雷的个数
int CountMinu(char minu[Rows][Cols], int x, int y);
然后是源文件game.c文件完成各种函数的实现
//game.c文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"test.h"
//初始化棋盘
void Initboard(char board[Rows][Cols], int row, int col, char set) {
int i = 0;
int j = 0;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
board[i][j] = set;//set是初始化的值如果是minu数组set就是'0',如果是show数组set就是'*'
}
}
}
//打印棋盘
void DisplayBoard(char board[Rows][Cols], int row, int col) {
int i = 0;
int j = 0;
printf("--------扫雷---------\n");
for (i = 0; i <= row; i++) {
printf("%d ", i);//打印坐标的行
}
printf("\n");
for (i = 1; i <=row; i++) {//因为这里打印的棋盘是真正的棋盘所以是9*9
printf("%d ", i);//打印坐标的列
for (j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------扫雷---------\n");
}
//布置雷
void SetMine(char board[Rows][Cols], int row, int col) {
//因为雷有十个
int count = Easycose;
while (count) {
//生成随机下标
int x = rand() % row +1;
int y = rand() % col +1;
if (board[x][y] != '1') {
board[x][y] = '1';
count--;
}
}
}
//统计附近雷的个数
int CountMinu(char minu[Rows][Cols], int x, int y) {
return (minu[x - 1][y - 1] + minu[x - 1][y] + minu[x - 1][y + 1] + minu[x][y - 1] + minu[x][y + 1] + minu[x + 1][y - 1] + minu[x + 1][y] + minu[x + 1][y + 1] - 8 * '0');
}
//排查雷
void FindMine(char minu[Rows][Cols], char show[Rows][Cols], int row, int col) {
int x = 0;
int y = 0;
int win = 0;
while (win < Row * Col - Easycose) {
//DisplayBoard(minu, Row, Col);
printf("请输入你选的下标:");
scanf("%d %d", &x, &y);
if (x >=1 && x <= Row && y>=1 && y <= Col) {
if (minu[x][y] == '1') {
printf("此处是雷,你失败了\n");
DisplayBoard(minu, Row, Col);
break;
}
else {
//统计附近有多少雷
int c= CountMinu(minu, x, y);//统计选择的非雷坐标周围的雷的个数
show[x][y] = c + '0';
DisplayBoard(show, Row, Col);
win++;//不是雷的位置减少
}
}
else {
printf("选的下标超出界限,请重新输入:\n");
}
}
if (win == Row * Col - Easycose) {
printf("恭喜你排雷成功\n");
DisplayBoard(minu, Row, Col);
}
}
然后就是test.c文件实现整个代码的主体
#define _CRT_SECURE_NO_WARNINGS 1
#include"test.h"
void menu() {
printf("--------------------\n");
printf("----- 1.play -----\n");
printf("--------------------\n");
printf("----- 0.exit -----\n");
printf("--------------------\n");
}
void game() {
//用两个数组来表示两个棋盘.一个棋盘装雷的信息一个棋盘装排除雷的信息,用char类型,因为这边我们用'0'初始化第一个数组,'*'初始化第二个数组
char minu[Rows][Cols] = { 0 };
char show[Rows][Cols] = { 0 };
//第一步初始化棋盘
Initboard(minu, Rows, Cols, '0');
Initboard(show, Rows, Cols, '*');
//布置雷
//这里我用rand函数随机生成雷
SetMine(minu, Row, Col);
//打印棋盘
// DisplayBoard(minu, Row, Col);
DisplayBoard(show, Row, Col);
//排除雷
FindMine(minu, show, Row, Col);
}
int main() {
srand((unsigned int)time(NULL));//每次访问都让种子的值改变使其实现生成真正的随机数
int input = 0;
do {
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("已成功退出游戏");
break;
default:
printf("请重新选择:");
break;
}
} while (input);
}
总结:
设置两个11*11的数组
用minu数组进行雷和非雷位置的布置,show数组是用户用来进行排除雷的的,用户实际访问的是minu数组的下标,然后minu数组将结果通过show数组显示给用户看的
然后就是代码的实现还有就是完成这个游戏的结束标志这里我设置的是当win < Row * Col - Easycose时。