目录
前言:
前面两篇文章中,各位小伙伴们写出了自己在C语言写学习中的第一个小游戏井字棋,阿銮在这里恭喜各位小伙伴辣!本文我们将进行更加复杂的阶段编程练习——编写扫雷游戏。
一、文件建立:
同样的,我们在编写扫雷游戏时,也使用模块化开发的方式,将整段编程代码划分为game.h、game.c与test.c三个文件进行编写:
1.头文件game.h:
该文件用于包含宏与其它头文件,并存放功能实现函数的函数声明:
2.函数定义文件game.c:
该文件用于书写所有的程序功能实现的函数定义:
3.工程测试文件test.c:
该文件用于书写我们的程序主体部分:
二、编写井字棋游戏:
1.程序整体执行思路:
与之前写过的井字棋游戏整体执行思路相同,首先我们自定义两个函数,menu为菜单函数,负责向玩家打印游戏菜单;game为游戏函数,负责实现整个游戏的逻辑实现。当程序开始编译运行后,将会按照顺序,先执行menu函数打印出游戏菜单,接着执行game函数让玩家们进行游戏:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//游戏逻辑:
void game()
{
...
}
void test()
{
menu();
game();
...
}
int main()
{
test();
return 0;
}
同时,与井字棋游戏相同,大多数时候玩家往往会选择多次进行游戏,所以我们通过在数函数部分结合我们在之前介绍过的的循环和分支语句很容易实现该目的:
void test()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏...\n");
break;
default:
printf("输入错误,请重新选择!\n");
break;
}
} while (input);
}
这些步骤与井字棋游戏的整体运行逻完全相同,这里不再进行运行演示。
2.menu菜单:
与扫雷游戏相同,仅使用 printf 函数进行屏幕打印即可:
void menu()
{
printf("******************************\n");
printf("******************************\n");
printf("***** 欢迎来到扫雷游戏 *****\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("******************************\n");
printf("******************************\n");
}
且编译运行结果与井字棋相同,不再进行过多阐述。
3.game游戏函数逻辑:
(注:此处我们同样只关心实现逻辑,具体功能实现后面会逐一进行研究说明)
我们同样从扫雷游戏的游戏规则与胜利条件开始研究。扫雷游戏其本质为推理判断游戏,它有9×9标准游戏界面,在游戏开始时,所有方格中的内容将会被隐藏,玩家不清楚每个格子的内容,但在所有格子中,部分格子中被布置下了“地雷”,玩家需要在判断放个安全的情况下进行扫雷,在安全的格子上,若以该方格为中心的九宫格内有危险的“地雷”,该中心方格上将会显示中心九宫格内“地雷”的数量,玩家可以通过选择该位置来进行排雷,若判断失误,选择的位置上为“地雷”,则玩家输掉了该局游戏,直到玩家将全部的地雷全部排查出来,即可获得游戏的胜利。
梳理了游戏的规则,我们开始尝试编写该游戏。
在游戏函数中,首先我们进行棋盘的初始化。与井字棋游戏不同的是,在这里我们需要定义并初始化两个棋盘。需要两个棋盘原因是,我们对“安全”与“地雷”的区分将会使用到' 0 '和' 1 '两个字符,其中' 0 表示“安全”而' 1 '则表示“地雷”,如果我们仅仅只定义并初始化一个棋盘,当进行地雷判断时,我们将无法确定' 1 '是表示周围中心九宫格内地雷的数量还是表示该方格内为“地雷,造成我们对游戏情况判断的歧义”:
void game()
{
char mine[ROWS][COLS] = { 0 };
//存放布置的雷的信息
char show[ROWS][COLS] = { 0 };
//存放查出的雷的信息
}
接着我们对这两个棋盘进行初始化。mine数组中用于存放布置的地雷的信息,故首先将其全部初始化为“安全”,而show数组用于打印向玩家反馈当前扫雷情况,故刚开局时全部位置均未未知,初始化为象征性占位符' * ',并在棋盘初始化完成后将反馈棋盘show进行打印:
(mine数组中存放实际布雷信息,游戏实际为操作mine数组,show数组仅供反馈排雷情况使用)
void game()
{
char mine[ROWS][COLS] = { 0 };
//存放布置的雷的信息
char show[ROWS][COLS] = { 0 };
//存放查出的雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
}
在棋盘定义并初始化完成后,我们需要在我们定义的全“安全”棋盘中,放入一定数量随机位置的“地雷”:
(注:此处初始化与定义的棋盘,与进行实际操作的行与列不同,后文实现过程将会进行说明)
void game()
{
char mine[ROWS][COLS] = { 0 };
//存放布置的雷的信息
char show[ROWS][COLS] = { 0 };
//存放查出的雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
DisplayBoard(show, ROW, COL);
//布置雷
SetMine(mine, ROW, COL);
}
在放置好“地雷”后,就可以让玩家开始进行“扫雷”了:
void game()
{
//定义棋盘
char mine[ROWS][COLS] = { 0 };
//存放布置的雷的信息
char show[ROWS][COLS] = { 0 };
//存放查出的雷的信息
//初始化棋盘
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show,