当前位置:网站首页>[详解C语言]一文带你玩转C语言小游戏---扫雷
[详解C语言]一文带你玩转C语言小游戏---扫雷
2022-08-02 03:16:00 【Zoroxs】
作者简介:大家好我是zoroxs
个人主页:c/c++学习之路
如果觉得博主的文章还不错的话,请三连支持一下博主哦
扫雷小游戏
C语言能写很多的小游戏,可以很好地加深我们对学过知识的印象,更可以增加我们对学习的兴趣。
上次带大家写了一个三子棋,今天带大家再来写一个人人皆知的扫雷,这游戏,反正从小到大我是一局都没赢过,今天我们就用C语言来实现小时候特别爱玩的游戏

1.游戏整体思路
- 打印雷盘
- 往雷盘中放置雷
- 接受用户输入坐标,扫雷
- _判断是否踩到雷,踩到雷---->恭喜他被炸死, _
- 没踩雷,在对应位置显示周围有几颗雷
- 直到踩雷或者所有非雷位置都被走过,游戏结束
2.扫雷双雷盘设计
很关键的地方在于雷盘的设计,我们假设要99的雷盘,那我们要存储雷还有用户是否排过,周围又有几个雷,用一个99的二维数组可以实现。
给大家提供一个崭新的思路,
我们这里使用两个同样的二维数组来存储:
一个存储雷的位置,有雷是1,无雷是0,
_另一个当成展示雷盘,没扫过就是*,扫过就显示周围有几颗雷的数字_**
像这种靠墙壁的,计算它周围有几颗雷比较复杂,我们这里有一个妙手。
_我们如果要用9*9的雷盘,就弄成11*11的数组,我们展示的时候只展示9*9就可以了,这样每一个墙壁周围都有一层格子,极大方便了我们的计算。_
我们需要两个函数来帮我们实现一下棋盘,大家看之前的三子棋就知道,初始化,打印,必备
我们来看一下声明,这里需要注意的是,我们要初始化两个雷盘,初始化的字符不一样,所以参数需要把初始化的字符传进去
//初始化雷盘
void init_board(char board[ROWS][COLS], int row, int col, char ch);
//打印雷盘
void display_board(char board[ROWS][COLS], int row, int col);
我们来看一下代码实现
//初始化雷盘
void init_board(char board[ROWS][COLS], int row, int col, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ch;
}
}
}
void display_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//打印行号
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
来看一下展示出来的雷盘
3.往棋盘中放雷
雷盘已经好了,我们来往雷盘中放雷,我们可以在外边宏定义好需要放入的雷的数量
然后我们来定义一个放置雷的函数:
void set_board(char board[ROWS][COLS], int row, int col ,int mine_count);
void set_board(char board[ROWS][COLS], int row, int col, int mine_count)
{
while (mine_count > 0)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if ('0' == board[x][y])
{
board[x][y] = '1';
mine_count--;
}
}
}
这里用到了随机数,如果对随机数的使用没啥概念的朋友,可以去看一下前边的三子棋小游戏,对随机数的生成做了简单介绍 三子棋,还不明白的,可以私信我交流
4.扫雷
棋盘中雷已经放置成功,我们就可以开始扫雷了,按照用户输入的坐标进行判断,如果是雷就结束游戏,如果不是雷就展示坐标周围有几颗雷,继续扫雷
我们实现一个扫雷函数
void clean_mine(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
判断坐标周围有几颗雷的函数
int get_mine_count(char board[ROWS][COLS], int x, int y)
我们来实现一下代码,坐标合法并且此位置没有被扫过,我们才判断
//获取坐标周围有几颗雷
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return (board[x - 1][y - 1] + board[x - 1][y] + 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 clean_mine(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
int count = 0;
while (count < row * col - MINE_COUNT)
{
printf("请输入坐标:>\n");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
//判断坐标是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断是否被扫过
if (show_board[x][y] == '*')
{
if ('1' == mine_board[x][y])
{
printf("恭喜您,被雷炸死了\n");
break;
}
else if ('0' == mine_board[x][y])
{
int count = get_mine_count(mine_board, row, col);
show_board[x][y] = count + '0';
display_board(show_board, row, col);
count++;
}
}
}
}
if (count == row * col - MINE_COUNT)
{
printf("恭喜您,成功通关\n");
}
}
这里有一个注意事项就是返回周围有几颗雷时,因为我们用的是字符数组,周围有8个位置,所以需要减去 8乘以字符0
5.判断成败
雷盘的总位置–雷的个数就是无雷区,如果用户走过所有无雷区,则就赢得胜利
6.测试函数编写
以上基本就是我们的所有游戏代码了,差的是使用的头文件,以及函数声明和宏定义,
我们用测试函数来测试一下我们的游戏是否可以正常运行
直接给大家放代码了,有了三子棋的经验,基本很类似
//打印菜单
void menu()
{
printf("**********************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("**********************\n");
}
void game()
{
//定义两个雷盘,一个展示,一个放雷
char mine_board[ROWS][COLS];
char show_board[ROWS][COLS];
//初始化雷盘
init_board(mine_board, ROWS, COLS, '0');
init_board(show_board, ROWS, COLS, '*');
//打印雷盘
display_board(show_board, ROW, COL);
//放雷
set_board(mine_board, ROW, COL, MINE_COUNT);
//排雷
clean_mine(mine_board, show_board, ROW, COL);
}
int main(void)
{
int input = 0;
srand(time(NULL));
do
{
menu();
printf("请输入:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
7.代码拼接
代码总共分成了3个文件
- game.h-----引头文件,定义宏,函数声明
- game.c----游戏核心代码实现
- test.c ----测试函数核心代码实现
把这三个文件一起编译就可以跑起来游戏了,给大家把三个代码都放出来
7.1game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 11
#define COLS 11
#define COL 9
#define ROW 9
//雷数
#define MINE_COUNT 10
//初始化雷盘
void init_board(char board[ROWS][COLS], int row, int col, char ch);
//打印雷盘
void display_board(char board[ROWS][COLS], int row, int col);
//放雷
void set_board(char board[ROWS][COLS], int row, int col ,int mine_count);
//扫雷
void clean_mine(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col);
7.2game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化雷盘
void init_board(char board[ROWS][COLS], int row, int col, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ch;
}
}
}
void display_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//打印行号
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void set_board(char board[ROWS][COLS], int row, int col, int mine_count)
{
while (mine_count > 0)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if ('0' == board[x][y])
{
board[x][y] = '1';
mine_count--;
}
}
}
//获取坐标周围有几颗雷
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return (board[x - 1][y - 1] + board[x - 1][y] + 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 clean_mine(char mine_board[ROWS][COLS], char show_board[ROWS][COLS], int row, int col)
{
int count = 0;
while (count < row * col - MINE_COUNT)
{
printf("请输入坐标:>\n");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
//判断坐标是否合法
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//判断是否被扫过
if (show_board[x][y] == '*')
{
if ('1' == mine_board[x][y])
{
printf("恭喜您,被雷炸死了\n");
break;
}
else if ('0' == mine_board[x][y])
{
int count = get_mine_count(mine_board, row, col);
show_board[x][y] = count + '0';
display_board(show_board, row, col);
count++;
}
}
}
}
if (count == row * col - MINE_COUNT)
{
printf("恭喜您,成功通关\n");
}
}
7.3test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//打印菜单
void menu()
{
printf("**********************\n");
printf("****** 1.play ******\n");
printf("****** 0.exit ******\n");
printf("**********************\n");
}
void game()
{
//定义两个雷盘,一个展示,一个放雷
char mine_board[ROWS][COLS];
char show_board[ROWS][COLS];
//初始化雷盘
init_board(mine_board, ROWS, COLS, '0');
init_board(show_board, ROWS, COLS, '*');
//打印雷盘
display_board(show_board, ROW, COL);
//放雷
set_board(mine_board, ROW, COL, MINE_COUNT);
//排雷
clean_mine(mine_board, show_board, ROW, COL);
}
int main(void)
{
int input = 0;
srand(time(NULL));
do
{
menu();
printf("请输入:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入有误,请重新输入\n");
break;
}
} while (input);
return 0;
}
这就是三个文件的所有代码,可以实现最基本的扫雷,虽然没有平时玩的只能,但毕竟自己写,还是很有成就感的。
8.总结
不管是三子棋还是扫雷,都离不开我们之前学到过的知识,函数 、数组、分支、循环…把很多都串联起来使用,让大家的逻辑思维得到很好地锻炼
大家一定要多多练习,后边比如贪吃蛇、俄罗斯方块等等,有需要的大家可以评论区留言,我拿命更新
这里有一个缺陷,可以实现,但是我没有写, 就是使用递归,让扫的坐标,周围不是雷的全部自动散开,大家可以尝试尝试,有问题可以找我。
如果觉得博主的文章还不错的话,请三连支持一下博主哦
边栏推荐
- DAY-1 | 求两个正整数的最大公约数与最小公倍数之和——辗转相除法
- Good Key, Bad Key (thinking, temporary exchange, classic method)
- JDBC--Druid数据库连接池以及Template基本用法
- PHP WebShell Free Kill
- 暴力破解全攻略
- JVM学习----垃圾回收--G1
- Day34 LeetCode
- MySQL8 -- use msi (graphical user interface) under Windows installation method
- 数据库操作作业
- EF Core:基于关系的复杂查询 区分IEnumerable和IQueryable
猜你喜欢
ASP WebShell backdoor script and anti-kill
JDBC的入门使用
Reasons and solutions for Invalid bound statement (not found)
Go语学习笔记 - gorm使用 - 原生sql、命名参数、Rows、ToSQL Web框架Gin(九)
(Reposted) The relationship between hashcode and equals
小程序(开发必备常识)1
PyTorch(六)——PyTorch可视化
知识体系树
OD-Model [4]: SSD
MySQL8 - use under Windows package installation method
随机推荐
分布式事务解决方案模型
黑马案例--实现 clock 时钟的web服务器
Webshell upload method
一种基于行为空间的回声状态网络参数优化方法
MySQL中的时区设置
Istio微服务治理网格的全方面可视化监控(微服务架构展示、资源监控、流量监控、链路监控)
MySql中的like和in走不走索引
mysql8.0.28下载和安装详细教程,适配win11
什么是轮式里程计
I will give you a chance to interview in a big factory. Can you interview?Come in and see!
2022.7.30 js notes Operators and flow controllers, loops
STL entry basics map and set containers
Kubernetes 基本概念
CV-Model【4】:MobileNet v3
AntV X6制作画板工具(图形,线段,图片上传)
【LeetCode】1374. Generate a string with an odd number of each character
Go语学习笔记 - gorm使用 - gorm处理错误 Web框架Gin(十)
JSP Webshell free kill
第十一天&shell脚本
ROS2自学笔记:launch文件完整编写流程