扫雷很经典的游戏了,具体玩法就不在赘述,本篇是简易实现一下扫雷游戏。
为了方便增删查改需要把代码分模块管理。
1.game.h \\头文件,游戏代码的声明(函数声明、符号定义)
2.game.c \\游戏代码的实现
3.test.c \\测试游戏逻辑
还是把最基本的逻辑写一下,首先至少玩一把,上来就需要打印个菜单(1玩0退出),用do while循环,并且做相应的提示(菜单)让玩家选择,仔根据做出的选择做出响应,这时可以使用switch语句来实现:
void menu()
{
puts("************************");
puts("****** 1.play ******");
puts("****** 0.exit ******");
puts("************************");
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请输入选项:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
puts("Exit the game!");
break;
default:
puts("input again!");
}
} while (input);
return 0;
}
效果无误,在case 1中封装game()函数来实现游戏功能:
void game()
{
char mine[ROWS][COLS] = { 0 };
//布置雷的数组
char show[ROWS][COLS] = { 0 };
//存放排查出雷的信息
//初始化两个数组为指定的内容
//mine数组在没有布置雷使初始化为'0'
initBoard(mine, '0');
//show数组在没有排查雷的时候初始化为*
initBoard(show, '*');
//打印雷盘信息
//displayboard(mine);
//打印展示给玩家的信息
displayboard(show);
}
扫雷需要两个数组,一个是用来存放雷,另一个是把雷隐藏起来的页面,把第二个数组输出来供玩家使用:
void displayboard(char board[ROWS][COLS])
{
puts("-------扫雷------");
printf(" ");
for (int i = 1; i < 10; i++)
{
printf("%d ", i);
}
printf("\n");
puts(" -----------------");
for (int i = 1; i <= ROW; i++)
{
printf("%d ", i);
printf("|");
for (int j = 1; j <= COL; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
puts("\n-------扫雷------");
}
上面只是测试代码有没有问题,实际上是不需要打印雷盘信息的,只需要打印给玩家第二个看就可以了。
紧接着需要在面板上设置雷了:
随机生成雷的坐标,只要对应的坐标是空,就设置。
void mineSet(char board[ROWS][COLS], int row, int col)
{
int mines = MINES;
while (mines)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
mines--;
}
}
}
ps:别忘了把雷隐藏,只打印玩家信息图
雷布置好后,接下来就是排查九宫格中雷的数量,并显示在当前坐标上,如何计算当前坐标雷的数量呢?
只需要找到周围八个坐标的下标,判断是否等于’1’
,如果相等就+1,最后把结果返回去,就是雷的数量:
//把页面和排查的坐标作为参数
int countMine(char mine[ROWS][COLS], int i, int j)
{
int sum = 0;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (mine[x+i][y+j] == '1')
{
sum++;
}
}
}
return sum;
}
因为是输出的是字符,所以加上’0’的ASCII码值的结果就是那个数字字符了。
void searchMines(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 - MINES)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x > 0 && x < 10 && y>0 && y < 10)
{
if (show[x][y] != '*')
{
puts("此坐标已被排查!");
}
else
{
if (mine[x][y] == '1')
{
puts("\n你被炸死了!");
displayboard(mine);
break;
}
else
{
//只要成功下棋就增加一步
win++;
//统计mine数组中xy坐标周围八个格子里有几个雷
show[x][y] = countMine(mine, x, y) + '0';
displayboard(show);
}
}
}
else
{
puts("非法坐标,重新输入!");
}
}
if (win == row * col - MINES)
{
puts("\n游戏胜利!");
displayboard(mine);
}
}
游戏结束的条件是,那这个9*9的格子来说,当走的次数等于row乘以col-雷的数量时,说明已经雷已经被排查完,游戏结束,因此循环判断条件是row * col - MINES。
test.c:
#include "game.h"
void menu()
{
puts("************************");
puts("****** 1.play ******");
puts("****** 0.exit ******");
puts("************************");
}
void game()
{
char mine[ROWS][COLS] = { 0 };
//布置雷的数组
char show[ROWS][COLS] = { 0 };
//存放排查出雷的信息
//初始化两个数组为指定的内容
//mine数组在没有布置雷使初始化为'0'
initBoard(mine, '0');
//show数组在没有排查雷的时候初始化为*
initBoard(show, '*');
//设置雷
mineSet(mine, ROW, COL);
//打印雷盘信息
displayboard(mine);
//打印展示给玩家的信息
displayboard(show);
//排查雷数
searchMines(mine, show, ROW, COL);
}
int main()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
printf("请输入选项:");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
puts("Exit the game!");
break;
default:
puts("input again!");
}
} while (input);
return 0;
}
game.c:
#include "game.h"
//初始化
void initBoard(char board[ROWS][COLS], char set)
{
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
board[i][j] = set;
}
}
}
//打印数据
void displayboard(char board[ROWS][COLS])
{
puts("---------扫雷--------");
printf(" ");
for (int i = 1; i < 10; i++)
{
printf("%d ", i);
}
printf("\n");
puts(" -----------------");
for (int i = 1; i <= ROW; i++)
{
printf("%d ", i);
printf("|");
for (int j = 1; j <= COL; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
puts("\n---------扫雷--------");
}
//设置雷
void mineSet(char board[ROWS][COLS], int row, int col)
{
int mines = MINES;
while (mines)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
mines--;
}
}
}
void boom(char show[ROWS][COLS], int i, int j)
{
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
show[x + i][y + j] = ' ';
}
}
}
int countMine(char mine[ROWS][COLS], int i, int j)
{
int sum = 0;
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (mine[x+i][y+j] == '1')
{
sum++;
}
}
}
return sum;
}
//排查雷
void searchMines(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 - MINES)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x > 0 && x < 10 && y>0 && y < 10)
{
if (show[x][y] != '*')
{
puts("此坐标已被排查!");
}
else
{
if (mine[x][y] == '1')
{
puts("\n你被炸死了!");
displayboard(mine);
break;
}
else
{
win++;
//统计mine数组中xy坐标周围八个格子里有几个雷
char c = countMine(mine, x, y) + '0';
if (c == '0')
{
void boom(show, x, y);
}
show[x][y] = c;
displayboard(show);
}
}
}
else
{
puts("非法坐标,重新输入!");
}
}
if (win == row * col - MINES)
{
puts("\n游戏胜利!");
displayboard(mine);
game.h:
#include
#include
#include
#define ROWS 11
#define COLS 11
#define ROW ROWS-2
#define COL COLS-2
#define MINES 10
//初始化数组
void initBoard(char board[ROWS][COLS], char set);
//显示数组
void displayboard(char board[ROWS][COLS]);
//布置雷
void mineSet(char board[ROWS][COLS], int row, int col);
//排查雷
void searchMines(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
以上就是扫雷的简易实现,很多功能待完善,待我在研究研究!