目录
游戏的组成
还是跟之前猜数游戏一样,需要进去需求分析。首先需要设计一个菜单界面,其次是游戏界面,相
信每个人都玩过扫雷游戏,这样我们能联想到这么些步骤,初始化棋盘、打印棋盘、设置雷的位
置、排查雷。这次设计这个扫雷游戏需要分多个文件来组成,首先需要一个头文件,其次是两个源
文件,头文件放函数的声明以及一些定义,源文件就放我们的函数定义。
1.头文件saolei.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 Mine_count 10 //定义雷的数量
#define MaxSize 50//定义最大长度
//以下是函数声明
void menu();//菜单
void game(int Rows, int Cols, int Row, int Col, int Mine_count);//游戏
void test();//输入选择
void InitPanel(char arr[MaxSize][MaxSize], int rows, int cols, char set);//初始化棋盘
void PrintPanel(char arr[MaxSize][MaxSize], int row, int col);//打印棋盘
void setMine(char arr[MaxSize][MaxSize], int row, int col, int Mine_count);//设置雷
void checkMine(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int row, int col, int Mine_count);//排雷
void foldPanel(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int row, int col);//附近没有雷展开
头文件的声明我写了注释,方便大家理解,如果不理解也不要着急,我们接着往下看。
2.源文件1 define.c
#include "saolei.h"
//以下是函数的定义
void InitPanel(char arr[MaxSize][MaxSize], int rows, int cols, char set)//初始化棋盘,形参接收实参传来的
{
int i = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
arr[i][j] = set;//set是根据实参传进来决定
}
}
}
void PrintPanel(char arr[MaxSize][MaxSize], int row, int col)//打印棋盘,形参接收实参传来的
{
int i = 0;
for (int i = 0; i <= col; i++) {//打印列0-9数字,方便排雷
printf("%2d ", i);//最大宽度为2
}
printf("\n");
for (int i = 1; i <= row; i++) {
printf("%2d ", i);//打印行0-9数字,方便排雷
for (int j = 1; j <= col; j++) {
printf("%2c ", arr[i][j]);
}
printf("\n");
}
}
void setMine(char arr[MaxSize][MaxSize], int row, int col,int Mine_count) //设置雷的位置
{
int count = Mine_count;//雷
int x = 0;//设置坐标
int y = 0;
while (count)
{
int x = rand() % row + 1;//随机坐标用来赋雷
int y = rand() % col + 1;
if ( arr[x][y]!='1') //判断有没有重复赋雷
{
arr[x][y] = '1';
count--;
}
}
}
void foldPanel(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int x, int y) //附件没有雷展开
{
int count = get_Mine_quantity(mine, x, y);//统计周围雷的数量
if (count != 0)
{
show[x][y]= count + '0';
}
else if(show[x][y] != ' ')//判断这个位置有没有被展开
{
show[x][y] = ' ';//没有的话并且周围没雷直接展开
//通过checkMine函数,用户所输入的坐标传进来然后判断,没有雷且这个位置没有被展开,接着展开
//通过递归的方式一直展开,直到周围有雷。
int i, j;
for (int i = x - 1; i < x + 1; i++) {
for (int j = y - 1; j < y + 1; j++) {
foldPanel(mine, show, i, j);
}
}
}
else
{
return;
}
}
static int get_Mine_quantity(char arr[MaxSize][MaxSize], int x, int y)//这个设置成静态函数,只在这个文件下使用
{
int count_AroundMine = 0;//统计周围雷的数量
for (int i = x - 1; i < x + 1; i++) {//通过checkMine函数,用户所输入的坐标传进来然后判断
for (int j = y - 1; j < y + 1; j++) {
count_AroundMine += arr[i][j] - '0';//通过计算'1'和'0'的ASCII码值来统计,'1'=49、'0'=48
}
}
return count_AroundMine;//返回雷的数量
}
void checkMine(char mine[MaxSize][MaxSize], char show[MaxSize][MaxSize], int row, int col, int Mine_count) //排雷
{
int x = 0;//设置坐标
int y = 0;
int click = 0;//设置排雷的次数
while (click < row * col - Mine_count) //当排雷排完了循环就结束
{
printf("请输入你要排查的位置: ");
scanf("%d %d", &x, &y);//输入要排雷的坐标
printf("\n");
if (x >= 1 && y >= 1 && x <= row && y <= col) //判断有没有越界
{
if (mine[x][y] == '0')//根据mine棋盘判断
{
if ((show[x][y] >= '0' && show[x][y] <= '9') || (show[x][y] == ' '))
{
printf("该坐标已经排查过,请重新输入:\n");
}
else
{
/*int amoun_Mine = get_Mine_quantity(mine, x, y);//没踩到雷,统计周围雷的数量
show[x][y] = amoun_Mine + '0';//根据传回来雷的数量加上字符0,转化为字符形式*/
foldPanel(mine, show, x, y);//展开
PrintPanel(show, row, col);//然后打印出周围有多少雷的数量
click++;
}
}
if (mine[x][y] == '1')
{
printf("小可爱,你踩到雷了呢!\n ");
printf("\n");
PrintPanel(mine, row, col);//打印出所有位置的面板
printf("\n");
break;
}
}
else
{
printf("请输入有效的坐标!\n ");
printf("\n");
PrintPanel(show, row, col);
}
if (click == row * col - Mine_count)//当排雷排完了游戏就结束
{
printf(" 恭喜挑战成功!\n");
PrintPanel(mine, row, col);//查完成后打印出来
break;
}
}
}
这里的函数分别是初始化棋盘、打印棋盘、设置雷、获取周围雷的数量、展开、排查雷。
3.源文件2 saolei.c
#include "saolei.h"
void menu()//菜单界面
{
printf("***********************\n");
printf("***** 1:大学生难度 *****\n");
printf("***** 2:初中生难度 *****\n");
printf("***** 3:高中生难度 *****\n");
printf("***** 0:你走吧 *****\n");
printf("***********************\n");
}
void test()
{
int input = 0;//初始化用户输入
do {
menu();
printf(" 请输入: ");
scanf("%d", &input);//用户输入
printf("\n");
switch (input)
{
case 0:
printf(" 拜了个拜了您嘞! \n");
break;
case 1:
printf("****** 扫雷游戏 ******\n");
game(11, 11, 9, 9, 10);
break;
case 2:
printf("****** 扫雷游戏 ******\n");
game(18, 18, 16, 16, 40);
break;
case 3:
printf("****** 扫雷游戏 ******\n");
game(18, 32, 16, 30, 99);
break;
default:
printf(" 请输入有效数字 \n");
break;
}
} while (input);
}
void game(int Rows, int Cols, int Row, int Col,int Mine_count)//游戏
{
char mine[MaxSize][MaxSize] = { 0 };//初始化数组,一个用来存放雷的信息
char show[MaxSize][MaxSize] = { 0 };//初始化数组,一个用来存放排雷的信息
InitPanel(mine, Rows, Cols, '0');初始化雷的棋盘,实参传给形参,就是这里的括号里面的东西传到函数括号里的东西
InitPanel(show, Rows, Cols, '*');//初始化玩的棋盘
setMine(mine, Row, Col, Mine_count);//设置雷
//PrintPanel(mine, Row, Col);
PrintPanel(show, Row, Col);//设置完成后打印出来
checkMine(mine, show, Row, Col,Mine_count);//查雷,需要两个棋盘配合起来
}
int main()
{
srand((unsigned int)time(NULL));
test();
return 0;
}
这里的函数分别是菜单、入口、游戏。
总结
这次的扫雷游戏比上次写的猜数游戏难度大了许多,但是也提升了不少,通过实现这个扫雷游戏能
让你对数组、循环、分支以及函数的理解再往前一步,我也是敲了两遍才慢慢理解,但还是有所欠
缺。如果你们有兴趣的话可以自己动手试试喔。