C语言扫雷游戏(下)
整个工程的框架出来之后,这篇文章来对实现整个流程进行实现。
一、游戏正式开始前的准备工作:打印一个菜单——menu函数,并且让玩家顺利进入游戏
1.展示一个游戏最初始的界面
2.用switch语句来服务用户的选择再合适不过
到此为止,我们就可以安心去设计game()函数的内容了
二、执行游戏的步骤
1.先初始化两个棋盘,包括mine棋盘(用于布置雷)和show棋盘(用于展示给玩家看)
2.把show棋盘打印在屏幕上供玩家进行操作
3.在mine数组里面布置雷
4.玩家扫雷
由此不难看出游戏执行需要四个关键的函数
(1)初始化棋盘的函数:
`void InitializeBoard(char board[ROWS][COLS], int rows, int cols, char set)
(2)打印棋盘的函数:
void DisplayBoard(char arr[ROWS][COLS],int row,int col)
(3)布置雷的函数:
void SetMine(char arr[ROWS][COLS],int row,int col)
(4)玩家进行扫雷操作的函数:
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS])
下面对这四个函数进行逐一分析设计
三、game()内部设计,实现整个游戏的功能
1.初始化棋盘
(1)逻辑:用两重for循环遍历二维数组mine的所有元素,全部初始化为‘0’;同理遍历show数组的是所有元素,全部初始化为‘*’。
(2)具体代码实现
//初始化棋盘
void InitializeBoard(char arr[ROWS][COLS], int rows,int cols,char set)
{
int i = ROWS;
int j = COLS;
for (i = 0; i < ROWS; i++)
{
for (j = 0; j < COLS; j++)
{
arr[i][j] = set;
}
}
}
2.布置雷
(1)逻辑:我们的目的是在ROW行,COL列的数组当中布置雷。那么rand()%ROW+1就可以产生1~ROW的数字,rand()%COL+1就可以产生1-COL的数字,这两个数字一组合就是一个随机的坐标值,判断一下是不是‘0’,如果是的话就可以初始化为1,雷就布置下去了。
(2)此外,还有必要设置雷的个数,每布置一个雷这个数字就减1,直到布置完为止,这里采用count来接收雷的个数。
(3)在头文件中可以定义雷的个数如:#define EASY_COUNT 10//布置雷的时候计数用的,此处表示雷的个数是10(可任意修改)
(4)具体代码实现
//布置雷:生成十个随机的坐标,布置十个雷
void SetMine(char arr[ROWS][COLS],int row,int col)
{
int count = EASY_COUNT;
int x = ROW;
int y = COL;
while (count)
{
int x = rand() % ROW + 1;
int y = rand() % COL + 1;
if (arr[x][y] = '0')
{
arr[x][y] = '1';//布置一个雷
count--;
}
}
}
3.打印棋盘
(1)逻辑:与初始化棋盘的函数相似,用两重循环遍历整个数组即可,注意换行符的处理,美观起见可以先打印行号和列号。
(2)具体代码实现
//打印棋盘
void DisplayBoard(char arr[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
4.玩家扫雷
(1)逻辑:玩家输入的坐标有三种可能性:踩雷(mine里面的数字1);没踩雷(mine里面的数字0);坐标错误(不符合ROW行,COL列),分别对这三种情况进行处理即可。先对玩家输入坐标的合法性进行判断,合理则进入第1,2种情况,不合理则进入第3种情况
(2)踩雷/没踩雷:判断mine[x][y]是否等于‘1’,如果是的话就踩雷,不是的话就没踩雷
(3)坐标错误:让玩家重新输入
(4)具体代码实现
//辅助排查雷函数FindMind,统计周围雷的个数
int GetMineCount(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 FindMine(char mine[ROWS][COLS],char show[ROWS][COLS])
{
int x = 0;
int y = 0;
int win = 0;//记录玩家排查掉的无雷格子个数
while (win < ROW * COL - EASY_COUNT)//ROW*COL-EASY_COUNT是无雷格子的个数
{
printf("请输入要排查的坐标(行,列)(只用输入两个数字,中间用空格隔开):");
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= ROW) && (y >= 1 && y <= COL))//判断坐标的有效性
{
if (mine[x][y] == '1')//踩雷
{
printf("很遗憾,你被炸死了\n");
printf("请看雷都在哪里?0表示没有雷,1表示有雷\n");
DisplayBoard(mine, ROW, COL);//让玩家看一下雷都在哪里
break;
}
else//没踩雷,统计雷的个数
{
int count = GetMineCount(mine, x, y);//统计该点周围8个格子当中雷的个数
show[x][y] = count + '0';//把int数字转为字符:int= char+'0'
system("cls");//清理屏幕
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐标输入错误,请重新输入");
}
}
if (win == ROW * COL - EASY_COUNT)
{
printf("恭喜你!排雷成功\n");
DisplayBoard(mine, ROW, COL);//让玩家看一下雷都在哪里
}
}
game.h
//此文件写游戏需要的数据类型和函数声明等
#define ROW 9//真正有雷数组的行
#define COL 9//真正有雷数组的列
#define ROWS 11//整个大棋盘的行
#define COLS 11//整个大棋盘的列
#define EASY_COUNT 10//布置雷的时候计数用的,此处表示雷的个数是10(可任意修改)
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void menu();//菜单
void InitializeBoard(char arr[ROWS][COLS], int rows,int cols, char set);//初始化棋盘
void DisplayBoard(char arr[ROWS][COLS], int rows, int cols);//打印棋盘
void SetMine(char arr[ROW][COL], int row, int col);//布置雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS]);//排查雷
test.c
//此文件写游戏的测试逻辑
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h";
void menu()//菜单
{
printf("**********************\n");
printf("********1.play********\n");
printf("********0.exit********\n");
printf("**********************\n");
}
void game()//完成扫雷游戏
{
char mine[ROWS][COLS];//存放布置好的雷
char show[ROWS][COLS];//展示排查出雷的信息
InitializeBoard(mine, ROWS, COLS,'0');//mine数组全部初始化为‘0’
InitializeBoard(show, ROWS, COLS, '*');//show数组全部初始化为‘*’
SetMine(mine, ROW, COL);//布置雷
DisplayBoard(show, ROW, COL);//打印棋盘
FindMine(mine,show,ROWS,COLS);//排查雷
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("-------扫雷游戏-------\n");
game();//运行扫雷游戏
break;
case 0:
printf("游戏结束\n");
break;
default:
printf("选择值错误,请重新选择:\n");
}
} while (input);
return 0;
}
game.c
//此文件写游戏中函数的实现
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h";
//初始化棋盘
void InitializeBoard(char arr[ROWS][COLS], int rows,int cols,char set)
{
int i = ROWS;
int j = COLS;
for (i = 0; i < ROWS; i++)
{
for (j = 0; j < COLS; j++)
{
arr[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char arr[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
//布置雷:生成十个随机的坐标,布置十个雷
void SetMine(char arr[ROWS][COLS],int row,int col)
{
int count = EASY_COUNT;
int x = ROW;
int y = COL;
while (count)
{
int x = rand() % ROW + 1;
int y = rand() % COL + 1;
if (arr[x][y] = '0')
{
arr[x][y] = '1';//布置一个雷
count--;
}
}
}
//辅助排查雷函数FindMind,统计周围雷的个数
int GetMineCount(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 FindMine(char mine[ROWS][COLS],char show[ROWS][COLS])
{
int x = 0;
int y = 0;
int win = 0;
while (win < ROW * COL - EASY_COUNT)
{
printf("请输入要排查的坐标(行,列)(只用输入两个数字,中间用空格隔开):");
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= ROW) && (y >= 1 && y <= COL))//判断坐标的有效性
{
if (mine[x][y] == '1')//踩雷
{
printf("很遗憾,你被炸死了\n");
printf("请看雷都在哪里?0表示没有雷,1表示有雷\n");
DisplayBoard(mine, ROW, COL);//让玩家看一下雷都在哪里
break;
}
else//没踩雷,统计雷的个数
{
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';//把int数字转为字符:int= char+'0'
system("cls");
DisplayBoard(show, ROW, COL);
win++;
}
}
else
{
printf("坐标输入错误,请重新输入");
}
}
if (win == ROW * COL - EASY_COUNT)
{
printf("恭喜你!排雷成功\n");
DisplayBoard(mine, ROW, COL);//让玩家看一下雷都在哪里
}
}