1.设立菜单。里面要含有游戏的开始界面和后续的选择选项。2.结束一场游戏后再次询问是否继续游玩下去。3.选择了开始游戏后,控制台冒出一个雷盘,待扫的雷用*代替。4.雷盘的行row,列col均为10.5.每次扫一次雷,如果扫到雷则游戏结束,否则冒出周围以自己为中心的8颗待扫的雷中的真实雷数量。6.当雷全部被扫光,游戏结束。
我们可以用三个文件将代码分成三个模块。text.c文件包含我们菜单的主体逻辑。game.c则包含游戏实现的逻辑,game.h是头文件,包含子函数的声明和预处理。这三个文件可以使程序有条不紊,每个模块都有自己要做的事。接下来我们开始思考text.c文件。我们设置的菜单可以设成一个子函数Menu,每次调用子函数Menu则打印菜单。同理,设置的游戏也可以是子函数,每次调用函数则开始进行扫雷。
Menu()
{
printf("*****扫雷游戏*******\n");
printf("*****1.游戏开始******\n");
printf("*****0.退出**********\n");
printf("请输入你的选择\n");
}
接下来我们需要根据玩家输入的数字来设计接下来的子函数。如果玩家输入数字1,则开始游戏。如果玩家输入数字0则结束游戏。因为结束一场游戏后需要再次询问是否继续游玩下去,所以我们考虑到使用do while循环,因为do while循环的特点是先执行再判断是否进行循环,符合我们的程序设定。再根据我们需要玩家输入的数字来进行分支,所以我们考虑使用swtich结构,正好符合我们的程序设置。这里我们用一个子函数gameselect将我们讲的内容包在一起。do while的判断条件正好是用户输入的数字1或0(也恰好适合用来判断真或假。在c语言中0代表假,非0代表真)我们也需要考虑如果玩家不输入合法数字,我们就要考虑再加个default分支告诉玩家输入错误。
gameselect()
{
int selectnumber = 0;
scanf("%d", &selectnumber);
do {
switch (selectnumber)
{
case 1:
game();
break;
Menu();
case 0:
break;
defalut:
printf("输入不正确,请重新输入\n");
}
} while (selectnumber);
}
接下来我们再思考游戏的逻辑,即开始设计子函数game。我们可以定义两个雷盘,一个是打印给玩家的雷盘show,里面全是未排的雷。一个是真正的雷盘mine,里面包含雷的位置信息。show里面可以全装*,而mine可以先装字符0,再通过随机生成雷的技术将雷放进去。玩家在打印给玩家的雷盘show每排一个雷,我们就用真正雷盘上的位置来对比。由于两个雷盘的内容并不一样,我们又得设置一个函数用来初始化雷盘。我们可以设置一个函数Initboard,该函数可以通过参数来初始化雷盘。接下来我们得需要打印玩家所看见的雷盘show,它是玩家的游戏雷盘,这里可以用函数 Displayboard来打印它。两个雷盘初始化后我们就得考虑把雷放进去mine里面了。所以我们再设置一个函数Setmine,里面用来设置雷。既然雷放好了,我们就得考虑排雷了。所以我们再设置一个函数Finemine,里面装着对比雷盘的逻辑,即排雷的实现逻辑。这些子函数的传递都需要设立数组的参数,雷盘的行row,雷盘的列col来传递。
void game()
{
char show[ROWS][COLS];//定义展示给玩家的雷盘
char mine[ROWS][COLS];//定义实际上的真正的雷盘
Initboard(show, ROWS, COLS, '*');//初始化展示给玩家的雷盘
Initboard(mine, ROWS, COLS, '0');//初始化真正的雷盘
Displayboard(show, ROW, COL);//打印雷盘
Setmine(mine, ROW, COL);//放置雷
Findmine(mine, show, ROW, COL);//排查雷
}
game()的主体逻辑已经写完。接下来我们就要考虑game中的各个函数的实现逻辑了。我们把这四个函数放在game.c文件中。我们先考虑Initboard这个子函数,该函数主要是把两个雷盘给初始化,放进去想放的东西。所以我们就接受主函数传递的参数,通过数组的遍历,即for的嵌套将每个字符放进去数组即可。
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i <= rows; i++)
{
int j = 0;
for (j = 0; j <= cols; j++)
{
board[i][j] = set;
}
}
}
接下来则是Dispalyboard函数了,该函数用来打印玩家所看到的雷盘,里面需要遍布雷*。为了让玩家好确认雷的坐标,我们可以再雷盘上加个坐标。我们先在第一个for循环(即打印每一行的for循环)第一行,即i=0的时候打印数字123456789 10就可以在雷盘的上方显示列的坐标col。同理,我们在第二个for循环里面(即打印每雷盘的每一列的for循环)打印123456789 10,就可以显示雷盘的行row坐标。但打印col坐标的时候需要i=0开始,不然就把row坐标挤出去一个。
void Displayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("-------扫雷游戏---------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
接下来就是Setmine函数了。该函数主要把雷放进mine函数里面。我们可以通过rand,srand()这两个库函数实现伪随机算法,让雷‘1’随机放置。如果要放count个雷的数量,我们就可以用while循环,用count当做while的判断条件,直到count==0时while就会终止放雷‘1’。然后我们定义x,y(放置雷的坐标)用%来规定雷随机产生的位置,防止不在雷盘上。(如果不懂rand,srand,和%的作用可以去查阅资料)count_easy是后面宏定义的雷的数量
void Setmine(char mine[ROW][COL], int row, int col)
{
int count = count_easy;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
接下来是最后的函数,也是最重要的函数Finemine了。我们主要的逻辑是对比两个雷盘。如果在show数组中玩家排雷的位置在数组mine正好是雷,则游戏结束,排雷失败。否则则统计mine中该位置周围的雷数量。我们可以将雷盘设成数组,正好可以传达雷的坐标,即位置信息。我们可以定义玩家输入的坐标x,y,再可以定义排雷成功的条件win。如果win 直接返回该位置周围的雷的坐标即可,如果是雷有多少‘1’就有多少‘1’加在一起,不是雷就会加‘0’最后减去8个‘0’刚好就是雷的数量。将函数返回的数字加上字符‘0’就是字符中数字(这个数字恰好就是雷的数量)每排一颗雷就展示一遍show雷盘,与此同时排雷成功条件win++。这样一直循环,直到雷全部排完。当雷排完的数量等于空雷-雷的数量,我们就可以打印成功排雷了,然后把真正的雷盘打印给玩家看 这个时候我们再把所有函数所需要的声明,宏定义写在game.h这个头文件上。ROW,COL是行,列。ROWS,COLS,是为了防止数组溢出,数组实际的行列。 再把这些函数一调用就成为了主函数main(srand的使用和time函数的使用,不懂可以去查资料,翻阅其他的博客即可) text.c game.c game.h 希望看完这篇博客对你有所启发,我建议看过一遍后要自己动手思考写代码(这过程要全凭自己思考)一步一步实现,就能写出属于自己的不同于别人的代码。如有错误,还请指出!这里是しかし,我们下次再见!int Startistics(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + 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;
int win = 0;
while (win < ROW * COL - count_easy)
{
printf("请输入坐标\n");
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
{
int minenumber = Startistics(mine, x, y);
show[x][y] = minenumber + '0';
Displayboard(show, row, col);
win++;
}
}
else
{
printf("输入的坐标有误,请重新输入\n");
}
}
if (win == ROW * COL - count_easy)
{
printf("恭喜你成功排雷!");
Displayboard(mine, ROW, COL);
}
}
#pragma once
#include
int main()
{
srand((unsigned int)time(NULL));
Menu();//扫雷游戏介绍
gameselect();
return 0;
}
(三)代码的实现
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
Menu()
{
printf("*****扫雷游戏*******\n");
printf("*****1.游戏开始******\n");
printf("*****0.退出**********\n");
printf("请输入你的选择\n");
}
void game()
{
char show[ROWS][COLS];//定义展示给玩家的雷盘
char mine[ROWS][COLS];//定义实际上的真正的雷盘
Initboard(show, ROWS, COLS, '*');//初始化展示给玩家的雷盘
Initboard(mine, ROWS, COLS, '0');//初始化真正的雷盘
Displayboard(show, ROW, COL);//打印雷盘
Setmine(mine, ROW, COL);//放置雷
Findmine(mine, show, ROW, COL);//排查雷
}
gameselect()
{
int selectnumber = 0;
scanf("%d", &selectnumber);
do {
switch (selectnumber)
{
case 1:
game();
break;
Menu();
case 0:
break;
defalut:
printf("输入不正确,请重新输入\n");
}
} while (selectnumber);
}
int main()
{
srand((unsigned int)time(NULL));
Menu();//扫雷游戏介绍
gameselect();
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
for (i = 0; i <= rows; i++)
{
int j = 0;
for (j = 0; j <= cols; j++)
{
board[i][j] = set;
}
}
}
void Displayboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
printf("-------扫雷游戏---------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
int j = 0;
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void Setmine(char mine[ROW][COL], int row, int col)
{
int count = count_easy;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int Startistics(char mine[ROWS][COLS], int x, int y)
{
return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] + mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] + 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;
int win = 0;
while (win < ROW * COL - count_easy)
{
printf("请输入坐标\n");
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
{
int minenumber = Startistics(mine, x, y);
show[x][y] = minenumber + '0';
Displayboard(show, row, col);
win++;
}
}
else
{
printf("输入的坐标有误,请重新输入\n");
}
}
if (win == ROW * COL - count_easy)
{
printf("恭喜你成功排雷!");
Displayboard(mine, ROW, COL);
}
}
#pragma once
#include
(四)写后的话