扫雷游戏(C语言详解)
- 放在最前面的
- 1、前言(扫雷游戏的简介)
- 2、扫雷游戏的规则(简易版)
- 3、代码实现
- (3.1)提醒一下:
- ( i ) 提醒1:
- ( ii ) 提醒2:
- (3.2) 上代码
- **game.h** 头文件
- **game.c** 头文件
- **test.c** 头文件
- 4、结果展示
- (4.1)输入的坐标是非法的(即不在坐标的范围)
- (4.2)输入的坐标是雷,则游戏提前结束
- (4.3)输入的坐标 不是雷,打印四周(八个坐标)有几个雷
- (4.4)成功避免所有布置的雷,游戏完美结束
- 5、END
放在最前面的
🎈 🎈 我的CSDN主页:OTWOL的主页,欢迎!!!👋🏼👋🏼
🎉🎉我的C语言初阶合集:C语言初阶合集,希望能帮到你!!!😍 😍
👋🏼🎉🎊创作不易,欢迎大家留言、点赞加收藏!!! 🥳😁😍
1、前言(扫雷游戏的简介)
《扫雷》中玩家的目标是在最短时间内识别出所有非雷区的格子,同时避免触碰到地雷。
游戏区域由多个隐藏格子组成,每个格子可能隐藏着地雷或数字,数字表示周围八个格子中地雷的数量。
玩家通过点击格子揭示内容,使用逻辑推理逐步排除雷区。
游戏考验玩家的观察力和推理能力,任何一次误点地雷都会导致游戏失败。
2、扫雷游戏的规则(简易版)
1. 第一次点击不会是雷。
2. 格子里的数字表示它周围有几个雷。
3. 游戏目标是找出所有雷,如果 “触雷” 则输。
3、代码实现
(3.1)提醒一下:
( i ) 提醒1:
我在代码注释中对每一行代码进行了 详细的 解释,保证 0基础小白能看得懂!
( ii ) 提醒2:
我写了三个文件,分别是
game.h、 game.c、test.c
。
game.h
里面存放着与game
相关函数的声明 的 头文件。
game.c
里面存放着与扫雷游戏有关的函数的实现即定义
如:初始化函数 Init()
函数、布置雷 set_mine
函数等 的 源文件。
test.c
里面存放着 主函数(main
)和 测试运行整个扫雷游戏的代码块的头文件。
(3.2) 上代码
game.h 头文件
//标准输出输出调用的头文件
#include<stdio.h>
// rand 函数 和 srand 函数调用的头文件
#include<stdlib.h>
// time()时间戳函数调用的头文件
#include<time.h>
//定义一个宏定义常量 ROW 数值是 9
#define ROW 9
//定义一个宏定义常量 COL 数值是 9
#define COL 9
//定义一个宏定义常量 ROWS 数值是 9+2 = 11
#define ROWS ROW+2
//定义一个宏定义常量 COLS 数值是 9+2 = 11
#define COLS COL+2
定义一个宏定义常量 NUM(用作存储 放置雷的个数) 数值是 76
#define NUM 76
//初始化函数 Init() 的声明
void Init(char board[ROWS][COLS], int rows, int cols, char set);
//打印函数 Print() 的声明
void Print(char board[ROWS][COLS], int row, int col);
//布置雷 set_mine() 的声明
void set_mine(char mine[ROWS][COLS], int row, int col);
//排雷 clear_mine() 的声明
void clear_mine(char mine[ROWS][COLS], char show[ROWS][COLS] , int row, int col);
game.c 头文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"//引用 game.h 头文件
//初始化扫雷棋盘函数 Init() 的调用
void Init(char board[ROWS][COLS], int rows, int cols, char set)
{
// 定义一个整型变量 i,
// 并且初始化为 0
int i = 0;
//外层 for 循环
for (i = 0; i < rows; i++)
{
// 定义一个整型变量 j,
// 并且初始化为 0
int j = 0;
//内层 for 循环
for (j = 0; j < cols; j++)
{
//将字符set的值,赋值给 board[i][j]
board[i][j] = set;
}
}
}
//打印函数 Print() 的定义
void Print(char board[ROWS][COLS], int row, int col)
{
// 定义一个整型变量 i,
// 并且初始化为 0
int i = 0;
//输出打印 提示信息
printf("\n------扫雷游戏------\n");
// 定义一个整型变量 j,
// 并且初始化为 0
int j = 0;
//for 循环
//用于 输出列数
for (j = 0; j <= col; j++)
{
//打印列数
printf("%d列\t", j);
}
//换行
printf("\n");
//外层 for 循环
for (i = 1; i <= row; i++)
{
//打印行数
printf("%d行\t", i);
//内层 for 循环
for (j = 1; j <= col; j++)
{
//输出打印 board[i][j] 对应的内容
// \t 是转义字符,含义是 制表符
//并按照%c\t的格式 进行打印
printf("%c\t", board[i][j]);
}
//换行
printf("\n");
}
//输出打印 提示信息
printf("------扫雷游戏------\n\n");
}
//布置雷 set_mine() 的定义
void set_mine(char mine[ROWS][COLS], int row, int col)
{
//定义一个整型变量 n
//并将 放置雷的个数 NUM 赋值给 n
int n = NUM;
// while 循环
while (n)
{
//定义两个整型变量 x y,
//并将 rand() --随机数字的生成 函数 % row
//生成的结果 分别 赋值给 x y
int x = rand() % row + 1;
int y = rand() % col + 1;
//如果 mine[x][y] 的 内容 等于 ‘0’(字符0), 则执行下面的语句块
if (mine[x][y] == '0')
{
//将 ‘1’(字符1) 赋值给 board[x][y]
mine[x][y] = '1';
//雷的个数 - 1(减1)
n--;
}
}
}
//排雷 clear_mine() 的定义
void clear_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
//输出打印 提示信息
printf("一共有%d 个雷\n", NUM);
//定义两个整型变量 x y,
//并进行初始化,赋值为 0
int x = 0;
int y = 0;
//定义两个整型变量 count,
//用作计算第几次排雷次数 即避开了多少雷
int count = 0;
// while 循环,
// 循环判断的条件是 count < NUM
while (count < NUM)
{
//输出打印 提示信息
printf("\n欢迎您,请输入要排查的坐标\n");
printf("提示1:(横、纵坐标中间用空格隔开)\n");
printf("提示2:(横、纵坐标都是[1~9]):>");
//输入 两个整型数字
int n2 = scanf("%d %d", &x, &y);
//if 条件判断语句
// 如果函数 x > 0 && x <= row && y > 0 && y <= col,执行下面的语句块
// 即 if 条件判断条件是 输入的坐标是否有效
if (x > 0 && x <= row && y > 0 && y <= col)
{
// if 条件判断语句
// 如果函数 board[x][y]的 内容 不等于 ‘1’(字符1),执行下面的语句块
if (mine[x][y] != '1')
{
// if 条件判断语句
// 如果函数 board[x][y]的 内容 等于 ‘*’(字符*),执行下面的语句块
if (show[x][y] == '*')
{
//输出打印 提示信息
printf("\n第%d次 排查!\n", count + 1);
// 将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] 即统计求和 show[x][y] 四周 七个坐标的雷数
// 并将结果以字符的形式赋值给 show[x][y]
// (因为 mine[x][y]、show[x][y] 都是字符数组,元素必须是字符的形式!!!)
show[x][y] = (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]) - 7 * '0';
//输入的坐标有效,
// 并且不是雷,
// 还有没有被排查过
// (三个条件同时满足!!!),
// 则用作计算第几次排雷次数 即避开了多少雷的变量 count自增 1
count++;
//打印函数 Print() 的调用
Print(show, ROW, COL);
//如果用作计算第几次排雷次数 即避开了多少雷的变量 count
//等于 ROW * COL -NUM 即(没有放置雷的个数),执行下面的语句块
if (count == ( ROW * COL -NUM) )
{
//输出打印 提示信息
printf("恭喜您,你成功避开 %d个雷!\n", NUM);
printf("棒棒哒!游戏结束!\n");
//跳出循环
break;
}
}
//
else
{
//输出打印 提示信息
printf("\n该坐标已经排查过了,请重新输入!\n");
}
}
// mine[x][y] == '1',即 mine[x][y] 里面的内容是雷。
else
{
//输出打印提示信息
printf("\n非常遗憾!你被炸死了!游戏结束!\n");
//输出打印 提示信息
printf("\n雷区布置展示:>\n");
//打印函数 Print() 的调用
Print(mine, ROW, COL);
//跳出循环
break;
}
}
//
else
{
//输出打印 提示信息
printf("坐标非法,请输入有效坐标\n");
}
}
}
test.c 头文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"//引用 game.h 头文件
//定义菜单 menu() 函数
void menu()
{
//输出打印 提示信息
printf("\n********************\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("********************\n\n");
}
//
void game()
{
// 定义一个二维的字符型数组,
// 数组名字是 mine,
// 有 ROWS 行、COLS 列
char mine[ROWS][COLS];
// 定义一个二维的字符型数组,
// 数组名字是 show,
// 有 ROWS 行、COLS 列
char show[ROWS][COLS];
//初始化函数 Init() 的调用
Init(mine, ROWS, COLS,'0');
//初始化函数 Init() 的调用
Init(show, ROWS, COLS,'*');
//输出打印 提示信息
printf("\n扫雷游戏页面:>\n");
//打印函数 Print() 的调用
Print(show, ROW, COL);
//布置雷 set_mine() 的调用
set_mine(mine, ROW, COL);
//输出打印 提示信息
printf("\n雷区布置展示:>\n");
//打印函数 Print() 的调用
Print(mine, ROW, COL);
//排雷 clear_mine() 的调用
clear_mine(mine, show, ROW, COL);
}
//定义测试函数 test()
void test()
{
// rand 函数(随机数的生成函数)使用前,
// 必须要提前引用 srand 函数,
// time() 函数是时间戳函数
srand((unsigned int)time(NULL));
//定义一个整型变量 input
//并且初始化为0
int input = 0;
//使用 do while 循环语句
do
{
//调用 菜单函数
menu();
//打印提示信息
printf("请选择:>");
// n1 来接受 scanf 函数的返回值,
// 输入一个整数
int n1 = scanf("%d", &input);
//使用 switch 分支语句
switch (input)
{
// 如果 input = 1
// 执行 case 1:后面的语句
case 1:
//调用 game()函数
game();
//break 语句用来跳出 switch 分支语句
break;
case 0:
//打印提示信息
printf("退出游戏\n");
//break 语句用来跳出 switch 分支语句
break;
default:
// 如果 input 不等于 0 也不等于 1
// 执行 default:后面的语句
printf("选择错误,请重新选择\n");
//break 语句用来跳出 switch 分支语句
break;
}
} while (input);//跳出 do-while 循环的条件是 input 等于 0
}
//主函数
int main()
{
//调用测试函数 test()
test();
return 0;
}
4、结果展示
提示:我写的是9*9的扫雷简易版游戏
(4.1)输入的坐标是非法的(即不在坐标的范围)
(4.2)输入的坐标是雷,则游戏提前结束
(4.3)输入的坐标 不是雷,打印四周(八个坐标)有几个雷
(4.4)成功避免所有布置的雷,游戏完美结束
5、END
每天都在学习的路上!
On The Way Of Learning