功能一:显示的棋盘
功能二:埋雷的棋盘
功能三:初始化棋盘
功能四:埋雷
功能五:显示棋盘
功能六:排雷
首先我们可以知道的是需要设计一个玩家看到的棋盘页面,棋盘上没有任何的显示。
这是一个9*9的网格,那么我们可以用一个二维数组来存放它。
char show [ROWS][COLS];
这里棋盘上的*就相当于上面棋盘上的方格。
那么我们只需要先在数组里每个元素都存放上‘*’然后再打印出来就可以完成这个设计。
我们可以把这个存放*的初始化函数记为
void Init (char arr[ROWS][COLS], int x,int y, char set);
void Init(char arr[ROWS][COLS], int x, int y, char set)
{
int i = 0, j = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
{
arr[i][j] = set;
}
}
}
这里的ROWS和COLS解释一下。我们打印的是一个9*9的棋盘,玩家输入坐标进行排雷,那么可以宏定义一下ROW、COL=9;
其次,扫雷游戏每扫一个空格,都会显示周围八个格子的雷数。
那么对于1-9这个格子来说,他的右边和上边是没有格子的,那么为了方便设计我们可以添加上一行一列的空格子。
那么也就是说实际上我们设计一个9*9的棋盘,要初始化一个11*11的二维数组,那么宏定义一个ROWS和COLS=ROW+2;
现在我们初始化显示给玩家的棋盘
Init(show,ROWS,COLS,'*');
这样子显示给玩家的棋盘内存放的都是*,打印出来也就是*;
接着我们还需要初始化一个雷盘,里面存放雷的位置,我们可以用数字1表示雷,数字0表示没有雷。
Init(board, ROWS, COLS, '0');
现在雷盘已经初始化完成,我们需要随即插入雷就完成了埋雷。
void Set(char arr[ROWS][COLS], int x, int y,int count)
这里count代表埋雷的数目,简单模式我们可以宏定义一下count=10;
void Set(char arr[ROWS][COLS], int x, int y,int count)
{
int i = 0, j = 0;
for (; count > 0;)
{
i = rand() % 9 + 1;
j = rand() % 9 + 1;
if (arr[i][j] == '0')
{
arr[i][j] = '1';
count--;
}
}
}
通过随机数生成横纵坐标,然后判断这个坐标有没有被埋过雷,如果没有的话就在这个坐标买入雷。
随机数模9生成的数是0-8,而我们的位置坐标是1-10,所以在余数+1就能得到需要的坐标范围。
我们这里打印的是显示给玩家的棋盘。
Display(show, ROW, COL);
一个9*9的棋盘然后在第一行前打印出来0-9,在第一列打印出来0-9,也就是需要打印一个10*10的网格。
void Display (char arr[ROWS][COLS], int x, int y)
{
int i = 0, j = 0;
printf("--------扫雷--------\n");
for (i = 0; i < 1; i++)
{
for (j = 0; j <= y; j++)
{
printf("%d ",j);
}
printf("\n");
}
for (i = 1; i <= x; i++)
{
printf("%d ",i);
for (j = 1; j <= y; j++)
{
printf("%c ",arr[i][j]);
}
printf("\n");
}
printf("--------扫雷--------\n");
}
排雷是整个游戏里面最主要的一部分,首先玩家输入想要排雷的坐标,然后对这个位置进行判断,
首先判断坐标输入是否合法,即1 如果arr[i][j]==‘1’,那么就证明这个位置是有雷的,那么这时候游戏就应该结束了,并且把埋雷的棋盘打印出来,告诉玩家哪里有雷。 如果arr[i][j]==‘0’,那么就证明这个位置没有雷,那么就应该把附近八个格子里面的雷数显示在这个格子里面,并且我们通过玩游戏可以知道,如果这个格子显示0的话,那么附近的格子也应该被扫出来。 就像如果我扫2-8这个位置附近都没有雷,那么它旁边就应该自动展开,这样子不仅方便玩家进行游戏,还能减少反复输入坐标进行排雷。 那么这里我们应该写一个函数,来计算周围八个格子里面到底有多少雷。 因为我们在雷盘里面存放的都是字符1和0,所以只需要把这些字符相加,再减去对应的字符0的个数,就能得到对应数字的值。 然后我们这里扫雷是一个循环的过程,达到胜利或者失败条件再跳出这个循环,所以我们可以在一个死循环下面去跑这个扫雷的过程。 现在我们需要一个胜利条件,去判断这局游戏是否赢了,否则即使我们排掉了全部的雷,循环还会继续运行。那么这个判断也很简单,我们可以想一下,如果排到最后,棋盘上只剩下10个‘*’,其余全部显示的是数字,那么我们只需要统计‘*’的个数,就可以这个是否赢下了这局游戏。 因为我们前面while的判断条件是a的值,所以我们在排雷一次以后就a = Win(show); 如果Win返回0的话,循环就会跳出,这时候就赢下了这局游戏。 这个代码还是有些地方没有完善,比如扫雷展开那里,一次最多展开九个格子,还不能像我们平常玩的那种一下子展开一片,这里还需要继续改进一下。另外如果想升级难度,只需要改变一下棋盘大小和雷数就可以,代码的移植性还是比较高的。雷数判断
int countsum(char arr[ROWS][COLS], int x, int y)
{
return arr[x - 1][y - 1] + arr[x - 1][y] + arr[x - 1][y + 1]
+ arr[x][y - 1] + arr[x][y] + arr[x][y + 1]
+ arr[x + 1][y - 1] + arr[x + 1][y] + arr[x + 1][y + 1]-9*'0';
}
中雷判断
void Mine(char show[ROWS][COLS], char board[ROWS][COLS], int x, int y, int set)
{
int row = 0, col = 0, count=x*y-set, sum=0, a=1;
while (a)
{
printf("请输入排雷坐标\n");
scanf("%d %d", &row, &col);
if (row >= 1 && row <= x && col >= 1 && col <= y)
{
if (board[row][col] == '1')
{
printf("很遗憾,排雷失败!!!\n");
Display(board, x, y);
break;
}
else
{
sum = countsum(board, row, col);
show[row][col] = sum+'0';
int i = 0, j = 0;
if (sum==0)
{
for (i = -1, j = -1; j < 2; j++)
{
show[row + i][col + j] = countsum(board, row + i, col + j)+'0';
if (board[row + i][col + j] == '1')
show[row + i][col + j] = '*';
}
for (i = 0, j = -1; j < 2; j++)
{
show[row + i][col + j] = countsum(board, row + i, col + j)+'0';
if (board[row + i][col + j] == '1')
show[row + i][col + j] = '*';
}
for (i = 1, j = -1; j < 2; j++)
{
show[row + i][col + j] = countsum(board, row + i, col + j)+'0';
if (board[row + i][col + j] == '1')
show[row + i][col + j] = '*';
}
}
Display(show, ROW, COL);
}
}
else
{
printf("输入错误,坐标非法");
}
}
}
赢家判断
int Win(char show[ROWS][COLS])
{
int i = 1, j = 1, z=0;
for(i=1;i<=ROW;i++)
{
for (j=1; j <=COL; j++)
{
if (show[i][j] == '*')
{
z++;
}
}
}
if (z != easycount)
{
return z;
}
else
return 0;
}
总结
#define _CRT_SECURE_NO_WARNINGS
#include