系列文章目录:
扫雷游戏的创建
小白的初次尝试,如有错误,请及时联系博主,多多关照。
前言:
扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格 子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
一、扫雷游戏规则?
游戏组成
扫雷游戏共有5种可玩元素,分别是:
-
方块:可以被打开,里面隐藏着其它的元素。
-
数字:以数字为中心3×3的范围内,有着和数字相同数量的炸弹方块。
-
记号:有“旗帜”和“问号”两种,可以用来标记方块。被“旗帜”标记后的方块不能再被打开,同时炸弹计数器显示的数值-1。一般“旗帜”会用来标记玩家确信是炸弹的方块。
-
空格:空的格子会自动打开周边的方块,直到遇见数字为止。
-
炸弹:判定游戏胜负的关键元素。
②操作方式
使用鼠标可以对游戏内容进行操作:
单击左键可以打开方块;单击右键可以给方块打上标记。
此外,如果一个数字的周围,被插上旗帜的方块数量等于该数字,那么此时对着这个数字双击左键,可以直接打开它附近所有未被旗帜标记的方块。
③胜负判定
当场上只剩下炸弹方块未被打开后,游戏胜利!在这之前如果你打开了炸弹方块,则游戏失败。
二、扫雷游戏创建步骤
首先我们需要写不同用途的文件,以确保游戏的运行,分别是:
1. game.h //头文件(包含所有需要的用到的头文件,所有参数的定义,函数声明)
2.game.c //游戏文件(所有函数内容的编辑)
3. test.c //测试文件(代码运行)
2.1.在“game.h”下引入库
代码如下:三者含义将在后面介绍
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
2.2.定义游戏变量
原因:函数要先声明后使用
优点:方便以后对参数实现更改
思路:
第一步,首先我们需要创建一个界面函数,用于选择退出游戏或者是进入游戏。
第二步,创建一个放置雷的棋盘
第三步,放入雷,并打印有雷的棋盘
第四步,输入排查雷的坐标
第五步,反馈输入坐标的结果,之后循环,直到成功排查或被雷炸死
代码如下:
#pragma once
#define ROW 9 //表示9行
#define COL 9 //表示9列
#define ROWS ROW+2 表示11行
#define COLS COL+2 表示11列
#define EASY_COUNT 10 //10个雷
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int cols, int rows, char set);
//打印棋盘
void DisplayBorad(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char board[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);
三、在“test.c”下创建主函数
3.1.这部分为游戏的主函数
代码如下:
#include"game.h" //要想使用下面的game()函数需要引用“game.h”文件
int main()
{
int input = 0; //输入值
srand((unsigned int)time(NULL)); //生成一个随机数,time函数无参返回
//返回类型强制转换为unsigned//如需想生成随机数则需要使用#include<time.h>
do
{
menu();printf("请选择:>");
switch (input)
{
case 1:
printf("开始游戏");
game();
break;
case 0:
printf("退出游戏");
break;
default:
printf("请重新输入");
break;
}
} while (input);
return 0;
}void menu() //菜单函数的创建
{
printf("欢迎来到扫雷游戏");
printf("**************");
printf("***1-start****");
printf("****0-exit****");
printf("**************");
}
3.2.游戏的“game()”函数创建
代码如下:
void game() //游戏所用到函数
{
char mine[ROWS][COLS]; //存放布置的雷的信息
char show[ROWS][COLS]; //存放排查出的雷的信息InitBoard(mine,ROWS,COLS,'0'); //用于存放雷的棋盘,初始化为0
InitBoard(show, ROWS, COLS,'?'); //用于存放雷的棋盘,初始化为?
DisplayBoard(show, ROW, COL); //打印9×9显示给玩家看的棋盘
SetMine(mine, ROW, COL); //布置雷
//布置好雷之后可以打印下面这个函数查看是否布置成功,隐藏此函数请在最前面加两个//
DisplayBoard(mine, ROW, COL);FindMine(mine, show, ROW, COL); //开始排查雷
}
棋盘的设置
我们首先要创建一个棋盘用于放置雷,而棋盘我们用二维数组char[x][y]来设置,x,y分别表示棋盘的行列,当我们任意选择棋盘中的一个坐标,如果这个坐标放置的不是雷,那么它就会显示以当前坐标为中心的周围 8 个格子中地雷的数量,如图所示:
但是如果我们选择的坐标是这个棋盘的最边上,那么它所搜查的范围就会超出所设置的二维数组9×9的棋盘,如下图所示的红色框:
它搜查的范围已经越出了9*9的范围里,导致了越界问题。所以我们在设置棋盘的时候可以选择将棋盘的范围设置的大一些,在9×9棋盘的基础上,将二维数组扩大一圈设置成11×11的棋盘。如下图:
红线框为原来9*9范围。那么在这个棋盘上我们输入坐标排查的的范围都是在棋盘的范围之内,就不存在越界问题了,所以在设置棋盘的时候我们将存放数据的数组可以设置成char[11][11]
四、在“game.c”下创建游戏函数内容
4.1.初始化棋盘
(非雷用字符 0 表示,雷用字符 1 表示)
代码如下:
void InitBoard(char board[ROWS][COLS], int cols, int rows, char set)
{
int i = 0; //控制行
for (i = 0; i < ROWS; i++)
{
int j = 0; //控制列
for (j = 0; j < COLS; j++)
{
board[i][j] = set; //创建初始化数组
}
}
}
4.2.打印棋盘
代码如下:
void DisplayBoard(char board[ROWS][COLS], int col, int row)
{
int i = 0; //控制行
printf("欢迎来到扫雷游戏");
for (i = 0; i <= COL; i++) //打印列号
{
printf("%d", i);
}
printf("\n");
for(i=1;i<=ROW;i++)
{
int j = 0;
printf("%d", i); //打印行号
for (j = 1; j <= COL; j++) //控制列
{
printf("%c ", board[i][j]); //循环打印数组里的所有内容
}
printf("\n"); //每一行打印完之后换行
}
printf("\n");
}
4.3.布置棋盘中的雷
代码如下:
void SetMine(char board[ROWS][COLS], int row, int col)
{
//设置雷的数量为10
int number = EASY_COUNT;
while (number)
{ //rand函数使用需要#include<string.h>
int x = rand() % ROW + 1; //棋盘x的坐标,%row值为0-8,+1值变成0-9
int y = rand() % COL + 1; //与上同理
if (board [x][y] == '0') //首先判断当前的随机位置是否有雷,无雷进入
{
board [x][y] = '1'; //没有雷就在当前位置下放一个‘1’表示雷
count--; //放置成功后,雷的数量减一
}
}
}
4.4.排查棋盘中的雷
代码如下:
void FindMine(char board[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
int x = 0; //行
int y = 0; //列
int win = 0; //排查次数
while (win < row * col - EASY_COUNT) //9*9共81个格子减去10个雷还剩71个格子
{
printf("请输入要排查的坐标:>");
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
DisplayBorad(mine, ROW, COL); //炸死后雷的分布图给玩家呈现出来
break;
}
else
{
//此坐标不是雷,就要统计此坐标附近雷的个数
int number = GetMineCount(mine, x, y);
show[x][y] = number + '0'; //排查出有几个雷后,将数字转化为字符型// +‘0’的意思为将整形变量转换为字符型
DisplayBorad(show, ROW, COL);
win++; //每排查一次,此数+1
}
}
else
{
printf("排查的坐标非法,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
DisplayBorad(mine, ROW, COL);
4.4中GetMineCount函数
代码如下:
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] +
mine[x - 1][y] + //可以看到这是对该坐标周围的 8 个坐标的字符加起来的,
//因为字符 '1' 和字符 '0' 对应的ASCII码值是相连的,
// 因此将周围 8 个的字符加起来减去 8 个字符 '0' ,
//这样我们就可以得到字符 '1' 的个数,也就是雷的个数。
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0');
}
总结:
这就是扫雷游戏的全部内容。