一、游戏说明
首先打开游戏界面会出现一个扫雷区,有三种扫雷区可供选择,各扫雷区的扫雷难度依次递增
初级:81个方块,10个雷(这里实现的是初级版的扫雷)
中级:256个方块,40个雷
高级:480个方块,99个雷
玩法
扫雷游戏的规则非常简单:
挖开地雷(即点到设置成为雷的方块),被炸,游戏结束。
挖开空方块,可以继续玩。
挖开数字,则表示在其周围的八个方块中共有多少个雷,可以使用该信息推断能够安全单击附近的哪些方块。
玩游戏过程中的情况如下:
二、游戏设计步骤
1.创建菜单
2.创建和初始化游戏扫雷区
3.设置雷的位置
4.打印出扫雷区
5.开始扫雷
三、代码实现
1.创建菜单
规定输入 1 为玩游戏,输入 0 为退出游戏
void menu()
{
printf("****************************\n");
printf("******** 1.play ********\n");
printf("******** 0.exit ********\n");
printf("****************************\n");
}
2.创建和初始化游戏扫雷区
首先创建雷区需要两个二维数组
- Mine[ROWS][COLS] 用来存储布置雷区的信息,不会显示出来
- Show[ROWS][COLS] 用来显示出扫雷游戏过程中的数据
- InitBoard(char board[ROWS][COLS], int rows, int cols,char set)函数用来初始化游戏界面
- InitBoard(Mine, ROWS, COLS,‘0’) 函数将Mine数组中每个元素全部初始为字符 ‘ 0 ’
- InitBoard(Show, ROWS, COLS, ‘*’) 函数将Show数组中的每个元素全部初始化为 ‘ * ’
void InitBoard(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;
}
}
}
3.设置雷
利用随机数产生机制(若不明白随机数的产生,可以看:如何生成随机数)在数组 Mine[ROWS][COLS] 中随机产生所需个数的雷,规定字符 ‘ 1 ’ 为雷,字符 ‘ 0 ’,不为雷
void SetMine(char Mine[ROWS][COLS], int row, int col)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (Mine[x][y] == '0')
{
Mine[x][y] = '1';
count--;
}
}
}
4.打印扫雷区
同理,相应的Mine数组或者Show数组传入
DisplayBoard(char board[ROWS][COLS], int row, int col) 函数中就可实现对应界面的打印
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
int j = 0;
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
5.扫雷
FineMine(char Mine[ROWS][COLS], char Show[ROWS][COLS], int row, int col) 为扫雷函数
首先输入要排雷的坐标,若坐标合法,则排雷
当被排的坐标为雷是,则被炸;若不是雷,则在此坐标显示周围的雷数
显示雷数的函数为Get_mine_count(char Mine[ROWS][COLS], int x, int y)
当排完所有雷后,则排雷成功
static int Get_mine_count(char Mine[ROWS][COLS], int x, int y)
{
return Mine[x - 1][y - 1] +
Mine[x - 1][y] +
Mine[x - 1][y + 1] +
Mine[x][y - 1] +
Mine[x][y + 1] +
Mine[x + 1][y - 1] +
Mine[x + 1][y] +
Mine[x + 1][y + 1] - 8 * '0';
}
void FineMine(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 (Mine[x][y] == '1')
{
printf("此坐标为雷,轰!被炸啦!\n");
DisplayBoard(Mine, row, col);
break;
}
if (Mine[x][y] == '0')
{
int count = Get_mine_count(Mine, x, y);
Show[x][y] = count + '0';//因为Show数组为字符数组,所以数
//字元素在内存中以ASCII码存储
//count+'0'就可将该位置用字
//符数字的形式表示出来
DisplayBoard(Show, row, col);
win++;
}
}
else
{
printf("坐标不合法,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
}
}
以上是各各步骤函数的具体实现,而为了方便,我们将代码分为三个文件:
1.game.h------关于游戏相关的函数声明,符号声明及头文件的包含
2.game.c------游戏相关函数的实现
3.test.c------测试游戏的逻辑
game.h
说明:当扫雷的坐标为扫雷区的边缘时,为了方便打印扫雷区边缘上坐标附近雷的数目,这里设置的实际上的数组比显示出来的数组要“大上一圈”,即上下多一行,左右多一列
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9//显示出来的行数
#define COL 9//显示出来的列数
#define ROWS ROW+2//未了方便统计雷的数目,实际上扫雷区的行数
#define COLS COL+2//实际上扫雷区的列数
#define EASY_COUNT 10//设置雷的数目
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
void DisplayBoard(char board[ROWS][COLS], int row, int col);
void SetMine(char Mine[ROWS][COLS], int row, int col);
void FineMine(char Mine[ROWS][COLS],char Show[ROWS][COLS], int row, int col);
game.c
#include"game.h"
void InitBoard(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;
}
}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
int j = 0;
for (i = 1; i <= row; i++)
{
printf("%d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void SetMine(char Mine[ROWS][COLS], int row, int col)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (Mine[x][y] == '0')
{
Mine[x][y] = '1';
count--;
}
}
}
static int Get_mine_count(char Mine[ROWS][COLS], int x, int y)
{
return Mine[x - 1][y - 1] +
Mine[x - 1][y] +
Mine[x - 1][y + 1] +
Mine[x][y - 1] +
Mine[x][y + 1] +
Mine[x + 1][y - 1] +
Mine[x + 1][y] +
Mine[x + 1][y + 1] - 8 * '0';
}
void FineMine(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 (Mine[x][y] == '1')
{
printf("此坐标为雷,轰!被炸啦!\n");
DisplayBoard(Mine, row, col);
break;
}
if (Mine[x][y] == '0')
{
int count = Get_mine_count(Mine, x, y);
Show[x][y] = count + '0';
DisplayBoard(Show, row, col);
win++;
}
}
else
{
printf("坐标不合法,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功!\n");
}
}
test.c
#include"game.h"
void menu()
{
printf("****************************\n");
printf("******** 1.play ********\n");
printf("******** 0.exit ********\n");
printf("****************************\n");
}
void game()
{
char Mine[ROWS][COLS] = { 0 };
char Show[ROWS][COLS] = { 0 };
InitBoard(Mine, ROWS, COLS,'0');
InitBoard(Show, ROWS, COLS, '*');
SetMine(Mine, ROW, COL);
//DisplayBoard(Mine, ROW, COL);
printf("--------扫雷----------\n");
DisplayBoard(Show, ROW, COL);
printf("--------扫雷----------\n");
FineMine(Mine, Show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择>:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("扫雷\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("请重新输入\n");
break;
}
} while (input);
return 0;
}
四、运行效果
简易版的扫雷游戏就此完成!