一 扫雷游戏的规则和实现思路
1.游戏概述 在一个9*9的空间里寻找地雷,找出所有地雷就算游戏结束。9*9的空间属于是基础版,但是实现的原理都是一样的,今天介绍的就是基础版。
2.游戏规则
揭开所有非地雷的方块而不触发地雷。每个方块可以是未揭开的、已揭开的或者标记为潜在地雷的状态。揭开一个方块可能会显示一个数字,表示周围八个方块中的地雷数量,或者揭开一个地雷,导致游戏失败。玩家通过逻辑推理和猜测来确定哪些方块是安全的,从而成功揭开所有非地雷的方块。在此代码实现中没有标记为雷的功能。
3.游戏实现思路
1.首先创建一个菜单选择游戏还是退出。
2.再创建棋盘进行初始化。
3.在游戏过程中需要显示棋盘打印一个9*9的棋盘。
4.随机设置10个雷分布在棋盘中。
5.当揭开一个方块时,如果是雷就游戏结束,反之就显示周围雷的信息,当揭开所有的方块时并没有揭开雷就获胜。
二 扫雷游戏的实现
使用的环境是vs2022。
一共三个文件
t.c // ⽂件中写游戏的测试逻辑g.c // ⽂件中写游戏中函数的实现等g.h // ⽂件中写游戏需要的数据类型和函数声明等
void test() {
srand((unsigned int)time(NULL));
int input = 0;
do {
muen();
printf("输入(0 1)\n");
scanf("%d", &input);switch (input) {
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,重新输入");
}
} while (input);
}
int main()
{
test();
return 0;
}
2.game函数
在棋盘的设计中我们将棋盘设置成11*11,并且创建了两个棋盘,一个显示给玩家的棋盘,一个存放雷的棋盘。1.先创建两个11*11的二维数组,一个是存放雷的数组,一个是展示出来的扫雷信息数组。
这样创建的好处是不会让一个二维数组上有太多的信息而且便于我们控制。
2.创建11*11的数组主要是方便我们处理处于角落的雷,我们可以在最外围不放置雷这样就可以实现在角落依然可以正确统计周围八个方块雷的数量。
3.有雷的方块我们使用字符’1‘来表示, ’0‘表示没雷,’*‘表示为揭开的方块。使用字符是因为为揭开的方块是使用’*‘表示,为了统一我们都是用字符表示
//初始化棋盘
void initboard(char board[ROWS][COLS], int rows, int cols, int set) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = set;
}
}
}
2.打印棋盘
选择棋盘的方块需要键盘操作,为了方便操作我们显示每一个方块的坐标。
//打印棋盘
void display(char board[ROWS][COLS], int row, int col) {
printf("----------------------------------\n");
for (int i = 0; i <= col; i++) {
printf("%d ", i);
}printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {printf("%c ", board[i][j]);
}
printf("\n");
}}
3.布置雷
布置雷时遵从随机原则此时运用rand()srand()time()
rand()函数
rand()
函数是编程中常用的工具,用于生成伪随机数。它存在于C语言的标准库中头文件为stdlib.h。通过初始化随机数生成器的种子,调用rand()
函数时,会返回一个介于0到RAND_MAX
之间的整数,这个范围是由编译器定义的最大随机数值。rand()
函数的结果是确定性的,即相同的种子将生成相同的数值序列。
srand()
srand()
函数在C语言中用于设置随机数生成器的种子,以影响后续调用rand()
函数生成的伪随机数序列。通常,种子是通过传递给srand()
函数的参数来确定的。只要传给srand的种子不断变化就能实现生成真正的随机数
time()
time()
函数是C语言等编程环境中常用的一个函数,用于获取当前系统时间。它返回一个time_t
类型的值,代表1970年1月1日 00:00:00起至今所经过的秒数。通过调用time()
并传递NULL
作为参数,可以方便地获取当前时间,将此函数结果作为srand的参数便可以实现随机数。
将这三个函数结合写成这样一条语句
srand((unsigned int)time(NULL));
//布置雷
void setmine(char mine[ROWS][COLS], int row, int col){
int x = 0;
int y = 0;
int count = 10;
while (count) {
x = rand() % row + 1;//限制x的范围
y = rand() % col + 1;//限制y的范围
if (mine[x][y] != '1') {//不允许在同一位置设置雷
mine[x][y] = '1';
count--;
}
}
}
4.找雷
1.首先输入坐标,再判断周围有几个雷
可以发现每一行的x坐标都是一样的,且y坐标都是+(-1),+(0),+(1)
所以可以使用一个循环解决
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
count += (mine[x+i][y+j]-'0');//因为’x'-‘0’=x 得出正确的雷个数
2.每输入一个坐标就打印更新的棋盘
返回值再加上字符0是因为show数组是字符数组
int ret = minestate(mine, X, Y);
show[X][Y] = ret + '0' ;
display(show, ROW, COL);
3.结束条件
在9*9的棋盘中需要揭开71个方块就获胜,所以设置一个while 循环条件是(row*col-10)
//雷的情况
int minestate(char mine[ROWS][COLS], int x, int y) {
int count = 0;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
count += (mine[x+i][y+j]-'0');
}
}
return count;
}
//排雷
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int X = 0;
int Y = 0;
int win = 0;
while (win < row * col - 10) {
printf("输入坐标(x y)\n");
scanf("%d %d", &X, &Y);
//display(show, ROW, COL);
if (X>= 1 && X <= row && Y >= 1 && Y <= col) //输入正确的x y坐标
{
if (mine[X][Y] == '1')
{
printf("踩雷\n");
display(mine, ROW, COL);//打印布置雷的信息
break;}
else
{
int ret = minestate(mine, X, Y);
show[X][Y] = ret + '0' ;
display(show, ROW, COL);
win++;
}
}
else
{
printf("输入错误重新输入\n");
}
if (win == row * col - 10) {
printf("扫雷成功\n");}
}
}
三.源文件
t.c
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include"g.h"void muen() {
printf("----------------------------\n");
printf("----------------------------\n");
printf("-------- 1 . play --------\n");
printf("-------- 0 . exit --------\n");
printf("----------------------------\n");
printf("----------------------------\n");
}
void game() {
//初始化棋盘
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
initboard(mine, ROWS, COLS, '0');
initboard(show, ROWS, COLS, '*');
//打印棋盘
//display(mine, ROW, COL);
display(show, ROW, COL);
//布置雷
setmine(mine,ROW, COL);
display(mine, ROW, COL);
//雷的情况找雷
findmine(mine, show, ROW, COL);
}
void test() {
srand((unsigned int)time(NULL));
int input = 0;
do {
muen();
printf("输入(0 1)\n");
scanf("%d", &input);switch (input) {
case 1:
printf("开始游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,重新输入");
}
} while (input);
}
int main()
{
test();
return 0;
}
g.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"g.h"
//初始化棋盘
void initboard(char board[ROWS][COLS], int rows, int cols, int set) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = set;
}
}
}
//打印棋盘
void display(char board[ROWS][COLS], int row, int col) {
printf("----------------------------------\n");
for (int i = 0; i <= col; i++) {
printf("%d ", i);
}printf("\n");
for (int i = 1; i <= row; i++) {
printf("%d ", i);
for (int j = 1; j <= col; j++) {printf("%c ", board[i][j]);
}
printf("\n");
}
}
//布置雷
void setmine(char mine[ROWS][COLS], int row, int col){
int x = 0;
int y = 0;
int count = 10;
while (count) {
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] != '1') {
mine[x][y] = '1';
count--;
}
}
}
//雷的情况
int minestate(char mine[ROWS][COLS], int x, int y) {
int count = 0;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
count += (mine[x+i][y+j]-'0');
}
}
return count;
}
//排雷
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int X = 0;
int Y = 0;
int win = 0;
while (win < row * col - 10) {
printf("输入坐标(x y)\n");
scanf("%d %d", &X, &Y);
//display(show, ROW, COL);
if (X>= 1 && X <= row && Y >= 1 && Y <= col)
{
if (mine[X][Y] == '1')
{
printf("踩雷\n");
display(mine, ROW, COL);
break;}
else
{
int ret = minestate(mine, X, Y);
show[X][Y] = ret + '0' ;
display(show, ROW, COL);
win++;
}
}
else
{
printf("输入错误重新输入\n");
}
if (win == row * col - 10) {
printf("扫雷成功\n");}
}
}
g.h
#pragma once
#pragma once
#include<stdio.h>
#include <stdlib.h>
#include<time.h>#define ROW 9
#define COL 9
#define EASYCOUNT 10;
#define ROWS ROW+2
#define COLS COL+2
void initboard(char board[ROWS][COLS], int rows, int cols, int set);
void display(char board[ROWS][COLS], int row, int col);
void setmine(char mine[ROWS][COLS], int row, int col);
void findmine(char mine[ROWS][COLS],char show[ROWS][COLS],int row, int col);
四.游戏界面
五.总结
该代码没有实现标记为雷的功能,还有点一个消失一大片的功能 。