扫雷游戏可能大家都有玩过,今天我就用C语言来简单实现扫雷小游戏。
一. 游戏规则
扫雷就是要把所有非地雷的格子揭开即胜利;踩到地雷格子就算失败。游戏主区域由很多个方格组成。使用鼠标左键随机点击一个方格,方格即被打开并显示出方格中的数字;方格中数字则表示其周围的8个方格隐藏了几颗雷。
以上是扫雷的游戏规则,但我们自己实现时,也同样要遵循以上规则。
1.在定义棋盘的时候,定义9*9的棋盘,以二维数组来实现;
2.布雷时,'0'代表该位置没有雷, '1'代表该位置有雷(以'1'为代表有雷是为了方便之后计算所选周围雷的个数计算);
3.此版本只是简易版,不能像电脑上的扫雷游戏那样,可以一次排除点击位置附近所有没有雷的地方,只能一个一个去输入判断;
二. 扫雷的模拟实现
主要实现以下几个功能:
- 首先创建一个用户交互界面,方便进行游戏;
- 定义出显示棋盘,用来打印棋盘的状态。棋盘大小为9*9,以二维数组来定义棋盘;
- 定义出实际操作的棋盘界面,即用来实现埋雷、扫雷、计算所选位置雷数等功能的棋盘,该棋盘需要设置大小为11*11,这样方便后续对棋盘的操作;
- 初始化棋盘,显示棋盘全部初始化'*', 实际操作棋盘全部初始化为'0' ;
- 进行埋雷,我们设置雷的个数为10个,利用随即播种来随机生成雷的位置,将买雷的位置赋值为'1';
- 开始排雷,知道碰到雷or排除所有雷为止,游戏结束;
三. 各功能代码实现
3.1 创建用户交互界面
void menu()
{
printf("************************\n");
printf("***** 1.play ******\n");
printf("***** 0.exit ******\n");
printf("************************\n");
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
//扫雷
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("选择错误\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
3.2 初始化棋盘函数
//初始化棋盘
void InitBoard(char mine[ROWS][COLS], int rows, int cols, char set);
//初始化棋盘
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.3 打印棋盘
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);根据传入的不同棋盘来显示。
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
//1~9
int i = 0;
int j = 0;
//打印列号
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);//打印行号
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
3.4 进行埋雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
static 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';//由字符转数字
}
3.5 开始排雷
//排雷
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)//EASY_COUNT表示雷的个数
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾你被炸死了!\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
//计算x,y周围有几个雷
int n = get_mine_count(mine, x, y);
show[x][y] = n + '0';//由整数转变为字符
DisplayBoard(show, row, col);
win++;
}
}
else
printf("输入坐标非法,无法排雷,请重新输入\n");
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
四.扫雷的完整代码
4.1 main.c
//main.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 };//存放排查出雷的信息
//初始化mine数组全为'0'
InitBoard(mine, ROWS, COLS, '0');
//初始化show数组全为'*'
InitBoard(show, ROWS, COLS, '*');
//打印棋盘
//DisplayBoard(mine, ROW, COL);//显示雷
//DisplayBoard(show, ROW, COL);//显示初始棋盘
//布置雷
SetMine(mine, ROW, COL);
//DisplayBoard(show, ROW, COL);//显示棋盘
DisplayBoard(mine, ROW, COL);//显示雷的位置
//排雷
FindMine(mine, show, ROW, COL);
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
//扫雷
game();
break;
case 0:
printf("退出游戏\n");
break;
default :
printf("选择错误\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
4.2 game.c
//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)
{
//1~9
int i = 0;
int j = 0;
//打印列号
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
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 board[ROWS][COLS], int row, int col)
{
int count = EASY_COUNT;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
static 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)//EASY_COUNT表示雷的个数
{
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 0 && x <= row && y >= 0 && y <= col)
{
if (mine[x][y] == '1')
{
printf("很遗憾你被炸死了!\n");
DisplayBoard(mine, ROW, COL);
break;
}
else
{
//计算x,y周围有几个雷
int n = get_mine_count(mine, x, y);
show[x][y] = n + '0';//由整数转变为字符
DisplayBoard(show, row, col);
win++;
}
}
else
printf("输入坐标非法,无法排雷,请重新输入\n");
}
if (win == row * col - EASY_COUNT)
{
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
4.3.game.h
//game.h头文件
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//符号的声明
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
//函数的声明
//初始化棋盘
void InitBoard(char mine[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);