目录
① 前言
② 游戏规则
③ 实现思路
一. test.c文件实现
1.创建菜单
2.实现switch case语句
3.创建雷盘
4.多种函数
二. game.c文件实现
1.初始化雷盘
2.打印雷盘
3.随机布雷
4. 进行排雷
三.game.h头文件实现
致谢:
三.整体代码实现
1.test.c
2.game.c
上期讲到了C语言三子棋游戏的实现,本期介绍另外一款热门小游戏--——扫雷!
这款游戏相信小时候都玩过,接下来随着我来用C语言实现,我会一步步把整个扫雷游戏的所有功能实现,详细的讲解每一个功能代码上的实现。
扫雷~启动!!
在一个N*N的方块矩阵中随机布置一定量的地雷,再由玩家输入坐标翻出地雷,以找出所有地雷为最终游戏目标。如果玩家翻开的方块有地雷,则游戏结束。
1.创建菜单:进行菜单的美化。
2.实现switch case语句:开始游戏或退出游戏的选择。
3.创建雷盘:假设创建9*9的数组雷盘,在这个棋盘上去布置雷,再对雷进行排查。但我们在找雷的过程中,进行遍历该位置的周围,会导致越界,所以我们就把这个数组扩大一圈,变成11*11。
创建两个雷盘,一个我们放雷,一个对外加密的雷盘
4.初始化雷盘:对两个雷盘初始化。
5.打印雷盘:打印对外加密的雷盘,再加入行列序号方便输入坐标查雷。
6.随机布雷:利用rand函数进行在9*9雷盘范围内随机布雷,不会让后面的排查雷操作越界。
7.进行排雷:这是非常关键的一步,需要假设多种情况。
主要通过三个文件来实: test.c game.c game.h
test.c — 扫雷的测试game.c — 游戏函数的实现
game.h — 游戏函数的声明,
//菜单
void menu()
{
printf("->*************************<-\n");
printf("->******1. 开始游戏********<-\n");
printf("->******0. 退出游戏********<-\n");
printf("->*************************<-\n");
}
int main()
{
srand((unsigned int )time(NULL)); //产生随机值
int input = 0;
do
{
printf("请选择\n");
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("你已经退出游戏");
break;
default:
printf("输入错误,重新选择");
break;
}
} while (input);
return 0;
}
在自定义进入游戏函数里面创建两个数组
因为代码中多次使用数组,利用#define定义两个数组和大小在头文件中。
//printf("扫雷 启动!\n");
char mine[ROWS][COLS]; //创建布置雷的数组
char show[ROWS][COLS]; //对外显示需要排查雷的数组
需要对雷盘初始化,打印雷盘,随机布置雷,排查雷这些操作
//游戏
void game()
{
//printf("扫雷 启动!\n");
char mine[ROWS][COLS]; //创建布置雷的数组
char show[ROWS][COLS]; //对外显示需要排查雷的数组
//初始化棋盘
Initboard(mine,ROWS,COLS,'0');
Initboard(show, ROWS, COLS,'*');
//打印棋盘
//Displayboard(mine, ROW, COL);
Displayboard(show, ROW, COL);
//布置雷
Setmine(mine,ROW,COL);
//Displayboard(mine, ROW, COL);
//排查雷
Findboard(mine, show, ROW, COL);
设置四个参数,二维数组名,大小,还有一个想要初始化独立的字符。
数组大小比对外数组大,防止后期越界
//初始化棋盘定义
void Initboard(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 Displayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("-------扫 雷-------\n");
for (j = 0; j <= col; j++) //打印列的序号
{
printf("%d ", j);
}
printf("\n");
for (i = 0; i <= row; i++) //打印排雷区分割
{
printf("- ");
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d", i); //打印行的序号
printf("|"); //打印排雷区分隔
for (j = 1; j <= row; j++)
{
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("-------扫 雷-------\n");
}
通过rand()进行随机布雷,控制范围。创建一个地雷数量的变量,只有成功布雷后才结束。
//布置雷定义
void Setmine(char board[ROWS][COLS], int row, int col) //范围依旧在对外显示数组内
{
int x = 0;
int y = 0;
int ret = BOMB; //定义炸弹的数量
while (ret)
{
x = rand() % row + 1; //布置随机雷,范围在1~9
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
ret--;
}
}
}
1.当翻开的是“地雷”时,会被炸然后游戏结束。
2.当输入的格子周围一圈当中存在“地雷”时,输入的坐标处会显示周围一圈格子内存在“地雷”的个数。
3.如果把不是雷的地方都找出来了,游戏也结束
//排查雷定义,将两个数组联系到一起
void Findboard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int win = 0;
while (win\n");
scanf("%d %d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col)
{
if (mine[i][j] == '1')
{
printf("你被炸了,游戏结束\n");
Displayboard(mine, ROW, COL); //让用户被炸的明白
break;
}
else if (mine[i][j] != '1') //不是雷,计算周围有几个雷
{
int ret = GetBomb(mine,i,j);
show[i][j] = ret + '0'; //得到的数字需要转成字符形式,因为数组是char。将该位置换成字符数
Displayboard(show, ROW, COL); //打印赋值后的show棋盘
win++;
}
}
else
{
printf("输入错误,请重新输入坐标\n");
}
}
if (win == row * col - BOMB)
{
printf("恭喜你,排雷成功\n");
}
}
GetBomb()计算坐标处雷的数量,因为数组char型,函数返回的是整型,加上'0'。
因为:'0'的ascll值 48。
'1' ------49
'2'---50
所以:'2' - '0' = 2;
字符2减去字符0,等于数字2,同理,字符1-字符0 = 数字1
//计算坐标周围雷的数量
int GetBomb(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';
}
我们需要两组二维数组大小,需要炸弹数量的定义,需要包含rand() time()头文件,还要多个函数的定义
#pragma once
#include
#include
#define ROW 9 //给用户看的大小
#define COL 9
#define ROWS ROW+2 //实际大小
#define COLS COL+2
#define BOMB 10 //布置炸弹的数量
//初始化棋盘
void Initboard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void Displayboard(char board[ROWS][COLS], int row, int col);
//布置雷
void Setmine(char board[ROWS][COLS], int row, int col);
//排查雷
void Findboard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
到这里,整体扫雷游戏代码讲解差不多结束了,感谢你看到这里,扫雷游戏是非常经典的一款,相信每一位初学者都会接触,希望我的介绍能有些许帮助,谢谢大佬看到这里,在下面我献上整个文件代码实现。 文中不足的,希望得到指正和改善。感激不尽!!愿星光照亮每一位赶路人。
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include"game.h"
//菜单
void menu()
{
printf("->*************************<-\n");
printf("->******1. 开始游戏********<-\n");
printf("->******0. 退出游戏********<-\n");
printf("->*************************<-\n");
}
//游戏
void game()
{
//printf("扫雷 启动!\n");
char mine[ROWS][COLS]; //创建布置雷的数组
char show[ROWS][COLS]; //对外显示需要排查雷的数组
//初始化棋盘
Initboard(mine,ROWS,COLS,'0');
Initboard(show, ROWS, COLS,'*');
//打印棋盘
//Displayboard(mine, ROW, COL);
Displayboard(show, ROW, COL);
//布置雷
Setmine(mine,ROW,COL);
//Displayboard(mine, ROW, COL);
//排查雷
Findboard(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int )time(NULL)); //产生随机值
int input = 0;
do
{
printf("请选择\n");
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("你已经退出游戏");
break;
default:
printf("输入错误,重新选择");
break;
}
} while (input);
return 0;
}
#pragma once
#include"game.h"
//初始化棋盘定义
void Initboard(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 Displayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("-------扫 雷-------\n");
for (j = 0; j <= col; j++) //打印列的序号
{
printf("%d ", j);
}
printf("\n");
for (i = 0; i <= row; i++) //打印排雷区分割
{
printf("- ");
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d", i); //打印行的序号
printf("|"); //打印排雷区分隔
for (j = 1; j <= row; j++)
{
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("-------扫 雷-------\n");
}
//布置雷定义
void Setmine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int ret = BOMB; //定义炸弹的数量
while (ret)
{
x = rand() % row + 1; //布置随机雷,范围在1~9
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
ret--;
}
}
}
//计算坐标周围雷的数量
int GetBomb(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 Findboard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int win = 0;
while (win\n");
scanf("%d %d", &i, &j);
if (i >= 1 && i <= row && j >= 1 && j <= col)
{
if (mine[i][j] == '1')
{
printf("你被炸了,游戏结束\n");
Displayboard(mine, ROW, COL); //让用户被炸的明白
break;
}
else if (mine[i][j] != '1') //不是雷,计算周围有几个雷
{
int ret = GetBomb(mine,i,j);
show[i][j] = ret + '0'; //得到的数字需要转成字符形式,因为数组是char。将该位置换成字符数
Displayboard(show, ROW, COL); //打印赋值后的show棋盘
win++;
}
}
else
{
printf("输入错误,请重新输入坐标\n");
}
}
if (win == row * col - BOMB)
{
printf("恭喜你,排雷成功\n");
}
}
#pragma once
#include
#include
#define ROW 9 //给用户看的大小
#define COL 9
#define ROWS ROW+2 //实际大小
#define COLS COL+2
#define BOMB 10 //布置炸弹的数量
//初始化棋盘
void Initboard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void Displayboard(char board[ROWS][COLS], int row, int col);
//布置雷
void Setmine(char board[ROWS][COLS], int row, int col);
//排查雷
void Findboard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);