C语言简单扫雷游戏

学过二维数组后 即可 使用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;
}

有什么问题请指出,我会及时修改

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值