1.扫雷游戏制作框架
在写代码开始前,我们应该创建两个.c
文件,一个用来写游戏逻辑的代码,另一个用来写游戏的各个模块的代码,一个.h
文件用来声明函数的,把不同的模块放在不同的文件中,能够更好的展现出游戏代码的逻辑。
首先,我们应该创建一个棋盘,一个棋盘就行是一个平面坐标系,因此,我们应该创建二维数组的方式来模拟棋盘。在创建好二维数组之后,我们就可以对二维数组进行棋盘初始化。
之后,我们就可以来布置雷,布置雷可以采用生成随机数的方法来,生成雷的坐标位置,然后雷布置好之后就可以排除雷了,具体细节请向下翻阅。
2.游戏主函数的实现
在代码开始前创建两个.c
文件,一个.h
文件。
例如:
在文件test.c
中写主函数。
int main()
{
return 0;
}
我们把我们需要包含的头文件方在.h
文件中,方便使用。
#include<stdio.h>
在test.c
文件中我们就需要引入头文件了。
#include"game.h"
int main()
{
return 0;
}
之后我们需要的头文件都可以放在game.h
文件中,需要时,直接引用#include"game.h"
就可以使用了。
在主函数中,我们可以使用do ...while();
来循环游戏;封装一个表示游戏菜单的函数,因为菜单并不是游戏的核心部分,因此不必放在game.c
文件中;
例如:
#include"game.h"
void menu()
{
printf("****************\n");
printf("*** 1 . play ***\n");//选择1,代表玩游戏;选择0,则代表推出游戏。
printf("*** 0 . exit ***\n");
printf("****************\n");
}
int main()
{
int input = 0;//创建变量,来存放用户的选择
do
{
menu();//游戏菜单,供用户选择玩游戏,还是退出游戏
printf("请选择:>\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("玩游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入错误,请重新输入\n");
}while(input);//如果用户输入的是1,游戏将会再次循环,如果用户输入的是0,游戏将会停止。
return 0;
}
在大体写出了游戏框架后,应该简单测试一下,以免后面出现多个错误时,来重新检查。
3.初始化棋盘
首先需要创建两个二维数组,用于存放数据,一个数组主要用来存放布置雷的信息,另一个数组用来存放排除雷的信息,两个二维数组的联合使用,能够更好的提高代码效率。
存放布置雷信息的二维数组里面应该存放字符类型的的数据,在棋盘中,我们可以用'0';
来表示不是雷,用'1';
表示雷;存放排除雷信息的二维数组里面应该存放字符类型的的数据,初始化为'*'
来表示。
布置雷信息的二维数组
存放排除雷信息的二维数组
但是,这里有一个不方便的地方,那就是在排除雷的时候,要计算坐标附近的八个位置上是否有雷,如果坐标是(9,9),那我们应该如计算呢?因此,为墨门可以创建一个11*11的棋盘,方便后续的使用。
布置雷信息的二维数组
存放排除雷信息的二维数组
这里需要注意的是:为了方便的调整棋盘的大小,我们可以对二维数组的行和列使用#define
,为了方便使用棋盘的行和列,#define
应该放在game.h
文件中。
例如:在game.h
的头文件里
#define ROW 9
#define COL 9
#define EASY_COUNT 10
#define ROWS ROW+2
#define COLS COL+2
为了方便,我们可以先创建11*11的二维数组, 因为第九行的坐标周围在9*9的规格中不够八个坐标,无法方便的统计雷的个数,因此我们需要使用11x11的棋盘.
#include"game.h"
void menu()
{
printf("****************\n");
printf("*** 1 . play ***\n");//选择1,代表玩游戏;选择0,则代表推出游戏。
printf("*** 0 . exit ***\n");
printf("****************\n");
}
void game()
{
//定义二维数组
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
}
int main()
{
int input = 0;//创建变量,来存放用户的选择
do
{
menu();//游戏菜单,供用户选择玩游戏,还是退出游戏
printf("请选择:>\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("玩游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入错误,请重新输入\n");
}while(input);//如果用户输入的是1,游戏将会再次循环,如果用户输入的是0,游戏将会停止。
return 0;
}
初始化棋盘应该属于游戏的部分,因此,我们需要把初始化棋盘这一模块放在游戏函数game();
中。
void game()
{
//定义二维数组
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine,ROWS,COLS,'0');//两个数组初始化内容不同,为了方便,我们可以将初始化的内容传过去
InitBoard(show,ROWS,COLS,'*');
}
先在game()
函数中写出初始化棋盘的函数,函数的定义放在game.c
文件中,函数的声明放在game.h
文件中。
例如:
在game.h
文件中
//初始化棋盘函数的声明
void InitBoard(char board[ROWS][COLS],int rows,int cols,char set);
在game.c
文件中
//初始化棋盘函数的定义
void InitBoard(char board[ROWS][COLS],ROWS,COLS,char set)
{
int i = 0;
int j = 0;
for(i = 0;i < ROWS,i++)
{
for(j = 0;j < COLS;j++)
{
board[i][j] = set;
}
}
}
4.打印棋盘
在初始化棋盘后,为了检查棋盘是否初始化成功,我们可以创建一个函数来打印棋盘。
在game()
函数中
void game()
{
//定义二维数组
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine,ROWS,COLS,'0');//两个数组初始化内容不同,为了方便,我们可以将初始化的内容传过去
InitBoard(show,ROWS,COLS,'*');
DisplayBoard(mine,ROW,COL);//由于我们只想要展示9*9的棋盘,因此,我们需要使用ROW,COL
DisplayBoard(show,ROW,COL);
}
同样的,在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;
for(i = 1; i <= row;i++)
{
for(j = 1; j <= col;j++)
{
printf("%c ",board[i][j];
}
printf("\n");
}
}
为了使棋盘更加的好看,我们可以在打印棋盘的时候加上以下内容
例如:
void DisplayBoard(char board[ROWS][COLS],int row,int col)
{
int i = 0;
int j = 0;
printf("-----------扫雷----------\n);
for(i = 0; i <= row; i++)
{
printf("%d ",i);
}
for(i = 1; i <= row;i++)
{
printf("%d ",i);
for(j = 1; j <= col;j++)
{
printf("%c ",board[i][j];
}
printf("\n");
}
}
这样,我们的棋盘就布置好了。
5.布置雷
在初始化棋盘和打印棋盘之后,我们就需要来布置雷了,在布置雷的时候,我们生成随机数的函数rand()
,在使用这个函数之前,应该在主函数中添加srand()
,用来初始化随机数的生成器。
例如:
int main()
{
srand((unsigned int )time(NULL));
int input = 0;//创建变量,来存放用户的选择
do
{
menu();//游戏菜单,供用户选择玩游戏,还是退出游戏
printf("请选择:>\n");
scanf("%d",&input);
switch(input)
{
case 1:
printf("玩游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("输入错误,请重新输入\n");
}while(input);//如果用户输入的是1,游戏将会再次循环,如果用户输入的是0,游戏将会停止。
return 0;
这个时候,我们就可以布置雷了。
在game()
函数中
SetMine(mine,ROW,COL);
在game.h
文件中
void SetMine(char board[ROWS][COLS],int row,int col);
在game.c
文件中
void SetMine(char board[ROWS][COLS],int row,int col)
{
int x = 0;
int y = 0;
int count = EASY_COUNT;//为了使雷的数量容易更改,这里使用#define
while(count)
{
x = rand() % r0w + 1;
y = rand() % col + 1;
if(board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
这样,我们的雷就布置好了,我们可以打印一下布置好雷的棋盘
例如:
在game()
函数中
void game()
{
//定义二维数组
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine,ROWS,COLS,'0');//两个数组初始化内容不同,为了方便,我们可以将初始化的内容传过去
InitBoard(show,ROWS,COLS,'*');
//DisplayBoard(mine,ROW,COL);//由于我们只想要展示9*9的棋盘,因此,我们需要使用ROW,COL
//DisplayBoard(show,ROW,COL);
SetMine(mine,ROW,COL);
DisplayBoard(mine,ROW,COL);
}
结果如图:
6.排除雷
在排除雷的时候,我们需要在排除雷的函数中把两个二维数组传过去。如果在排除雷的过程大体会出现一下几种情况,一是用户坐标会输入错误;二是用户会输入存放了雷的坐标;三是用户会输入之前已经排查过的坐标;四是用户会输入正确的坐标,这时我们就应该打印棋盘,并在打印的棋盘中用户输入的坐标出显示出周围8个坐标雷的个数。
我们应该把计算一个坐标附近的雷的坐标个数封装成一个函数。
GetMineCount(mine,ROWS,COLS);
在game()
函数中,先设计排除雷的函数
FindMine(mine,show,ROW,COl);
在game.h
文件中声明该函数
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
void GetMineCount(char mine[ROWS][COLS],int rows,int cols);
在game.c
文件定义该函数
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
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");
DisplayBoard(mine, ROW, COL);//游戏结束后,打印放置雷的棋盘
break;
}
else
{
if(show[x][y] != '*')
{
printf("输入错误,请重新输入:>");
}
else
{
show[x][y] = GetMineCount(mine,x ,y ) + '0';//函数用来数周围8个坐标雷的个数
DisplayBoard(show, ROW, COL);//打印存放雷信息的棋盘
win++;
}
}
}
else
{
printf("输入非法坐标,请重新输入:>");
}
}
if(win == ROW * COL - EASY_COUNT)
{
printf("恭喜你,扫雷成功\n");
DisplayBoard(mine, ROW, COL);//游戏结束后,打印放置雷的棋盘
}
}
在计算坐标周围的雷的个数的时候,我们可以采用'1' - '0'
来表示;如果是雷的话,结果就为1,不是雷的话,结果为0。
在game.c
文件定义该函数
void GetMineCount(char mine[ROWS][COLS],int x,int y)
{
return mine[x - 1][y] + mine[x + 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 8*'0';
}
这样我们的扫雷游戏就大体写成了,为了检验最后成功的那一部分代码,我们可以把win = 0;
改成win = 70;
这样循环一次,如果没有踩到雷,就挑战成功了。