运用C语言知识,实现一个简单又好玩的扫雷游戏,整个代码不超过300行。
一、游戏规则
1.扫雷游戏通常由一个方形区域组成,被分成若干个小方格。
2.每个方格可能会有一个地雷,也可能没有。玩家需根据其他方格的状态来判断哪些方格是有雷的。
3.一开始,所有方格都是暗的,玩家需要挖开一些方格来了解游戏的状态。
4.当玩家挖开一个没有地雷的方格时,方格上会显示数字,这个数字代表着周围八个方格中有多少个是地雷。
5.玩家可以标记一些方格为有雷,以便在游戏过程中不会误挖到。
6.若玩家挖到了一个地雷,游戏就结束了。
7.直到玩家将所有没有地雷的方格挖开,只留下有地雷的方格,游戏胜利。
网页版扫雷游戏:https://www.minesweeper.cn/
二、功能分析
- 游戏菜单,玩家可选择开始游戏或退出游戏
- 系统布置棋盘,确定扫雷游戏的棋盘大小
- 系统布置雷,在棋盘中任意位置布置一定的雷
- 玩家排查雷,若位置不是雷,就显示周围有几个雷,直至所有非雷位置找出,游戏胜利;若位置是雷,就炸死,游戏结束。
游戏界面:
三、关键设计
(1)棋盘的布置
创建两个数组,一个数组用于存放系统布置的雷信息(字符0表示该位置无雷,字符1表示该位置有雷),一个数组用于显示玩家排查后的雷信息(若排查坐标有雷,则游戏结束;无雷,则计算该坐标周围8个位置的雷数)。
(2)棋盘边缘处位置的雷排查
对创建的两个数组进行两行两列的增加,避免排查雷时数组越界的出现。
(3)坐标周围雷数的计算
当排查坐标(x,y)不为雷时,计算该坐标周围8个位置的雷数量:有雷为字符1,无雷为字符0,则周围8个位置都减去一个字符0的值的和即可得到雷的数量。
注:字符1的ASCALL码值为49,字符0的ASCALL码值为48
四、实现代码
本次扫雷游戏的实现,通过多文件的形式完成。其中,源文件用于实现和测试扫雷游戏的功能逻辑,头文件则用于存放扫雷游戏中各类型变量和函数使用的声明等。
test.c // 该文件用于测试扫雷游戏的功能逻辑
game.c //该⽂件用于实现扫雷游戏的各函数功能
game.h //该文件用于存放扫雷游戏中各类型变量和函数使用的声明等
各文件具体实现代码:
game.h(存放扫雷游戏需要的变量和函数声明等 )
// 存放扫雷游戏需要的变量和函数声明等
#include <stdio.h> // printf函数所需头文件
#include <stdlib.h> // rand函数所需头文件
#include <time.h> // time函数所需头文件
#define COUNT_Mine 10
#define ROW 9
#define COL 9
#define ROWS 11
#define COLS 11
void Menu(); // 菜单函数
void Game(); // 游戏函数
// 初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int rows, int cols);
//布置雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//计算排查坐标周围的雷数
int GetMineCount(char mine[ROWS][COLS], int x, int y);
game.c(存放扫雷游戏各函数的具体实现 )
#define _CRT_SECURE_NO_WARNINGS 1
// 存放扫雷游戏各函数的具体实现
#include "game.h" // 引入扫雷游戏的头文件
// Menu()函数,菜单
void Menu() {
printf("************************\n");
printf("***** 扫雷游戏 *****\n");
printf("************************\n");
printf("***** 1.Start game *****\n");
printf("***** 2.Exit game *****\n");
printf("************************\n");
}
// Game()函数,游戏
void Game() {
char mine[ROWS][COLS]; // 存放雷的信息
char show[ROWS][COLS]; // 显示雷的信息
// 初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS, '*');
// 布置雷
SetMine(mine, ROW, COL);
// 打印棋盘
DisplayBoard(show, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
// 打印棋盘
// DisplayBoard(mine, ROW, COL);
// DisplayBoard(show, ROW, COL);
}
// InitBoard(),初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) {
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
// DisplayBoard(),打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
printf("************************\n");
printf("***** 扫雷游戏 *****\n");
printf("************************\n");
// 棋盘列坐标
for (int i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i); // 棋盘行坐标
for (int j = 1; j <= col; j++)
{
// 棋盘值
printf("%c ",board[i][j]);
}
printf("\n");
}
printf("---------------------------\n");
}
//布置10个雷
void SetMine(char board[ROWS][COLS], int row, int col) {
int count = COUNT_Mine;
while(count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (board[x][y] == '0') {
board[x][y] = '1';
count--;
}
}
}
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x, y; // 定义坐标
int win = 0; // 排查的非雷数
while (win < row*col-COUNT_Mine) {
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 if (show[x][y] != '*') {
printf("该坐标已排查,请重新输入!\n");
}
else {
int count = 0;
count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, row, col);
win++;
}
}
else {
printf("输入坐标有误,请重新输入!\n");
}
}
if (win == row * col - COUNT_Mine)
{
printf("恭喜你,排雷成功!\n");
DisplayBoard(mine, ROW, COL);
}
}
// 计算排查坐标周围的雷数
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
int count = 0;
count = 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';
return count;
}
test.c(测试扫雷游戏的逻辑)
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h" // 引入扫雷游戏的头文件
// 测试扫雷游戏的逻辑
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
Menu();
printf("请选择>");
scanf("%d", &input);
if (input == 1) {
Game();
}
else if (input == 2)
{
printf("游戏结束!\n");
break;
}
else
{
printf("输入有误,请重新选择!\n");
}
} while (input!=2);
return 0;
}
参考代码:https://gitee.com/zuiltd/c-language/commit/79975b459040fea543f65e432cdc3985baefb031