题目描述: 基于经典的扫雷游戏进行模拟,以二维数组模拟扫雷游戏的棋盘,棋盘规格为9*9,随机设置10颗地雷,输入坐标进行排雷,如果踩到地雷则输出相关信息”BOOM被炸死了QAQ“,
题目描述:
基于经典的扫雷游戏进行模拟,以二维数组模拟扫雷游戏的棋盘,棋盘规格为9*9,随机设置10颗地雷,输入坐标进行排雷,如果踩到地雷则输出相关信息”BOOM被炸死了QAQ“,本次游戏结束。若未踩中地雷,则输出提示信息,即以该坐标为中心其周围相邻的上、下、左、右、左上,右上,右下,左下八个方向共有多少颗地雷,根据提示信息继续排雷,递归实现安全区域展开,直至踩中地雷或者排出所有地雷,本次游戏结束。
实现逻辑:
- 初始化扫雷棋盘。
- 在棋盘1上随机坐标设置地雷。
- 棋盘2用作提示信息棋盘,本坐标处的值即以该坐标为中心其周围相邻的上、下、左、右、左上,右上,右下,左下八个方向共有多少颗地雷。
- 玩家输入坐标进行排雷。
- 递归实现周围无地雷区域大片展开功能。
一、游戏主界面
1.1 游戏界面显示
void menu()
{
printf("*************************************\n");
printf("************** 扫雷游戏 *************\n");
printf("*************************************\n");
printf("************** 1.PLAY ***************\n");
printf("************** 0.EXIT ***************\n");
printf("*************************************\n");
}
二、游戏开始准备
2.1 棋盘初始化和地雷设置
游戏开始前要初始化地雷棋盘,棋盘1用于设置地雷信息,利用相关函数产生十个随即坐标设置地雷,’1‘表示当前坐标放置地雷,’0‘表示当前坐标不放置地雷,棋盘2用于为玩家提示当前坐标周围地雷个数信息。
//棋盘初始化
//初始化
init(mine_info,ROWS,COLS, '0');
init(mine_check, ROWS, COLS, '*');
void init(char arr[ROWS][COLS], int row, int col, char c)
{
int i = 0, j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = c;
}
}
}
利用rand()函数、srand()函数产生十个随即坐标设置地雷。
void set_mine(char arr[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
int cnt = easy_mode_cnt;
while (cnt)
{
int x = rand() % 9 + 1;//取余限定产生坐标范围
int y = rand() % 9 + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
cnt--;
}
}
}
三、玩家扫雷
输入坐标扫雷,利用mine_check[]数组提示玩家坐标地雷信息。
void scan_mine(char mine_info[ROWS][COLS], char mine_check[ROWS][COLS])
{
int st = 0;
int x = 0, y = 0;
while (st<step)
{
printf("输入排雷坐标\n");
scanf("%d%d", &x, &y);
if (x<1 || x>ROW || y<1 || y>COL)
printf("坐标无效,请重新输入\n");
else
{
if (mine_info[x][y] == '1')
{
printf("BOOM!,很不幸,被炸死了QAQ\n");
break;
}
else if (mine_info[x][y] == '0'&&mine_check[x][y]=='*')
{
st += spread_(mine_info, mine_check, x, y);
show(mine_check, ROW, COL);
}
}
}
if (st == step)
printf("扫雷成功!GOOD!\n");
}
计算当前坐标与当前坐标相邻的九个坐标上的全部地雷数。
int count_mine(char arr[ROWS][COLS], int x, int y)
{
return arr[x - 1][y] + arr[x - 1][y - 1] + arr[x - 1][y + 1] + arr[x][y - 1] + arr[x][y + 1] + arr[x + 1][y - 1] + arr[x + 1][y] + arr[x + 1][y + 1] - 8 * '0';
}
安全区域展开:涉及到了递归的相关知识。
如果当前坐标上没有放置地雷,且其周围八个方向坐标上全部地雷数为0,则本坐标在棋盘2上的值设置为’ ‘,即代表安全区域,递归搜索当前坐标相邻的八个方向的坐标,如果count_mine(int,int)的值不为零则搜索下一个方向坐标,直至不满足条件递归结束。
int spread_(char mine_info[ROWS][COLS], char mine_check[ROWS][COLS], int x, int y)
{
int st = 0;
if (count_mine(mine_info,x,y) == 0&&x>0&&y>0&&y<=9&&x<=9)
{
mine_check[x][y] = ' ';
st++;
if (mine_check[x - 1][y - 1] == '*' && mine_info[x - 1][y - 1] == '0')
st+=spread_(mine_info, mine_check, x - 1, y - 1);
if (mine_check[x - 1][y] == '*' && mine_info[x - 1][y] == '0')
st += spread_(mine_info, mine_check, x - 1, y);
if (mine_check[x - 1][y + 1] == '*' && mine_info[x - 1][y + 1] == '0')
st += spread_(mine_info, mine_check, x - 1, y + 1);
if (mine_check[x][y + 1] == '*' && mine_info[x][y+1] == '0')
st += spread_(mine_info, mine_check, x, y + 1);
if (mine_check[x + 1][y + 1] == '*' && mine_info[x + 1][y + 1] == '0')
st += spread_(mine_info, mine_check, x + 1, y + 1);
if (mine_check[x + 1][y] == '*' && mine_info[x + 1][y] == '0')
st += spread_(mine_info, mine_check, x + 1, y);
if (mine_check[x + 1][y - 1] == '*' && mine_info[x + 1][y - 1] == '0')
st += spread_(mine_info, mine_check, x + 1, y - 1);
if (mine_check[x][y - 1] == '*' && mine_info[x][y - 1] == '0')
st += spread_(mine_info, mine_check, x, y - 1);
return st;
}
else if(x > 0 && y > 0 && y <= 9 && x <= 9)
{
mine_check[x][y] = count_mine(mine_info, x, y) + '0';
st++;
return st;
}
else
{
return 0;
}
}
四、游戏整体逻辑
void play()
{
//初始化
init(mine_info,ROWS,COLS, '0');
init(mine_check, ROWS, COLS, '*');
//展示
//show(mine_info, ROW, COL);
show(mine_check, ROW, COL);
//设置地雷
set_mine(mine_info, ROW, COL);
//show(mine_info, ROW, COL);
//排雷
scan_mine(mine_info, mine_check);
}
运行测试:
......
(安全区域大片展开)--递归实现
......
源码链接:扫雷(可实现安全区域展开) · 70aa3fa · qpy/C初阶 - Gitee.com