扫雷
学过二维数组后 即可 使用C语言 写一个扫雷小游戏,快来看看吧
扫雷的准备工作
1.文件夹
创建 game.h 用来放函数声明 并包含.c文件要使用的头文件;
创建 game.c 用来实现逻辑代码;
创建 menu.c 用来打印菜单 并且调用函数;
2.> 在 game.h 里包含的三个头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h> // 用来设置srand
3.并且在各个.c文件 包含 game.h 头文件
#include “game.h”
扫雷的具体实现
1) 打印菜单
输出简单菜单即可,使用do while 循环来实现重复调用菜单函数
如果对 do while 不熟的小伙伴 可自行查阅资料
#inlcude "game.h" // 这里导入了 下面代码就不重复写了
void menu()//创建menu函数
{
printf("****************\n");
printf("**** 1.play ****\n");
printf("**** 0.exit ****\n");
printf("****************\n");
}
int main()
{
int input=0;
//这里要写一个 srand 后面用来 随机埋雷
srand((int)time(NULL));
//
do
{
menu();//调用menu函数 打印菜单
}
while();//此时是空的 下一步会写
return 0;
}
输出效果:
2) 键入选择
使用switch来实现键入选择
如果对 switch 不熟的小伙伴 可自行查阅资料
int main()
{
int input=0;
do
{
menu();//调用menu函数 打印菜单
scanf("%d",&input);//
switch(input)//直接将input值作为swich的表达式
{
case 1 :
printf("调用游戏\n");
//game();函数调用下面一步会实现
break;
case 0:
printf("退出\n");
goto end;//直接退到return 的位置
default:
printf("键入错误\n");
}
}
while(input);//while同理 直接使用input的值来当表达式
end:
return 0;
}
输出效果:
3) 编写game函数
用户== 输入1== 的时候调用 game 函数
void game()//创建game函数
{
//这里将会放 调用所有功能的函数 此处只示范
}
int main()
{
int input=0;
//这里要写一个 srand 后面用来 随机埋雷
srand((int)time(NULL));
do
{
menu();//调用menu函数 打印菜单
scanf("%d",&input);//
switch(input)//直接将input值作为swich的表达式
{
case 1 :
//printf("调用游戏\n");
game();//调用游戏函数
break;
....;//以下为了不占用地方 省略
return 0;
}
3.1 编写 初始化
!!! 要先在 game.h里的写几个 宏 定义 方便使用
如不了解 宏 可自行搜索
game.h头文件
//这是 game.h 头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//需要定义的几个宏 下面
// ⬇
//这里定义9行9列 因为是9*9的扫雷
#define ROW 9
#define COL 9
// 这里再准备多2行2列 存雷会用到
#define ROWS ROW+2
#define COLS COL+2
//雷的数量
#define EASY_MODE 10
以下为 初始化功能 实现
这里是menu.c的初始化函数调用
玩家和策划界面 初始化调用的 初始化 函数是一致的 但是传的参数些许不一样
// menu.c文件
void game()
{
// 先创建 俩二维数组 创建char类型是因为它是细狗 够细
// 使用 ROWS COLS 防止越界 写好就别动它了
char mine[ROWS][COLS]={0};//后台显示存雷界面 简单理解为 策划
char show[ROWS][COLS] = {0};//隐藏存雷界面 简单理解为 玩家
// 防止越界的原因是因为 扫雷点某块区域的时候 周围也会显现
//玩家界面 初始化 你想用什么字符初始化都可以
Intboard(show,ROWS,COLS,'*');//这里使用了*
//策划界面 初始化 不要用和玩家模式一样的字符就行
Intboard(mine,ROWS,COLS,'0');//这里使用了0 因为一会儿埋雷是 1;
}
此处是game.h初始化函数声明
初始化参数分别是 模式, 行,列(11 * 11) 填充符号
//声明初始化 用谁传谁
void Intboard(char board[ROWS][COLS],int row,int col,char set);
以下是game.c实现函数初始化逻辑
#inlcude "game.h" //同样 只写一遍
//初始化函数实现
void Intboard(char board[ROWS][COLS],int row,int col,char set)
{
for(int i=0;i<row,i++)//行
{
for(int j=0;j<col;j++)//列
{
board[i][j]=set;//填充填充符号
}
}
}
以上只是为了演示三个文件 接下来会将三个写在同一个代码块
注意 以下使用 分隔线 来划分文件之间的区别
注意 以下使用 分隔线 来划分文件之间的区别
注意 以下使用 分隔线 来划分文件之间的区别
3.2 编写 打印棋盘
这里可以检测上一步错没错, 打印雷盘
//menu.c 调用
void game()
{
//之前省略
//打印游戏棋盘 //打印策划的主要是为了埋雷后看雷
DisplayBoard(mine, ROW, COL);//注意 打印9*9的
}
-----------------------------分隔-------------------------------------
//game.h 声明打印棋盘
//参数: 模式 行 列(注意这里是行列是 9*9)
void DisplayBoard(char board[ROWS][COLS],int row,int col);
-----------------------------分隔-------------------------------------
//game.c 打印棋盘实现
//打印棋盘
void DisplayBoard(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");
//为了不显示最外面一圈 防溢出的 要把 i=1 j也同理
for (i=1;i<=row; i++)
{
printf("%d ", i); //打印行号
for (j=1;j<= col;j++)
{
printf("%c ",board[i][j]);//打印初始化后的棋盘
}
printf("\n");
}
printf("------------------------扫雷游戏----------------------------\n");
}
输出效果:
这里是策划显示的界面
3.3 编写 埋雷
注意埋到 mine 这个数组,要埋 9 * 9 的
//menu.c 调用
void game()
{
//之前省略
//埋雷
setMine(mine, ROW, COL);//注意 这里依旧是9*9
}
-----------------------------分隔-------------------------------------
//game.h 声明埋雷
//参数: 模式 行 列 行列是(9*9)
void setMine(char board[ROWS][COLS], int row, int col);
-----------------------------分隔-------------------------------------
//game.c 实现埋雷
//埋雷
void setMine(char board[ROWS][COLS], int row, int col)
{
//将雷修改为标识符常量 方便后面修改 宏定义那最后写了
int count = EASY_MODE;
while (count)
{
//设置随机埋雷 //先前在 1) 打印菜单 位置注释有写到了
//限制rand 在 row 和col范围 随机生成数字
int x = rand() % row +1;
int y = rand() % col +1;
if (board[x][y] == '0')//随机位置 策划界面 当前字符 如果等于0
{
board[x][y] = '1';//埋雷
count--;//雷数减1
}
}
}
输出效果:
注意 埋完雷 要打印 mine 棋盘看看
是为了检测有没有出错
mine 模式下的雷盘:
这里也展示一下 show 雷盘 如下:
3.4 编写 排雷
注意 在埋完雷后 要打印 show 为模式的棋盘,这样才看不到雷在哪里
//menu.c 调用
void game()
{
//之前省略
//注意这里要输出一次 show模式下的 棋盘
DisplayBoard(show, ROW, COL);
//排查
FindMine(mine,show,ROW,COL);//两个模式都传 并且行列 9*9
}
-----------------------------分隔-------------------------------------
//game.h 声明排雷
//参数: 策划模式 玩家模式 行 列 9*9
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
-----------------------------分隔-------------------------------------
//game.c 实现排雷
//排雷
//利用字符1-字符0等于1 0-0等于0的算法 让周围8个值相加 在减去 8*字符0得出的数字就是雷的数字
int IsMineCount(char board[ROWS][COLS],int x,int y)
{
//计算周围8个
return (board[x - 1][y ] +
board[x - 1][y - 1] +
board[x - 1][y + 1] +
board[x][y-1] +
board[x][y+1] +
board[x+1][y-1]+
board[x+1][y] +
board[x+1][y+1]
- 8 * '0');
}
//排雷
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- EASY_MODE)
{
printf("请输入排查坐标->");
scanf("%d %d", &x,&y);
//判断是否合法输入 注意 因为用户不是程序员 所以从1开始
if (x >= 1 && x <= row && y <= col && y >= 1)
{ //判断是否为*
if (show[x][y] == '*')
{ //判断是否为雷
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);//被炸死后 显示雷的位置
break;
}
else {
//距离胜利又近一步了
win++;
//排查周围是否为雷
int count = IsMineCount(mine, x, y);
show[x][y] = count + '0';//会将count转变为字符
DisplayBoard(show, ROW, COL);
}
}
else {
printf("此坐标已被占用\n");
DisplayBoard(show, ROW, COL);
}
}
else {
printf("请输入合法坐标\n");
DisplayBoard(show, ROW, COL);
}
}
if (win == row * col - EASY_MODE) {//胜利条件等于 行*列-雷数
printf("恭喜你 你成功了\n");
DisplayBoard(mine, ROW, COL);
}
}
输出结果:
1.提示周围雷数
2.被炸死
3.通关
到此就完成了一个简单的扫雷游戏
完整代码
1) game.h 头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//显示9 需要多2行2列 防止越界
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//设置雷
#define EASY_MODE 60
//声明初始化 用谁传谁
void Intboard(char board[ROWS][COLS],int row,int col,char set);
//声明打印棋盘 只是将9 9作为形参 数组还是要11
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//埋雷
void setMine(char board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
2) game.c 文件
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//初始化
void Intboard(char board[ROWS][COLS], int row, int col,char set)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("------------------------扫雷游戏----------------------------\n");
//要打印列号
int j = 0;
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
//为了跳过最外防溢出的 要把i=1 j同理
for (i = 1; i <= row; i++)
{
//打印行号
printf("%d ", i);
int j = 0;
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 = EASY_MODE;
int i = 0;
while (count)
{
//设置随机埋雷
int x = rand() % row +1;
int y = rand() % col +1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//利用字符1-字符0等于1 0-0等于0的算法 让周围8个值相加 在减去 8*字符0得出的数字就是雷的数字
int IsMineCount(char board[ROWS][COLS],int x,int y)
{
//计算周围8个
return (board[x - 1][y ] +
board[x - 1][y - 1] +
board[x - 1][y + 1] +
board[x][y-1] +
board[x][y+1] +
board[x+1][y-1]+
board[x+1][y] +
board[x+1][y+1]
- 8 * '0');
}
//排雷
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- EASY_MODE)
{
printf("请输入排查坐标->");
scanf("%d %d", &x,&y);
//判断是否合法输入
if (x >= 1 && x <= row && y <= col && y >= 1)
{ //判断是否为*
if (show[x][y] == '*')
{ //判断是否为雷
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
else {
//雷数自增
win++;
//排查周围是否为雷
int count = IsMineCount(mine, x, y);
show[x][y] = count + '0';//会将count转变为字符
DisplayBoard(show, ROW, COL);
}
}
else {
printf("此坐标已被占用\n");
DisplayBoard(show, ROW, COL);
}
}
else {
printf("请输入合法坐标\n");
DisplayBoard(show, ROW, COL);
}
}
if (win == row * col - EASY_MODE) {
printf("恭喜你 你成功了\n");
DisplayBoard(mine, ROW, COL);
}
}
3) menu.c 文件
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void game()
{
//后台存雷界面
char mine[ROWS][COLS] = {0};
//用户扫雷
char show[ROWS][COLS] = {0};
//初始化 使用什么填充 就传什么
//前端由*号填充
Intboard(show, ROWS, COLS,'*');
//后端由0填充
Intboard(mine, ROWS, COLS,'0');
//打印游戏棋盘
//DisplayBoard(mine, ROW, COL);
//埋雷
setMine(mine, ROW, COL);
//打印游戏棋盘
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//排查
FindMine(mine, show, ROW, COL);
}
void menu()
{
printf("++++++++++++++++++++++++++++++++\n");
printf("++++++++++++ 1.扫雷 ++++++++++++\n");
printf("++++++++++++ 0.exit ++++++++++++\n");
printf("++++++++++++++++++++++++++++++++\n");
}
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("退出\n");
goto end;
default:
printf("输入错误\n");
}
} while (input);
end :
return 0;
}
有什么问题请指出,我会及时修改