^前言:谈起扫雷小游戏大家想必都不陌生吧,或许是在以前的老电脑上自带的游戏中玩过;那么,我们今天便言归正传,用c语言来简单创造个简单版的扫雷小游戏吧!
一·我们下面便开始对它的介绍布置:
首先,我们先在vs中创造文件方便后续的书写,按我的习惯:我先是创造了三个文件分别为test.c;game.c;game.h;顾名思义,我们可以根据它们的名字,后缀等看出:一个是我们整体布置测试的文件,一个是我们在其中安放一些运行函数的文件,最后一个是我们储存函数头文件的文件。下面整体对我们的设计分析:我将会在game.h内存放一些库函数头文件什么的,最后将会在另两个源文件中引用,大大减少了这种代码的创造量(#include"game.h")。
具体思路分布设计:1 我们先设计一个菜单作为对游戏的装饰,下面我们可以自由发挥,列如这个模板,在menu中尽情发挥。
void menu() {
printf("开始游戏请输入1;退出游戏请输入0\n");
}
2我们利用一个do while循环来实现可以重复进行的步骤,这里用了input来接收输入的0或1;在用一个switch语句来实现对游戏进行还是结束的一个选择。
int input = 0;
do {
menu();
scanf("%d", &input);
switch (input) {
case 1:game();
break;
case 0:printf("退出游戏");
break;
default:printf("输出出现了错误,请修改重新输入");
break;
}
} while (input);
下面我们便对game()函数内部具体实现:这样,我们创建两个棋盘,分别是我们所操作,能看到的,我们将雷作为字符1,将非雷的地方作为字符0;而另一个便是玩家进行游戏时所看到的棋盘,我们用填充满。为了之后可以确定未扫到雷的地方,其周围雷的个数,我们姑且将99棋盘先扩大到11*11,便于后续进行操作。
3我们接下来对我的和展示的两个数组进行用函数初始化:分别填入0,*,定义的数组如:
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
Initboard(mine, ROWS, COLS, '0');
Initboard(show, ROWS, COLS, '*');
接下来我们在game.h声明一下:
define ROW 9
define COL 9
define ROWS ROW+2
define COLS COL+2
void Initboard(char board[ROWS][COLS], int rows, int cols, int set);
然后我们在game.c中完成一下这步函数的实现吧:
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;
}
}
}
现在我们已经完成了将两个棋盘分别填好最初的数据。如下:
4下面我们要完成的便是对棋盘内容的打印操作,才会将上面的俩个棋盘打印出:
Displayboard(mine,ROW ,COL );
Displayboard(show, ROW, COL);
接着我们在game.h进行声明;
void Displayboard(char board[ROWS][COLS], int row, int col);
再完成函数实现这一步的具体操作:
我们可以初始化i,j两个变量来对这个棋盘打印,但是为了方便我们玩家后期进行坐标输入排雷时方便找到对应的位置,我们可以把坐标打印出来故我们可以在每列即j的第一个打印由0-9,而i便从每行的第一个打印由1-9;而这个0是为了使得行列坐标对齐。如下在game.c中的操作:
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 = 1; i <= row; i++) {
printf("%d ", i);
for (j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}printf("\n");
}
printf("-----------------扫雷-----------\n");
}
这样我们便完成了这个展示棋盘的方面:
5 接下来我们该布置雷的信息了,我们 可以选择布置简单的10个雷:
将雷的个数定义成count为10;我们可以用时间戳配合srand函数生成随机数来完成这一操作,然而我们还要控制十个雷的量,因此;我们采用一个while循环,让每布置一个雷这个计数的便减一,一直到为0,则不在进入这个布置雷的循环:
直接来看这个game.c中函数的设计吧:
void Setmine(char board[ROWS][COLS], int row, int col) {
int lei = count;
while (lei) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0') {
board[x][y] = '1';
lei--;
}
}
}
6 下面介绍玩家如何扫雷:
我们要想玩家肯定要先输入坐标,然后我们写的这个代码要判断它的合法性即不能越界,要在1-9之间,否则便提示‘输入错误’,如果上面条件符合的话,那么,我们便开始看看是否排雷重复,重复的话也要提醒,接着不重复的话,我们要判断是否为雷;如果是的话,就被炸死了,在这可以显示一下棋盘,让玩家输的明白。不是的话要在此位置显示出其周围雷的个数;那么怎么判断呢???:::要知道我们所填写的棋盘上都是字符:我们可以先把他转化成数字:而‘0‘对应48,然后数字依次叠加故:’1‘-’0‘=1;可以这样转换。因此我们这时候可以用一个函数做这件事,返回值用counts接收。函数如下:
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y] +
board[x - 1][y - 1] +
board[x][y - 1] +
board[x + 1][y - 1] +
board[x + 1][y] +
board[x + 1][y + 1] +
board[x][y + 1] +
board[x - 1][y + 1] - 8 * '0';
}
他有10个雷,81个位置,也就是说如果我们将这剩下的七十一个位置全部排出的话,在这个过程中我们没有踩到雷的话,我们就赢了,可以用win来记录,每当排过一次雷就让win减一,直到win为0,那么我们就可以胜利,胜利后也可以展示一下棋盘,方便玩家看清雷的位置,在game.c中的具体操作如下:
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
//判断坐标合法性
int win = row * col - count;
while (win) {
int x = 0;
int y = 0;
//找到非雷的个数
printf("请输入要排查雷的坐标,坐标之间用空格隔开,先行后列。\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (show[x][y] != '*') {
printf("该坐标已被排查过,不能重复排查。\n");//防止排雷重复
}
else {
if (mine[x][y] == '1') {
printf("扫到雷,已被炸死\n");
Displayboard(mine, ROW, COL);
break;
}
else {//统计mine中x,y周围的雷
int counts = get_mine_count(mine, x, y);
show[x][y] = counts + '0';//转换数字字符
Displayboard(show, ROW, COL);
win--;
}
}
}
else printf("输入的坐标非法,请重新输入\n");
}
if (win == 0) {
printf("恭喜排雷成功!!!\n");
Displayboard(mine, ROW, COL);
}
}
下面是我们这个游戏在test.c中game()内具体放置的函数:
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化
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);
Findmine(mine, show, ROW, COL);
}
7.我们来展示一下它运行起来的样子:
二·我们的介绍操作便完成了,下面我来展示下具体这三个文件的代码布置吧:
test.c:
#include"game.h"
void menu() {
printf("开始游戏请输入1;退出游戏请输入0\n");
}
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
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);
Findmine(mine, show, ROW, COL);
}
int main() {
srand((unsigned int)time(NULL));
int input = 0;
do {
menu();
scanf("%d", &input);
switch (input) {
case 1:game();
break;
case 0:printf("退出游戏");
break;
default:printf("输出出现了错误,请修改重新输入");
break;
}
} while (input);
return 0;
}
game.c:
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 = 1; i <= row; i++) {
printf("%d ", i);
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 lei = count;
while (lei) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0') {
board[x][y] = '1';
lei--;
}
}
}
int get_mine_count(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y] +
board[x - 1][y - 1] +
board[x][y - 1] +
board[x + 1][y - 1] +
board[x + 1][y] +
board[x + 1][y + 1] +
board[x][y + 1] +
board[x - 1][y + 1] - 8 * '0';
}
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int win = row * col - count;
while (win) {
int x = 0;
int y = 0;
printf("请输入要排查雷的坐标,坐标之间用空格隔开,先行后列。\n");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) {
if (show[x][y] != '*') {
printf("该坐标已被排查过,不能重复排查。\n");
}
else {
if (mine[x][y] == '1') {
printf("扫到雷,已被炸死\n");
Displayboard(mine, ROW, COL);
break;
}
else {//统计mine中x,y周围的雷
int counts = get_mine_count(mine, x, y);
show[x][y] = counts + '0';
Displayboard(show, ROW, COL);
win--;
}
}
}
else printf("输入的坐标非法,请重新输入\n");
}
if (win == 0) {
printf("恭喜排雷成功!!!\n");
Displayboard(mine, ROW, COL);
}
}
game.h:
define _CRT_SECURE_NO_WARNINGS
include
include
include
define ROW 9
define COL 9
define ROWS ROW+2
define COLS COL+2
define count 10
void Initboard(char board[ROWS][COLS], int rows, int cols, int set);
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);
三.当然,我们还可以进行一下拓展,比如安装显示上计雷数设备,显示时间设备等等,给他从简单到复杂化等。让我们的扫雷小游戏充满更大的趣味来吸引玩家兴趣等。
四·总结:我认为:无论我们用代码写什么,还是完成一项任务什么的,我们首先要思路清晰,分布将每一次该做什么想的清楚,再者就是每一步要发生什么,如何去解决等等都要考虑全面,接着便是动手一步一步去实践,每走一步就要检测自己是否出现了错误等,及时修改等等,最后持之以恒的在这条路上走下去,才能看见更加优秀的自己.