引言:
在前面一篇中,小编介绍了如何将代码分装在多个文件中的操作。在本篇文章中,小编将介绍一个广受欢迎的小游戏,以帮助大家熟悉这个操作。这个小游戏不仅可以让我们熟悉将代码放在多个文件中的操作,还可以加深我们对数组和函数的理解。快来和小编一起探索扫雷小游戏的乐趣吧!
C:将代码拆分放在多个文件的操作_c语言如何将一个文件的内容分成多个文件-CSDN博客
1、扫雷游戏的起源
扫雷游戏起源于1937年的“方块”游戏,1992年微软发布的Window3.1中加入了该游戏,从此风靡全球。玩扫雷游戏,可以锻炼你的观察和推理能力,培养细心和耐心。
2、畅玩扫雷游戏的设备
网页版的链接:扫雷游戏网页版 - Minesweeper
电脑:鼠标右键点击原始方块,以小旗标记为雷,再右键取消标记。标记的雷数和数字匹配时,点击数字(左右键均可)翻开周围的安全区域。鼠标左键带年纪无标记方块则直接打开。
手机或平板:再触屏上点击方块即标记为雷,再点去除标记。标记的雷数和数字匹配时,点击数字翻开周围的安全区域。长按方块直接打开。(可设置为点击直接打开,或者点击三次打开
关于安卓手机上连击放大问题:【设置】->【智能辅助】->【无障碍】->【放大手势】-关闭。(直接搜索放大手势关闭也可以)有的手机可能搜不到智能辅助。
3、简述一下游戏的设计
随机布置雷,第一次点击不是雷,格子里的数字表示它周围有几个雷(周围指已点击格子为中心,3*3的范围)游戏目标是找出所有雷。“触雷”则输。点击表情重新开始。二选一留到最后,可任选,需先清完其它方块。
简要逻辑实现:
在9*9的棋盘上
随机布置10个雷
排查雷,如果是雷,游戏结束,如果不是雷,就会显示周围有几个雷(图中数字就是显示该数字周围3*3的格子中有几个雷),当把所有不是雷的位置全部找出来,游戏就结束了,游戏胜利。
4、关于游戏代码分装
扫雷游戏大概一共200行代码,因此,我们将代码按照不同功能分装在三个文件中
test.c ------main函数,主要是来测试游戏的主逻辑
game.h ----- 函数的声明
game.c ------ 函数的实现
game.h和game.c是游戏实现的逻辑
5、棋盘的设计
完成扫雷游戏的运行,我们需要在 9*9 的棋盘上随机布置雷
我们需要将这些数据存放起来,存放数据我们要么使用变量,要么使用数组,这里我们需要存放的是9*9的棋盘,那么我们使用二维数组存放比较合适。
我们需要将布置的雷存放到棋盘中。可以假设数字1是雷。剩下不是雷的位置我们用0来表示。
当我们将雷布置完成后,我们需要排雷,那么该怎么排呢?
有没有发现什么问题?如果我们所要排的点周围雷有一个的情况下就会形成歧义
前面我们用1来表示雷,这里的1又用来排查出来周围雷的个数,这样在后面出现1的话究竟是表示什么呢?
既然如此,我们怎么避免这个问题呢?
我们可以在创建一个棋盘用来排查雷
布置雷的棋盘 排查出雷的信息
由于两个棋盘是一摸一样的,所以对应的位置是相同的。
到这里我们就可以解决信息拥挤或者歧义的情况,使用两个棋盘可以有效避免以一个棋盘上出现多种标识符,导致编写代码的时候出现紊乱。接下来还有一个问题。
还有一个问题,我们创建的数组该是什么类型的呢?
char board[11][11]
为什么使用字符数组呢?
因为我们对外所展示的是排查出的雷的信息的棋盘,布置好的雷的棋盘是隐藏的,这样的话当我们使用字符数组的时候,在未排查之前所展示的棋盘上每个位置都有*显示
主要是神秘。
6、代码的具体实现
6.1 menu函数设计
通过菜单来实现开始游戏,退出游戏等……选项
我们自定义一个函数menu来实现打印菜单
void menu()
{
printf("———— 1.play ————");
printf("———— 0.exit ————");
}
6.2 main函数设计
do…while循环用来实现游戏的开始和结束
int main()
{
int input = 0;
do
{
menu();
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
}
while (input);
return 0;
}
6.3 game函数的设计
首先需要实现棋盘的打印
通过棋盘的设计我们知道有两个字符数组,一个用来存放布置好的雷的信息,一个用来存放排查出雷的的信息,
char mine[11][11]; //用来存放布置好的雷的信息;
char show[11][11]; //用来存放排查出雷的的信息。
在mine 棋盘上,没有布置雷的时候,棋盘上显示的都是字符‘0'
在show 棋盘上,没有排查雷的时候,全部都是' * '。
6.4 InitBoard函数的设计
数组创建好后需要初始化,那应该怎么操作呢?
可以使用InitBoard函数来初始化
由于11大量的重复,后面再修改棋盘大小的时候比较麻烦,因此使用ROW 来表示行,COL来表示列,在game.h文件中定义:
#define ROW 9
#define COL 9#define ROWS ROW+2
#define COLS COL+2
char mine[ROWS][COLS]; //用来存放布置好的雷的信息;
char show[ROWS][COLS]; //用来存放排查出雷的的信息。
关于函数的声明我们都放到 game.h 文件中
void InitBoard(char board[ROWS][COLS], int row, int cot,char set);
函数的实现: (放在game.c中)
void InitBoard(char board[11][11], int row, int col,char set)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
}
6.5 DisplayBoard函数的设计
由于棋盘会不断打印,因此我们单独创建一个函数来打印棋盘。
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
DisplayBoard的声明我们放在game.h中
void DisplayBoard(char board[ROWS][COLS], int row, int col);
函数的实现:(放在game.c中)
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------扫雷------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);//打印行号
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
6.6 SetMine函数的设计
当棋盘打印完成后,我们需要布置雷,设计一个函数
SetMine(mine, ROW, COL);
函数的实现:(放在game.c中)
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = 10;
while (count)
{
//生成随机的下标
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] != '1');
{
board[x][y] = '1';
count--;
}
}
}
6.7 FindMine函数的设计
布置完雷后,我们开始排查雷
FindMine(mine, show, ROW, COL);
排查雷的声明:
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
这里面传ROW,COL是因为我们只需要排查9*9的棋盘即可
我们在mine棋盘排查,排查的数据放到show里面,排查的范围是9行9列
函数的实现:(放在game.c中)
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("请输入要排查的位置:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == "1")
{
printf("很遗憾,中招了\n");
DisplayBoard(mine, ROW, COL);
}
else
{
int c = GetMineCount(mine,x,y);
show[x][y] = c + '0';
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("输入坐标有误,重新输入\n:");
}
}
}
6.8 GetMineCount函数设计
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');
}
7、将代码分装到文件中
7.1 test.c文件
#include "game.h"
void menu()
{
printf("———— 1.play ————");
printf("———— 0.exit ————");
}
void game()
{
char mine[ROWS][COLS]; //用来存放布置好的雷的信息;
char show[ROWS][COLS]; //用来存放排查出雷的的信息。
//初始化数组
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()
{
int input = 0;
do
{
menu();
printf("请选择:\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
}
while (input);
return 0;
}
7.2 game.h
#include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘声明
void InitBoard(char board[11][11], int row, int col,char 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);
7.3 game.c
#include "game.h"
//实现初始化
void InitBoard(char board[11][11], int row, int col,char set)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = set;
}
}
}
//实现打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("------扫雷------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);//打印行号
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 = 10;
while (count)
{
//生成随机的下标
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] != '1');
{
board[x][y] = '1';
count--;
}
}
}
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 row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("请输入要排查的位置:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (mine[x][y] == "1")
{
printf("很遗憾,中招了\n");
DisplayBoard(mine, ROW, COL);
}
else
{
int c = GetMineCount(mine,x,y);
show[x][y] = c + '0';
DisplayBoard(show, ROW, COL);
}
}
else
{
printf("输入坐标有误,重新输入\n:");
}
}
结语:
还是决定更新一下,闲下来的时候没事做!