相信扫雷游戏大家肯定不陌生吧。小时候我以为这就是个运气游戏,运气好就不会踩到雷,长大之后才逐渐发现其中的规律。
1设计思路
a.棋盘设计
假设我们想要设计一个如下图所示的9×9的棋盘,那么相对应的我们就要设置一个9×9的二维数组。但要注意的是图中上面以2为中心点的方框,我们可以很好的排查它附近的雷,而下面以1为中心点的方框,我们排查它附近八个格子的时候就会产生数组越界。因此对于9×9的棋盘,我们的二维数组要开到11×11,最外围的一圈不设置雷,这样就不会造成越界访问了。
b.布置雷
在此次设计中,我将雷的位置设为1,非雷的位置设为0。这样设计也有一个缺陷,如下图所示蓝色的1代表其周围有一个雷,而红色的1代表雷的位置,我们人眼可以很清楚的区分它们的不同,但是编译器中这两个位置存储的都是1,无法区分蓝色1的地方是雷呢还是代表雷的个数。因此,我们就需要两个棋盘,一个棋盘用于布置雷(mine),另一个棋盘用于显示附近有多少雷(show)。
mine数组初始化为‘0’,布置雷的时候,改为‘1’;
show数组初始化为‘*’,排除雷后,具体位置改为数字字符 如:‘3’;
2具体实现
1)初始化数组
上面介绍过,mine数组刚开始初始化全’0‘,show数组刚开始初始化全’*‘。
//mine初始化全'0'
//show初始化全'*'
//init_board(mine, ROWS, COLS, '0');
//init_board(show, ROWS, COLS, '*');
void init_board(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;
}
}
}
2)打印棋盘
在打印的时候,给棋盘加上了行号和列好,以便进行识别。
//打印棋盘
//display_board(mine, ROW, COL);
//display_board(show, ROW, COL);
void display_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
//打印列号
for (j = 0; j <= col; j++)
{
printf("%d ", j);
}
printf("\n");
for (i = 1; i <= row; i++)
{
//打印行号
printf("%d ", i);
for (j = 0; j < col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
3)布置雷
由于雷的位置时随机生成的,因此使用了时间戳配合srand进行随机生成。
//srand((unsigned int)time(NULL));//利用时间戳生成随机数
void set_mine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
//设置坐标x y
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
4)排雷
排雷的关键就是要找到雷的位置,在此代码中多次使用了if语句嵌套来实现寻找雷的位置,并判断游戏是否胜利。
int get_mine_count(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
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 - EASY_COUNT)
{
printf("请输入要排查雷的坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
//坐标还没有被排查过
if (show[x][y] == '*')
{
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了\n");
display_board(mine, ROW, COL);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
display_board(show, ROW, COL);
win++;//统计排查成功的次数,达到一定次数后,游戏胜利
}
}
else
{
printf("坐标已被排查\n");
}
}
else
{
printf("非法坐标\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
display_board(mine, ROW, COL);
}
}
3运行结果
为了达到节目效果,在此次运行时,我在9×9的棋盘中设置了80个雷,并可以看到雷所在的位置坐标,以便我们快速的观察到游戏失败和游戏胜利的效果。
4总结
这是C语言实现的一个功能较为简单的程序,相比于网上的扫雷游戏,该程序还有很大的改进空间,大家也可以尝试将它改的更加智能一点。此次总体过程是快乐的,很享受解决每一个问题的过程,我盼望着有一天可以像那些大佬一样可以完全自己设计程序!