在9*9的矩阵中,随机布置10个(或自定义个)炸弹,由玩家输入坐标进行扫雷,如果该坐标没雷,并且该坐标八方皆没有雷,那么我们就对该坐标进行展开,并继续判断该坐标的八方是否有雷。若该坐标没雷,但八方有雷,我们就在棋盘上提示玩家该坐标附近有几颗雷。玩家可以对认为有雷的坐标进行标记,若标记满10个,则可以提示程序判断输赢,若标记的坐标都有雷,则胜利;若标记的坐标有不存在雷的,则失败;
先制作一个菜单,供玩家进行游戏的选择
若玩家选择play则进入game()函数进行游戏
//菜单
void menu()
{
printf("**************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("**************************\n");
}
void Test()
{
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);
}
int main()
{
Test();//三子棋游戏测试
return 0;
}
我们需要创建两个二维数组来进行操作。一个(mine)用来存放雷,用0表示无雷,1表示雷,游戏过程中不展示给玩家;另一个(show)用来让玩家进行扫雷,初始时用*覆盖
创建两个数组时行和列都得是11,这方便我们后面在进行展开及判断周围雷的数目时的函数运算;
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void BoardInit(char board[ROWS][COLS],int rows,int 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;
}
}
}
我们创建的二维数组是11*11的,但是实际上我们需要展示给玩家的棋盘只有9 * 9;所以我们打印时需要省略掉最外围(上下左右各一行/列)的行和列
void BoardPrint(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);//提示玩家坐标列数
}
printf("\n");
for(i=1;i<=row;i++)
{
printf("%d ",i);//提示玩家坐标行数
for(j=1;j<=col;j++)
{
printf("%c ",board[i][j]);
}
printf("\n");//每隔一行就换行
}
printf("----------扫雷游戏-----------\n");
}
雷的位置是随机的,所以我们需要用到rand(),srand(),time()函数。
设置的雷存放在mine数组中
设置雷的数量
#define EAZY_COUT 10
void BoardSet(char mine[ROWS][COLS],int row,int col)//只需要将雷存放在玩家所能看到的9*9棋盘中便可
{
int cout = EAZY_COUT;
while(cout)
{
int x = rand() % row + 1;//炸弹坐标从 1 -> 9
int y = rand() % col + 1;
if(mine[x][y] == '0')//避免在相同坐标下设置雷
{
mine[x][y] = '1';//用1表示炸弹
cout--;
}
}
}
玩家输入排雷坐标,若该坐标有雷,则游戏结束;若该坐标无雷,则判断该坐标八方的雷的个数并将其输入到棋盘上提醒玩家;
如果没有被炸死,那么在排完一次雷后,我们就对是否胜利进行判断,如果排满除了有炸弹的坐标外,就算胜利
void BoardFind(char mine[ROWS][COLS],char show[ROWS][COLS])//排雷过程
{
int x = 0;
int y = 0;
int cout = 0;//已排查过的坐标个数
int win_ret = 0;//用来接收是否胜利的返回值
while(1)
{
printf("请输入要排雷的坐标\n");
scanf("%d %d",&x,&y);
if(x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if(mine[x][y] == '1')
{
printf("很遗憾你被炸死了\n");
break;
}
else
{
int ret = ShowThunder(mine,x,y) + '0';//将数字转变为对应的字符
show[x][y] = ret;
system("cls");//每扫一次雷进行一次清屏
cout++;//每次排雷让排查的坐标个数加1
win_ret = is_win(cout,ROW,COL);
}
}
else
{
printf("输入坐标无效,请重新输入\n");
}
if(win_ret)
{
printf("恭喜你,扫雷成功\n");
break;
}
}
}
int ShowThunder(char mine[ROWS][COLS],int x,int y)//检测八方的雷的个数
{
int i = 0;
int j = 0;
int sum = 0;
for(i=-1;i<=1;i++)
{
for(j=-1;j<=1;j++)
{
if(j == 0 && i == 0)
{
continue;
}
else
{
sum += mine[x+i][y+j];//将除原本坐标外的八个方向的字符对应的ASCII码加起来
}
}
}
return sum - 8 * '0';//'1' - '0' == 1,若有8个雷则返回8;返回存在的雷的个数
}
int is_win(int cout,int row,int col)
{
int ret = row * col;
if(cout == ret - EAZY_COUT)
{
return 1;
}
return 0;
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void game()
{
char mine[ROWS][COLS] = {
0 };//用来存放雷的 --> 0表示无雷,雷用1表示
char show[ROWS][COLS] = {
0 };//显示给玩家看的
BoardInit(mine, ROWS, COLS, '0');//全部初始化为0,表示无雷
BoardInit(show, ROWS