目录
一、游戏介绍
《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
二、成品预览
选择菜单 ,进入游戏
输入坐标,进行排雷
不是雷,继续排
踩到雷了,游戏结束,打印雷的信息
三、设计思路
- 棋盘初始化
- 电脑随机放置雷
- 展示棋盘
- 排雷
- 展示周围雷的数目
- 展开一片
- 游戏输赢
- 完善游戏界面,打印菜单
四、游戏制作
- 设计 俩个数组
Myboard Showborad
Showboard数组用来展示玩家动作。
Myboard数组用于存放雷的信息。
- 规格为11*11
方便避免数组越界、统计周围雷的数目。
1)、初始化棋盘
memset函数(string.h)
快速设置数组元素
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
memset(board, set, sizeof(char) * rows * cols);
}
2)、电脑随机布置雷
标记‘0’为非雷,‘1’为雷
雷的位置,随机数生成。
rand生成随机数,调用rand函数,要先定义一次srand
注意:
随机布置雷,要布置在‘0’中
为了方便修改雷的数量,建议用宏定义雷的个数
void SetBoard(char board[ROWS][COLS], int row, int col)
{
int count = EASY;
while (count)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
3)、展示棋盘
为了方便识别,在9*9棋盘上,打印行、列信息。
void ShowBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
printf("**********扫雷游戏*********\n");
//Count(board, ROW, COL);
for (i = 0; i <= row; i++)
{
printf("%d", i);
for (j = 1; j <= col; j++)
{
if (i == 0)
printf(" %d ", j);
if(i>0)
printf(" %c ", board[i][j]);
}
printf("\n");
}
}
4)、获取周围雷的数目
统计周围8格的字符之和,
减去8个字符‘0’,得到雷的数目
在创建数组时,存放是字符
例如 Myboard的某一格周围有3个’1’,5个零,统计出 3*‘1’--8*‘ 0 ’,得到整数 3。
//计算周围八个格子雷数
int GetCount(char board[ROWS][COLS], int x, int y)
{
return board[x - 1][y - 1] + board[x][y - 1] + board[x + 1][y - 1]
+ board[x - 1][y] + board[x + 1][y] +
board[x - 1][y + 1] + board[x][y + 1] + board[x + 1][y + 1]
- 8 * '0';
}
5)、展开一片
玩家每次进行一次排雷(输入一次坐标),会检测Myboard周围8格的雷数目,如果雷不为0,在Showboard中的坐标点,显示雷的数目。
如果是0个雷,就显示成空白,同时每个坐标递归周围8格,为0就显示空白,直到为数字。就完成展开一片
void Open(char board[ROWS][COLS], char sboard[ROWS][COLS], int x, int y)
{
//检查合法性
if (x == 0 || y == 0 || x == ROWS - 1 || y == COLS - 1)
{
return;
}
if (sboard[x][y] != '*')
{
return;
}
//显示周围雷数
int count = GetCount(board, x, y);
if (count > 0)
{
sboard[x][y] = count + '0';
return;
}
//递归清除一片
else if (count == 0)
{
sboard[x][y] = ' ';
Open(board, sboard, x - 1, y - 1);
Open(board, sboard, x - 1, y);
Open(board, sboard, x - 1, y +1);
Open(board, sboard, x , y - 1);
Open(board, sboard, x , y + 1);
Open(board, sboard, x + 1, y - 1);
Open(board, sboard, x + 1, y );
Open(board, sboard, x + 1, y + 1);
}
}
6)、排雷&&判断输赢
判断输赢:
排到雷就为输
排完所有的非雷就为胜利
循环完成,每次排到一个非雷点,循环条件win标志++;直到win==非雷点
void Find(char board[ROWS][COLS],char sboard[ROWS][COLS] , int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win < row * col - EASY)
{
printf("输入坐标\n");
scanf("%d%d", &x, &y);
if (1 <= x && 9 >= x && 1 <= y && 9 >= y)//检查坐标合法性
{
if (sboard[x][y] == '*')//检查是否被排过
{
if (board[x][y] == '1')
{
printf("排到雷了,游戏结束\n");
ShowBoard(board, ROW, COL);
break;
}
Open(board, sboard, x, y);//展开一片
win++;
ShowBoard(sboard, row, col);
}
else
printf("坐标被排查过\n");
}
else
printf("坐标非法\n");
}
if (win == row * col - EASY)//排雷胜利条件
{
printf("排雷成功!\n");
ShowBoard(board, ROW, COL);
}
}
7)、菜单,模块化
打印一个简易菜单
将各个模块组装好
五、总结
当自己写了一次后,就不会感觉有多难了。
比较巧妙的思路在于设置俩个11*11的数组。
在排雷函数的实现,递归展开一片,要花点心思。
简易的小游戏,加深对数组的了解。
————编程没有捷径。