首先来谈谈我的设计思路,扫雷这个游戏其实就是棋盘中放雷和非雷,玩家需要将非雷单位全部找出,一旦选中雷,游戏就会结束。于是我就创立了两个二维数组,分别存放雷的信息以及显示给玩家的信息(毕竟如果让玩家看到雷的位置,这个游戏就失去意义了)。
1.打印菜单
2.初始化棋盘
3.玩家下棋
4.判断玩家是否踩雷以及实现扫雷的展开功能
5.游戏结束
由于代码量过大,我分装了game.h和game.c以及test.c三个源文件。
这个功能非常简单,我就不过多赘述了。代码如下:
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("##############\n");
printf("####1.start###\n");
printf("####0.exit####\n");
printf("##############\n");
}
void game()
{
char show[ROWS][COLS] = { 0 };
char real[ROWS][COLS] = { 0 };
Initial(show, ROWS, COLS, '*');
Initial(real, ROWS, COLS, '0');
set_mine(real, ROW, COL);
display(show, ROW, COL);
find_mine(real, show, ROW, COL);
}
int main()
{
int n = 0;
do
{
menu();
scanf("%d", &n);
switch (n)
{
case 0:
printf("退出成功。\n");
break;
case 1:
game();
break;
default:
printf("输入错误,请重试。\n");
break;
}
}while (n);
return 0;
}
我将字符‘ 1 ’视为雷,字符‘ 0 ’视为非雷。这个initial函数中的形参 char ch为初始化的字符。代码如下:
void Initial(char arr[ROWS][COLS], int row, int col, char ch)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = ch;
}
}
}
打印函数的实现用多个个for循环搞定,代码如下:
```c
void display(char arr[ROW][COL], int row, int col)
{
int i, j;
//为了玩家方便找到坐标,打印了列数。
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 ", arr[i][j]);//打印棋盘内容。
}
printf("\n");
}
}
紧接着我们就来实现放置雷的函数,代码如下:
void set_mine(char arr[ROW][COL], int row, int col)
{
int count = easy_count;//放置雷的个数
while (count)
{
int x = rand() % row + 1;//随机生成范围内的数字。
int y = rand() % col + 1;
if (arr[x][y] == '0')//判断该坐标是否含有雷,若无雷,就放置一个。
{
arr[x][y] = '1';
count--;//放置成功,雷数自减一。
}
}
}
效果图
ps:为了展示效果,我们将放置雷的棋盘打印出来,但在游戏中不会打印。
该部分共实现了三个功能
1.返回输入坐标附近的雷数
2.展开效果
3.判断游戏是否结束
首先我们来看判断函数,该函数实现了判断玩家是否踩雷,坐标是否合法,游戏是否结束等功能。代码如下:
void find_mine(char real_arr[ROW][COL],char arr[ROW][COL], int row, int col)
{
int count = row*col - easy_count;
int x, y;
while (count)
{
printf("请输入坐标。\n");
scanf("%d%d", &x, &y);//玩家输入坐标
if (x > 0 && x <= row && y > 0 && y <= col)//判断坐标是否合法
{
if (count == row*col - easy_count)
{
save(real_arr, arr, row, col, x, y);//防止玩家第一步踩雷
}
if (real_arr[x][y] == '1')//踩雷
{
printf("你被炸死了。\n");
break;
}
else if (real_arr[x][y] == '0')//未踩雷
{
count--;
arr[x][y] = get_mine(real_arr, x, y)+'0';//+‘ 0 ’为了将整形转变为字符型
/*open_mine(real_arr, arr, x, y, row, col);*/
open_mine(real_arr, arr, x, y,ROW,COL);
display(arr, ROW, COL);
}
}
else
printf("坐标错误,请重试。\n");
}
if (!count)
{
printf("游戏成功!\n");//当count为0时说明非雷单位全部排除
}
}
然后是返回雷数的函数:
int get_mine(char mine[ROW][COL], int x, int y)
{
return mine[x - 1][y - 1] - '0' + //减去‘ 0 ’为了将字符转变为整形。
mine[x - 1][y] - '0' +
mine[x - 1][y + 1] - '0' +
mine[x][y + 1] - '0' +
mine[x + 1][y + 1] - '0' +
mine[x + 1][y] - '0' +
mine[x + 1][y - 1] - '0' +
mine[x][y - 1] - '0';
}
接下来的函数利用递归实现了展开功能,递归条件为:
1.该坐标合法
2.该坐标非雷
3.该坐标为展开
代码如下:
void open_mine(char real_arr[ROW][COL], char show_arr[ROW][COL], int x, int y,int row,int col)
{
if (show_arr[x][y] == '*' && real_arr[x][y]!='1')
{
show_arr[x][y] = get_mine(real_arr, x, y) + '0';
}
if (show_arr[x - 1][y - 1] == '*' && real_arr[x - 1][y - 1] != '1' && x > 1 && y > 1)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x - 1][y] == '*' && real_arr[x - 1][y] != '1' && x > 1)
{
open_mine(real_arr, show_arr, x - 1, y, row, col);
}
if (show_arr[x - 1][y + 1] == '*' && real_arr[x - 1][y + 1] != '1' && x > 1 && y + 1 <col)
{
open_mine(real_arr, show_arr, x - 1, y + 1, row, col);
}
if (show_arr[x][y - 1] == '*' && real_arr[x][y - 1] != '1' && y > 1)
{
open_mine(real_arr, show_arr, x, y - 1, row, col);
}
if (show_arr[x][y + 1] == '*' && real_arr[x][y + 1] != '1' && y + 1<col)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x + 1][y + 1] == '*' && real_arr[x + 1][y + 1] != '1' && x + 1<row && y + 1<col)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x + 1][y] == '*' && real_arr[x + 1][y] != '1' && x + 1<row)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x + 1][y - 1] == '*' && real_arr[x + 1][y - 1] != '1' && x + 1<row && y - 1>0)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
}
#include
#include
#define easy_count 40
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void Initial(char arr[ROWS][COLS], int row, int col, char ch);
void set_mine(char arr[ROW][COL], int row, int col);
void find_mine(char real_arr[ROW][COL], char arr[ROW][COL], int row, int col);
void display(char arr[ROW][COL], int row, int col);
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()
{
printf("##############\n");
printf("####1.start###\n");
printf("####0.exit####\n");
printf("##############\n");
}
void game()
{
char show[ROWS][COLS] = { 0 };
char real[ROWS][COLS] = { 0 };
Initial(show, ROWS, COLS, '*');
Initial(real, ROWS, COLS, '0');
set_mine(real, ROW, COL);
display(show, ROW, COL);
find_mine(real, show, ROW, COL);
}
int main()
{
int n = 0;
do
{
menu();
scanf("%d", &n);
switch (n)
{
case 0:
printf("退出成功。\n");
break;
case 1:
game();
break;
default:
printf("输入错误,请重试。\n");
break;
}
}while (n);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void Initial(char arr[ROWS][COLS], int row, int col, char ch)
{
int i, j;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
arr[i][j] = ch;
}
}
}
void display(char arr[ROW][COL], int row, int col)
{
int i, j;
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 ", arr[i][j]);
}
printf("\n");
}
}
void set_mine(char arr[ROW][COL], int row, int col)
{
int count = easy_count;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
int get_mine(char mine[ROW][COL], int x, int y)
{
return mine[x - 1][y - 1] - '0' +
mine[x - 1][y] - '0' +
mine[x - 1][y + 1] - '0' +
mine[x][y + 1] - '0' +
mine[x + 1][y + 1] - '0' +
mine[x + 1][y] - '0' +
mine[x + 1][y - 1] - '0' +
mine[x][y - 1] - '0';
}
void open_mine(char real_arr[ROW][COL], char show_arr[ROW][COL], int x, int y,int row,int col)
{
if (show_arr[x][y] == '*' && real_arr[x][y]!='1')
{
show_arr[x][y] = get_mine(real_arr, x, y) + '0';
}
if (show_arr[x - 1][y - 1] == '*' && real_arr[x - 1][y - 1] != '1' && x > 1 && y > 1)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x - 1][y] == '*' && real_arr[x - 1][y] != '1' && x > 1)
{
open_mine(real_arr, show_arr, x - 1, y, row, col);
}
if (show_arr[x - 1][y + 1] == '*' && real_arr[x - 1][y + 1] != '1' && x > 1 && y + 1 <col)
{
open_mine(real_arr, show_arr, x - 1, y + 1, row, col);
}
if (show_arr[x][y - 1] == '*' && real_arr[x][y - 1] != '1' && y > 1)
{
open_mine(real_arr, show_arr, x, y - 1, row, col);
}
if (show_arr[x][y + 1] == '*' && real_arr[x][y + 1] != '1' && y + 1<col)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x + 1][y + 1] == '*' && real_arr[x + 1][y + 1] != '1' && x + 1<row && y + 1<col)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x + 1][y] == '*' && real_arr[x + 1][y] != '1' && x + 1<row)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
if (show_arr[x + 1][y - 1] == '*' && real_arr[x + 1][y - 1] != '1' && x + 1<row && y - 1>0)
{
open_mine(real_arr, show_arr, x - 1, y - 1, row, col);
}
}
void save(char arr1[ROW][COL], char arr0[ROW][COL], int row, int col,int x,int y)
{
if (arr1[x][y] == '1')
{
arr1[x][y] = '0';
while (1)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr1[x][y] == '0')
{
arr1[x][y] = '1';
break;
}
}
}
}
void find_mine(char real_arr[ROW][COL],char arr[ROW][COL], int row, int col)
{
int count = row*col - easy_count;
int x, y;
while (count)
{
printf("请输入坐标。\n");
scanf("%d%d", &x, &y);
if (x > 0 && x <= row && y > 0 && y <= col)
{
if (count == row*col - easy_count)
{
save(real_arr, arr, row, col, x, y);
}
if (real_arr[x][y] == '1')
{
printf("你被炸死了。\n");
break;
}
else if (real_arr[x][y] == '0')
{
count--;
arr[x][y] = get_mine(real_arr, x, y)+'0';
/*open_mine(real_arr, arr, x, y, row, col);*/
open_mine(real_arr, arr, x, y,ROW,COL);
display(arr, ROW, COL);
}
}
else
printf("坐标错误,请重试。\n");
}
if (!count)
{
printf("游戏成功!\n");
}
}
本人初学c语言,若有bug,还请大佬斧正。最后附上github链接:https://github.com/111q-33/clean_mine-sus.git