目录
扫雷规则简介
实现扫雷前,我们先来看看扫雷的玩法:在一个9×9(初级)、16×16(中级)、16×30(高级)或自定义大小的方块矩阵中随机布置一定量的地雷(初级为10个,中级为40个,高级为99个),再由玩家逐个翻开方块,以找出所有地雷为最终游戏目标,若打开的方块没有雷,则会出现一个数子用于统计该空格附近雷的数量。
这次呢,博主会带领大家完成一个初级的扫雷游戏(9*9),这次博主依旧如前面三子棋游戏实现一样,采用三个文件
game.h 里包含了我们这次所需要的头文件
game.c 里是我们游戏的具体实现
test.c 是我们的一个游戏测试
游戏主界面
作为一个游戏,我们肯定的有一个界面,让使用者知道这是干什么,那我们先写一个主界面吧:
void meanu()
{
printf("*************************\n");
printf("****** 扫雷游戏 ******\n");
printf("****** 1.玩游戏 ******\n");
printf("****** 2.退出游戏 ******\n");
printf("*************************\n");
}
主界面代码实现如下:
主界面都实现了,我们肯定的有一个主函数;那么主函数我们应该怎么写呢?
我们在有了三子棋经验后,便知道这个游戏我们需要可以选择,只要不退出可以满足多次游戏,那么我们便可以写出代码了
int main()
{
int input = 0;
meanu();
srand((unsigned int)time(NULL));//与rand()搭配使用,用于产生随机数
printf("请选择>:");
do
{
scanf("%d",& input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戏");
break;
default:printf("非法输入,请重新输入");
}
} while (input != 2);
return 0;
}
主界面和主函数的成功实现,那么我们test.c就可以写出来了
#include "game.h"
void meanu()
{
printf("*************************\n");
printf("****** 扫雷游戏 ******\n");
printf("****** 1.玩游戏 ******\n");
printf("****** 2.退出游戏 ******\n");
printf("*************************\n");
}
int main()
{
int input = 0;
meanu();
srand((unsigned int)time(NULL));
printf("请选择>:");
do
{
scanf("%d",& input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戏");
break;
default:printf("非法输入,请重新输入");
}
} while (input != 2);
return 0;
头文件
为了防止每次使用函数前都需要声明,所以我们将所有需要的声明和头文件都放在了game.h里面
我们先来看一下所需要用的game.h内容
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9 //进行宏定义
#define COL 9 //
#define ROWS ROW+2 //
#define COLS COL+2 //
#define cnt 10
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROW][COL], 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);
在game.h里面我们看到了一些函数的声明,而他们就是我们等会儿需要在game.c里逐一实现函数,接下来看看博主是怎么实现的吧
初始化棋盘
首先我们得先创建数组,博主用的是创建两个二维数组的方式,创建如下
char mine[ROWS][COLS];//用来储存含‘0’和‘1’的棋盘,含雷盘
char show[ROWS][COLS];//用来储存玩家所看见的棋盘
至于为什么这儿用ROWS和COLS,而不用row和col,主要是为了方便雷数量的判断,后面还会有介绍。
这里初始化时,因为我们mine[ROWS][COLS]里存放的是雷,而我们这里用‘0’和‘1’来表示,‘1’表示雷,而这里初始化时因为没有雷,我们全部初始化为‘0’;show[ROWS][COLS]是展示给玩家的,我们给它全部初始化为‘*’;
InitBoard()函数代码如下
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
当我们需要使用时,只需要传入我们所需初始化的参数就行
InitBoard(mine,ROWS,COLS,'0');
InitBoard(show, ROWS, COLS, '*');
打印棋盘
我们希望玩家在选择玩游戏后,可以给玩家打印出以下这样一个棋盘
这个棋盘包含行和列的编码,显示的时9*9,顶上有扫雷游戏的提示,打印的是‘*’,获取这些信息,便可以写出代码如下
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("*****扫雷游戏******\n");//打印扫雷
for (i = 0; i <=col; i++)//打印列的编号
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d", i);//打印行的编号
int j = 1;
for (j = 1; j <= col;j++)
{
printf(" %c", board[i][j]);
}
printf("\n");
}
}
//i和j从1开始,等于row、col结束,这里传进来的是ROW、COL,也就是9
//是为了打印9*9的棋盘
传参如下
DisplayBoard(show, ROW, COL);//打印9*9的棋盘
布置雷场
当我们棋盘打印好后我们发现到现在为止,我们还没有雷啊,无法玩
所以我们接下来开始布置雷场,布置雷场呢,我们采用前面所说随机数的概念来随机产生雷,SetMine()函数实现如下
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = cnt;//cnt为前面宏定义为10;
while (count)//循环结束条件
{
int x = (rand() % 9)+1;//产生1-9的随机数
int y = (rand() % 9)+1;//因为board[ROWS][COLS]是11*11的,而我们需要9*9的
if (board[x][y] == '0')//判断是否有雷,若无,则放上一个雷
{
board[x][y] = '1';
count--;//放一个雷就减一,10个雷放完结束
}
}
}
传参入下
SetMine(mine, ROW, COL);
//前面所说mine里放雷,所这里传参为mine
排查雷
当我们布置雷也完成之后我们就需要开始排雷了,首先我们得这个函数得提示玩家改干什么
printf("请输入需要排查雷的坐标>;");
接下来玩家需要输入坐标,所以我们得接收
scanf("%d %d", &x, &y);
输入得坐标我们是不是得进行一个判断,判断是否合法
if (x > 0 && x <= row && y > 0 && y <= col)
不合法时我们得给出提示
else printf("输入非法,重新输入:>");
当合法时,我们就得判断输入的该位置是否有雷,有雷我们就的提醒玩家你被炸死,并结束游戏,
我们为了让玩家死的明白,我们把雷的位置给玩家打印出来
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
该位置不是雷时,我们就要判断坐标周围有多少雷了,这时候我们创建11*11的作用就体现出来了,因为棋盘为9*9,要判断坐标周围雷的数量,一般是判断周围八个坐标,但是呢,边缘区域没有8个,就比较特殊,情况较为麻烦,而我们创建了11*11,可以有效的防止数组越界额,我们只在中间9*9的棋盘内放置了雷,边缘区域没有雷,所以不影响雷数量的判断
int n = GetMineCount(mine, x, y);
show[x][y] = n + '0';//在给玩家所展示的棋盘该位置告诉玩家有多少雷
DisplayBoard(show, ROW, COL);//打印
count++;//表示成功排除一个空位
GetMineCount()函数为我们写的判断有几个雷的函数,实现逻辑为周围8个字符的ascll值相加减去8个字符‘0’的ascll值,就为我们‘1’的数量,这里也可以看出把雷设为‘1’,无雷设为‘0’的好处了,下来我们看一下GetMineCount()函数的实现
int GetMineCount(char mine[ROW][COL], 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');
}
配合下图观看,若有三个就放返回3
当我们输入错误,或者成功排除一个空位时,我们还要进行下一次输入所一我们用while()来实现,到这儿我们布置雷的函数全部完成,实现如下
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (cnt<(row * col - count))//结束循环的条件
{
printf("请输入需要排查雷的坐标>;");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
int n = GetMineCount(mine, x, y);
show[x][y] = n + '0';
DisplayBoard(show, ROW, COL);
count++;
}
else printf("输入非法,重新输入:>");
if (count == row * col -cnt)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
}
至此我们game.c已经全部实现,我们来看一下game()函数的代码
void game()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
InitBoard(mine,ROWS,COLS,'0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(show, ROW, COL);
SetMine(mine, ROW, COL);
FindMine(mine, show, ROW, COL);
}
以上就是博主的对扫雷游戏的实现,制作不易,各位看官给个三连呗!!!
以上就是博主的对扫雷游戏的实现,制作不易,各位看官给个三连呗!!!
完整代码
game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9 //进行宏定义
#define COL 9 //
#define ROWS ROW+2 //
#define COLS COL+2 //
#define cnt 10
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROW][COL], 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);
game.c
#include "game.h"
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("*****扫雷游戏******\n");
for (i = 0; i <=col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d", i);
int j = 1;
for (j = 1; j <= col;j++)
{
printf(" %c", board[i][j]);
}
printf("\n");
}
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = cnt;
while (count)
{
int x = (rand() % 9)+1;//产生1-9的随机数
int y = (rand() % 9)+1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
int GetMineCount(char mine[ROW][COL], 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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
while (cnt<(row * col - count))
{
printf("请输入需要排查雷的坐标>;");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
DisplayBoard(mine, ROW, COL);
break;
}
int n = GetMineCount(mine, x, y);
show[x][y] = n + '0';
DisplayBoard(show, ROW, COL);
count++;
}
else printf("输入非法,重新输入:>");
if (count == row * col -cnt)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
}
void game()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
InitBoard(mine,ROWS,COLS,'0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(show, ROW, COL);
SetMine(mine, ROW, COL);
FindMine(mine, show, ROW, COL);
}
test.c
#include "game.h"
void meanu()
{
printf("*************************\n");
printf("****** 扫雷游戏 ******\n");
printf("****** 1.玩游戏 ******\n");
printf("****** 2.退出游戏 ******\n");
printf("*************************\n");
}
int main()
{
int input = 0;
meanu();
srand((unsigned int)time(NULL));
printf("请选择>:");
do
{
scanf("%d",& input);
switch (input)
{
case 1:
game();
break;
case 2:
printf("退出游戏");
break;
default:printf("非法输入,请重新输入");
}
} while (input != 2);
return 0;
}