当前位置:网站首页>C语言小游戏——扫雷
C语言小游戏——扫雷
2022-08-01 09:25:00 【it_NunU】
前言
“扫雷”相信小伙伴们都玩过吧,上机课偷偷玩机房的电脑,只有扫雷,纸牌等小游戏,打磨打磨上课的时间哈哈。
经过自己一段时间的学习后,接下来细讲一下我做的扫雷小程序吧!(附加区域展开效果哦~)
一、效果图(展示)
先展示一下程序运行效果图吧
打印菜单+初始化扫雷界面
接着扫雷游戏进行,输入排查坐标(如果该坐标附近区域无雷(全为0)即可展开附近一片)
接着继续输入坐标,如果该坐标是雷,则游戏结束,可选择继续游戏也可选择退出,继续游戏前可以按 2 实现清屏,以防上一局的游戏干扰视线
游戏结束后会展开所有坐标,查看雷或非雷的区域
二、整体结构及功能介绍
要想扫雷,首先得有一块足够埋雷的空间,扫雷时要想想该如何实现如果该格子周围八个格子都没有雷,该区域就会被清空;踩到雷,即游戏结束。
所以我们理清思路开始逐一实现
1、创建雷盘
2、初始化雷盘
3、打印雷盘
4、随机布置你定义的雷的数量
5、展开式排雷
程序文件还是与三子棋同样思路test.c;game.c;game.h同三子棋
需要思考的问题
对这上一个小游戏三子棋的思想,想完成一个大的平台,我们可以利用二维数组来存放雷的信息。
首先要电脑实现随机分布各个雷的位置、位置信息只有开发者能看到和游戏结束时能看到
三、功能解析及代码实现
创建雷盘、布置雷盘、初始化、打印
最上面和最左边的数字代表的是列与行坐标,'0'代表没有雷,'1'则为雷,'*'表示的是该点坐标还未进行扫雷;
如果9X9 的平台,当输入坐标为 3,1 时,发现左边有三个位置是超出我们定义的 9X9 数组范围的,那么如果解决这个问题呢?
我们可以让9X9的范围行列都向外扩展一圈,此时9X9就变为 11X11的范围了,接着可以把外围的格子初始化为0然后不显示外围的数据,这样就可以避免后续排查雷的判断了。
void init_board(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
int j = 0;
for ( i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void display_board(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");
for ( i = 1; i <= row; i++)
{
printf("%d ", i);
for ( j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("----------扫雷游戏----------\n");
}
void set_mine(char mine[ROWS][COLS], int row, int col)
{
// 布置10个雷
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
接着就是扫雷了,这里我没有添加第一次排雷不被炸死功能,此功能可以先用if判断第一次输入的坐标是否为雷,如果是雷则可以在雷盘上重新找一个非雷的位置将开始的雷移到其他地方,小伙伴可以自行实现哦~
扫雷功能实现:玩家输入一个坐标,如果是雷,则游戏结束,如果不是雷,并且该附近区域无雷,则展开一篇,游戏继续,直到下一次排到雷或者所有非雷位置被排查完,则游戏结束
// 统计
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (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] - 8 * '0');
}
// 递归实现展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数
if (count_number == 0)
{
show[x][y] = ' ';
if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*')
{
Spread(mine, show, x - 1, y - 1);
}
if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*')
{
Spread(mine, show, x - 1, y);
}
if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*')
{
Spread(mine, show, x - 1, y + 1);
}
if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*')
{
Spread(mine, show, x, y - 1);
}
if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*')
{
Spread(mine, show, x, y + 1);
}
if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*')
{
Spread(mine, show, x + 1, y - 1);
}
if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*')
{
Spread(mine, show, x + 1, y);
}
if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*')
{
Spread(mine, show, x + 1, y + 1);
}
}
else
{
show[x][y] = count_number + '0';
}
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
// 1. 输入排查的坐标
// 2. 检查坐标处是不是雷
// (1)是雷 - boom - game over
// (2)不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续
int x = 0;
int y = 0;
int win = 0;
while (win < row * col - EASY_COUNT)
{
printf("请输入要排查雷的坐标:");
scanf("%d %d", &x, &y);// x -- (1,9) y -- (1,9)
//判断坐标的合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
display_board(mine, ROW, COL);
break;
}
else
{
// 不是雷的情况下,统计x,y坐标周围有几个雷
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
Spread(mine, show, x, y);
//显示排查出的信息
display_board(show, ROW, COL);
win++;
}
}
else
{
printf("该坐标已排查过\n");
}
}
else
{
printf("坐标输入有误,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
display_board(show, ROW, COL);
}
}
四、完整源码展示
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf(" -------------------\n");
printf("| 1.play |\n");
printf("| 2.clear |\n");
printf("| 0.exit |\n");
printf(" -------------------\n");
}
void game()
{
// 设计2个数组存放信息
char mine[ROWS][COLS] = {
0 };
char show[ROWS][COLS] = {
0 };
// 初始化棋盘
// mine初始化为全'0'
// show初始化为全'*'
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
// 打印棋盘
//display_board(mine, ROW, COL);
//display_board(show, ROW, COL);
// 布置雷
set_mine(mine,ROW,COL);
// 排雷
//display_board(mine, ROW, COL);
display_board(show, ROW, COL);
find_mine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 2:
system("cls"); // 清屏
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
game.h
#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable : 6031)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
// 默认雷
#define EASY_COUNT 20
// 函数声明
// 初始化
void init_board(char board[ROWS][COLS], int rows, int cols,char set);
// 打印棋盘
void display_board(char board[ROWS][COLS], int row, int col);
// 布置雷
void set_mine(char mine[ROWS][COLS], int row, int col);
// 排查雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
// 展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_board(char board[ROWS][COLS], int rows, int cols,char set)
{
int i = 0;
int j = 0;
for ( i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void display_board(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");
for ( i = 1; i <= row; i++)
{
printf("%d ", i);
for ( j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("----------扫雷游戏----------\n");
}
void set_mine(char mine[ROWS][COLS], int row, int col)
{
// 布置10个雷
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
// 统计
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (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] - 8 * '0');
}
// 递归实现展开
void Spread(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
int count_number = get_mine_count(mine, x, y);//排查该坐标附近雷的个数
if (count_number == 0)
{
show[x][y] = ' ';
if ((x - 1 > 0 && x - 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x - 1][y - 1] == '*')
{
Spread(mine, show, x - 1, y - 1);
}
if ((x - 1 > 0 && x - 1 < 10) && (y > 0 && y < 10) && show[x - 1][y] == '*')
{
Spread(mine, show, x - 1, y);
}
if ((x - 1 > 0 && x - 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x - 1][y + 1] == '*')
{
Spread(mine, show, x - 1, y + 1);
}
if ((x > 0 && x < 10) && (y - 1 > 0 && y - 1 < 10) && show[x][y - 1] == '*')
{
Spread(mine, show, x, y - 1);
}
if ((x > 0 && x < 10) && (y + 1 > 0 && y + 1 < 10) && show[x][y + 1] == '*')
{
Spread(mine, show, x, y + 1);
}
if ((x + 1 > 0 && x + 1 < 10) && (y - 1 > 0 && y - 1 < 10) && show[x + 1][y - 1] == '*')
{
Spread(mine, show, x + 1, y - 1);
}
if ((x + 1 > 0 && x + 1 < 10) && (y > 0 && y < 10) && show[x + 1][y] == '*')
{
Spread(mine, show, x + 1, y);
}
if ((x + 1 > 0 && x + 1 < 10) && (y + 1 > 0 && y + 1 < 10) && show[x + 1][y + 1] == '*')
{
Spread(mine, show, x + 1, y + 1);
}
}
else
{
show[x][y] = count_number + '0';
}
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
// 1. 输入排查的坐标
// 2. 检查坐标处是不是雷
// (1)是雷 - boom - game over
// (2)不是雷 - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续
int x = 0;
int y = 0;
int win = 0;
while (win < row * col - EASY_COUNT)
{
printf("请输入要排查雷的坐标:");
scanf("%d %d", &x, &y);// x -- (1,9) y -- (1,9)
//判断坐标的合法性
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
display_board(mine, ROW, COL);
break;
}
else
{
// 不是雷的情况下,统计x,y坐标周围有几个雷
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
Spread(mine, show, x, y);
//显示排查出的信息
display_board(show, ROW, COL);
win++;
}
}
else
{
printf("该坐标已排查过\n");
}
}
else
{
printf("坐标输入有误,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
display_board(show, ROW, COL);
}
}
总结
以上就是C语言实现扫雷小游戏的分析了,还有部分功能期待小伙伴们能补全!
希望该文章能对小伙伴们有所帮助!留个赞再走吧~
(如有错误,望指出)
边栏推荐
猜你喜欢
![[Dataset] Dataset summary of various insulators, bird's nests and anti-vibration hammers](/img/02/927f4e228eb3abbd76cade5be00352.png)
[Dataset] Dataset summary of various insulators, bird's nests and anti-vibration hammers

CTO强烈禁止使用Calendar,那用啥?

USB Protocol (2) Terminology

Prime Ring Problem

PerViT: 神经网络也能像人类利用外围视觉一样观察图像!

会议OA(待开会议&所有会议)

HoloView——实时数据

Redis middleware (from building to refuse pit)

走进音视频的世界——mp3封装格式

Detailed explanation of JVM runtime data area and JMM memory model
随机推荐
GBase 8c中怎么查询数据库配置参数,例如datestyle
Graduation thesis writing skills
笔记。。。。
sqlserver 对比两张表的差异
Redis中间件(从搭建到弃坑)
2022.7.31-----leetcode.1161
leetcode 42. Catch the rain
Centos install php7.4, build hyperf, forward RDS
Lsky Pro 企业版手动升级、优化教程
程序员如何学习开源项目,这篇文章告诉你
372. 超级次方
【应用推荐】常见资源管理器整理,含个人使用体验和产品选型推荐
热修复技术可谓是百花齐放
基于MySql,Redis,Mq,ES的高可用方案解析
leetcode-6132: Make all elements in array equal to zero
[Tear AHB-APB Bridge by hand]~ Why aren't the lower two bits of the AHB address bus used to represent the address?
XX市消防救援指挥中心实战指挥平台多链路聚合解决方案实例
【STM32】入门(一):环境搭建、编译、下载、运行
How does UXDB return the number of records for all tables in the current database?
In the background of the GBase 8c database, what command is used to perform the master-slave switchover operation for the gtm and dn nodes