我们来梳理一下基本的思路
首先打印一个菜单是必不可少的
1.埋雷
首先我们要埋下我们的雷,所以我们得创建一个数组去埋雷.
2.打印棋盘
打印棋盘之前我们创立一个数组,再把埋雷数组的信息发送给棋盘数组,这样我们就能统计棋子周围雷的数量
3.判断输赢
扫到雷即为输,扫完除雷外所有位置即为赢
创建完这些文件,我们可以更轻松的去完成扫雷。
一个好的菜单能让这个游戏看起来更高级更人性化,实现它很简单
然后我们来写选择之后的反馈
void test(void)
{
int input = 0;
do
{
menu();
printf("请输入你要输入的值\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始玩游戏\n");
game();
break;
case 0:
printf("程序正在退出\n");
Sleep(1000);
break;
default:
printf("你输入的值有误请重新输入\n");
break;
}
} while (input);
}
相信很多人会问为什么要设置一个‘0’为退出选项,看到那个while函数是不是瞬间就明白了,0表示假,输入直接退出循环。
然后我们把他写到主函数中
int main()
{
srand((unsigned int)time(NULL));//后文提到,先不管
test();
return 0;
}
(以上内容都在test.c中实现逻辑会清晰很多. )
在打印棋盘之前,我们是不是得先初始化棋盘。
void Initboard(char mine[ROWS][COLS], int rows, int cols, char set)
{
int x = 0;
int y = 0;
for (x = 0; x < rows; x++)
{
for (y = 0; y < cols; y++)
{
mine[x][y] = set;
}
}
}
(上文说了在game.c中完成大部分函数的定义)
再在test.h中使用它
但别忘了创建数组哦。
第一个细节就是两个源文件中都必须包含头文件
#include"game.h"
第二个细节是定义行ROWS和列COLS
看靠边的这一行,如果我们定义成9*9的棋盘,在统计雷的过程中,我们的逻辑是不是去统计它周围一圈的雷,但是最后一行怎么办,这样统计不是数组越界了吗,所以我们定义一个11*11的棋盘,为的就是不让数组越界,我们可以直接在头文件中定义,方便修改
第三个细节是伴随第二个细节产生的,我们定义了11*11的棋盘,但是我们是不是只用9*9就可以了,所以我们还得定义两个数。
用来放棋子
函数代码如下
void printfboard(char mine[ROWS][COLS], int rows, int cols)
{
int x = 0;
int y = 0;
printf("----------扫雷---------\n");
for (x = 0; x <= rows; x++)
{
printf("%d ",x);
}
printf("\n");
for (x =1; x <= rows; x++)
{
printf("%d",x);
for (y = 1; y <= cols; y++)
{
printf(" %c", mine[x][y]);
}
printf("\n");
}
}
埋雷这里的细节还是很多啊,读者们请耐心体会一下啊
rand()是生成随机数的用它%rows(9)生成的是0-8的数,我们加上1生成1-9的数,是不是正好就是我们棋子的范围,我们还得在主函数中应用另一个函数
srand((unsigned int)time(NULL));
我们在生成随机数是数是随机生成的,所以我们是不是得判断这个地方是不是已经有雷了。有雷你还埋,雷的数量不就减少了吗。
到了本文最难的地方了,我也在坚持写,你们也要坚持看哦!!!!!
我们要把埋雷的数组信息给到排查雷,我们就得弄一个函数,把它两都传进来建立联系
Makesets(show, mine, row, col);
我们先来梳理一下
我们有三种情况 1.点到雷(直接炸死不解释)2.不是雷但周围有雷(统计并反馈数字)3.周围无雷
除雷外全部棋子被点完才算赢
我们先上代码再去解释
void Makesets(char show[ROWS][COLS], char mine[ROWS][COLS],int rows,int cols)
{
//int count = col * row - EASY;
int x = 0; int y = 0;
int count;
while (1)
{
count = wincount(show, row, col);
if (count == EASY)
{
break;
}
printf("请输入你的坐标-->");
scanf_s("%d %d", &x, &y);
int ret = Getnumber(mine, x, y);
printf("\n");
if ((x >= 1 && x <= rows) && (y >= 1 && y <= cols))
{
if (mine[x][y] == '1')
{
printf("很遗憾你被炸死了\n");
printfboard(mine, row, col);
break;
}
if (mine[x][y] != '1')
{
show[x][y] = ret + '0';
}
if (show[x][y] == '0')
{
lockline(show, mine, x, y);
}
printfboard(show, row, col);
}
else
{
printf("你输入的坐标非法请重新输入\n");
}
}
if(count==EASY)
printf("恭喜!!!!你获得了胜利\n");
}
很清晰的看到上面有棋子的三种不同情况
我定义了一个函数去统计雷的个数Getnumber
int Getnumber(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');
}
我来说一下之前为什么用字符‘0’和‘1’去当雷呢,就是为了好统计
我利用了一个函数lockline,是想这样
当周围无雷的时候,我是不是直接把周围也没有雷的棋子展开了,
所以定义了这个函数
void lockline(char show[ROWS][COLS],char mine[ROWS][COLS],int x,int y)
{
show[x][y] = Getnumber(mine, x, y) + '0';
if (show[x][y] == '0')
{
show[x][y] = ' ';
int i = 0;
int j = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (x + i > 0 && y + j > 0 && x + i <= row && y + j <= col&&show[x+i][y+j]=='*')
{
lockline(show, mine, x+i, y+j);
}
}
}
}
}
我用了一个递归来实现,思路是周围都是‘0’我就递归出去,碰到数字我就递归回来,并且把‘0’全部换成了空格,像这样
限制就是:是不是字符‘0’;
接下来是判断输赢
输不用解释
赢:是不是我得把所有不是雷的棋子全部扫完就算赢,所以我只要统计‘*’的个数,如果个数是雷的个数我就赢了
int wincount(char show[ROWS][COLS], int rows, int cols)
{
int i = 1;
int j = 1;
int count = 0;
for (i = 1; i<=rows; i++)
{
for (j = 1; j<=cols;j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count;
欧克全部完成
直接放代码把
void game(void)
{
//初始化布置雷与排查雷的棋子
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
Initboard(mine, ROWS, COLS, '0');
Initboard(show, ROWS, COLS, '*');
//打印棋盘
//printfboard(mine, row, col);
printf("\n");
printfboard(show, row, col);
//形成棋子(埋雷与统计雷)
printf("\n");
//埋雷
Minemine(mine,row,col);
printfboard(mine, row, col);
//统计雷并制造棋子
Makesets(show, mine, row, col);
}
接下来是全部的源码(供参考)
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include"game.h"
void game(void)
{
//初始化布置雷与排查雷的棋子
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
Initboard(mine, ROWS, COLS, '0');
Initboard(show, ROWS, COLS, '*');
//打印棋盘
//printfboard(mine, row, col);
printf("\n");
printfboard(show, row, col);
//形成棋子(埋雷与统计雷)
printf("\n");
//埋雷
Minemine(mine,row,col);
printfboard(mine, row, col);
//统计雷并制造棋子
Makesets(show, mine, row, col);
}
void menu(void)
{
printf(" 游戏菜单\n");
printf("*************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("*************************\n");
}
void test(void)
{
int input = 0;
do
{
menu();
printf("请输入你要输入的值\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("开始玩游戏\n");
game();
break;
case 0:
printf("程序正在退出\n");
Sleep(1000);
break;
default:
printf("你输入的值有误请重新输入\n");
break;
}
} while (input);
}
int main()
{
srand((unsigned int)time(NULL));
test();
return 0;
}
#include
#include
#define EASY 10
#define ROWS 11
#define COLS 11
#define row ROWS-2
#define col COLS-2
void Initboard(char mine[ROWS][COLS],int rows,int cols, char set);
void printfboard(char mine[ROWS][COLS],int rows,int cols);
void Minemine(char show[ROWS][COLS], int rows, int cols);
void Makesets(char show[ROWS][COLS],char mine[ROWS][COLS],int rows,int cols);
#include
#include"game.h"
#include
#include
#define _CRT_SECURE_NO_WARNINGS 1
int wincount(char show[ROWS][COLS], int rows, int cols)
{
int i = 1;
int j = 1;
int count = 0;
for (i = 1; i<=rows; i++)
{
for (j = 1; j<=cols;j++)
{
if (show[i][j] == '*')
{
count++;
}
}
}
return count;
}
void lockline(char show[ROWS][COLS],char mine[ROWS][COLS],int x,int y)
{
show[x][y] = Getnumber(mine, x, y) + '0';
if (show[x][y] == '0')
{
show[x][y] = ' ';
int i = 0;
int j = 0;
for (i = -1; i <= 1; i++)
{
for (j = -1; j <= 1; j++)
{
if (x + i > 0 && y + j > 0 && x + i <= row && y + j <= col&&show[x+i][y+j]=='*')
{
lockline(show, mine, x+i, y+j);
}
}
}
}
}
int Getnumber(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 Initboard(char mine[ROWS][COLS], int rows, int cols, char set)
{
int x = 0;
int y = 0;
for (x = 0; x < rows; x++)
{
for (y = 0; y < cols; y++)
{
mine[x][y] = set;
}
}
}
void printfboard(char mine[ROWS][COLS], int rows, int cols)
{
int x = 0;
int y = 0;
printf("----------扫雷---------\n");
for (x = 0; x <= rows; x++)
{
printf("%d ",x);
}
printf("\n");
for (x =1; x <= rows; x++)
{
printf("%d",x);
for (y = 1; y <= cols; y++)
{
printf(" %c", mine[x][y]);
}
printf("\n");
}
}
void Minemine(char show[ROWS][COLS], int rows, int cols)
{
int count = EASY;
while(count)
{
int x = rand() % rows + 1;
int y = rand() % cols + 1;
if (show[x][y] == '0')
{
show[x][y] = '1';
count--;
}
else
{
continue;
}
}
}
void Makesets(char show[ROWS][COLS], char mine[ROWS][COLS],int rows,int cols)
{
//int count = col * row - EASY;
int x = 0; int y = 0;
int count;
while (1)
{
count = wincount(show, row, col);
if (count == EASY)
{
break;
}
printf("请输入你的坐标-->");
scanf_s("%d %d", &x, &y);
int ret = Getnumber(mine, x, y);
printf("\n");
if ((x >= 1 && x <= rows) && (y >= 1 && y <= cols))
{
if (mine[x][y] == '1')
{
printf("很遗憾你被炸死了\n");
printfboard(mine, row, col);
break;
}
if (mine[x][y] != '1')
{
show[x][y] = ret + '0';
}
if (show[x][y] == '0')
{
lockline(show, mine, x, y);
}
printfboard(show, row, col);
}
else
{
printf("你输入的坐标非法请重新输入\n");
}
}
if(count==EASY)
printf("恭喜!!!!你获得了胜利\n");
}