引言:
在本篇博客中,我们将使用C语言实现一个经典小游戏——扫雷。扫雷游戏是一款受欢迎的益智游戏,目标是根据提示找出没有地雷的方格,避开地雷,同时逐步揭开整个雷区。通过本篇博客,我们将一步步介绍如何设计和实现这个扫雷游戏。
目录
1、 游戏规则
在开始之前,让我们先了解一下扫雷游戏的基本规则:
- 通过点击棋盘上的方格来进行探雷。
- 如果方格没有地雷,将显示周围八个方格中地雷的数量。
- 如果方格有地雷,游戏失败。
- 当玩家把除有地雷的方格外的所有方格都揭开,玩家胜利。
2、游戏整体框架
在我们开始编写具体代码之前,让我们先来了解扫雷游戏的整体框架。游戏主要分为以下几个功能模块:
2.1 初始化雷区
游戏开始时,会初始化一个9x9的雷区,同时随机布置一定数量的地雷。
2.2 显示游戏界面
游戏界面以表格形式呈现,玩家可以通过坐标输入来选择要翻开的格子。
2.3 翻开格子
玩家输入坐标后,游戏会判断该格子是否是地雷,如果是地雷,则游戏结束;如果不是地雷,则会显示周围地雷的数量。
2.4 递归展开
如果玩家选择了一个没有地雷并且周围地雷数为0的格子,游戏会自动展开周围的空格,并继续展开空格周围的空格,直到周围有地雷或边界为止。
2.5 判断胜利
游戏会统计翻开的格子数量,当所有不含地雷的格子都被翻开时,游戏胜利。
3、实现逻辑
这个C语言实现的扫雷游戏采用了函数式的编程方式,主要包括以下几个函数:
3.1 initBoard函数
用于初始化游戏的雷区和显示区,设置地雷和数字格的初始状态。
void initBoard(char arr[ROWS][COLS], int x, int y, int row, int col, char set) {
for (int i = x; i < row+x; i++) {
for (int j = y; j <col+y; j++) {
arr[i][j] = set;
}
}
}
3.2 displayBoard函数
显示游戏的界面,包括雷区和当前的翻开情况。
void displayBoard(char arr[ROWS][COLS]) {
system("cls");
printf("------------------扫雷------------------\n");
for (int i = 0; i <= ROW; i++) {
printf(" %d |", i);
}
printf("\n");
for (int i = 0; i <= ROW; i++) {
printf("----");
}
printf("\n");
for (int i = 1; i <= ROW; i++) {
printf(" %d |", i);
for (int j = 1; j <= COL; j++) {
if (arr[i][j] == 'X') {
if (win != 0) {
printf(" \033[31m%c\033[0m |", arr[i][j]);
}
else {
printf(" \033[32m%c\033[0m |", arr[i][j]);
}
}
else {
printf(" %c |", arr[i][j]);
}
}
printf("\n");
for (int j = 0; j <= COL; j++) {
printf("----", arr[i][j]);
}
printf("\n");
}
printf("------------------扫雷------------------\n");
}
3.3 setMine函数
随机布置地雷,保证地雷的位置不重复。
void setMine(char arr[ROWS][COLS], int count) {
while (count) {
int x = rand() % ROW + 1;
int y = rand() % COL + 1;
if (arr[x][y] == '0') {
arr[x][y] = '1';
count--;
}
}
}
3.4 getMineCount函数(递归展开)
计算指定格子周围地雷的数量。
void getMineCount(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y) {
if(arr2[x][y] == '*'){
int count = arr1[x - 1][y - 1] + arr1[x - 1][y] +
arr1[x - 1][y + 1] + arr1[x][y - 1] +
arr1[x][y + 1] + arr1[x + 1][y - 1] +
arr1[x + 1][y] + arr1[x + 1][y + 1] - 8 * '0';
if (count == 0) {
arr2[x][y] = ' ';
win--;
getMineCount(arr1, arr2, x - 1, y - 1);
getMineCount(arr1, arr2, x - 1, y);
getMineCount(arr1, arr2, x - 1, y + 1);
getMineCount(arr1, arr2, x, y - 1);
getMineCount(arr1, arr2, x, y + 1);
getMineCount(arr1, arr2, x + 1, y - 1);
getMineCount(arr1, arr2, x + 1, y);
getMineCount(arr1, arr2, x + 1, y + 1);
}
else {
arr2[x][y] = count + '0';
win--;
}
}
}
3.5 findMine函数
处理玩家的输入,翻开格子,展开空白格,并判断游戏胜利或失败。
void findMine(char arr1[ROWS][COLS], char arr2[ROWS][COLS]) {
while (win) {
int x, y;
printf("请输入坐标,并用空格隔开:");
scanf("%d %d", &x, &y);
if (arr1[x][y] == '1') {
markMine(arr1, arr2);//游戏结束,把地雷的位置在用户表上标记出来
displayBoard(arr2);
printf("\033[31m很遗憾,游戏结束!!!\033[0m\n");
break;
}
else {
//统计这个坐标周围有几个雷,若是0;则变为' ',并自动计算周围八个格子的值
getMineCount(arr1, arr2, x, y);
displayBoard(arr2);
}
}
if (win == 0) {
markMine(arr1, arr2);
displayBoard(arr2);
printf("\033[32m恭喜你,排雷成功!!!\033[0m\n");
}
}
4、完整代码和效果展示
在这一部分,我们将给出完整的C语言代码实现,并展示游戏效果。
头文件game.h
#pragma once
//定义雷区为9*9的方块
#define ROW 9
#define COL 9
//为了方便计算数字,定义的数组我们多加两行两列,
//地雷的位置和数字不放在最边上的行和列
#define ROWS ROW+2
#define COLS COL+2
//难度--地雷的数量
#define _EASY 10
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
//初始化表,x,y表示初始化的起始坐标,row和col表示初始化的表的大小,ch表示初始化的内容
void initBoard(char arr[ROWS][COLS], int x, int y, int row, int col, char set);
//显示用户表
void displayBoard(char arr[ROWS][COLS]);
//排查地雷
void findMine(char arr1[ROWS][COLS], char arr2[ROWS][COLS]);
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void initBoard(char arr[ROWS][COLS], int x, int y, int row, int col, char set) {
for (int i = x; i < row+x; i++) {
for (int j = y; j <col+y; j++) {
arr[i][j] = set;
}
}
}
//定义win,表示除地雷外的空格数
int win = ROW * COL - _EASY;
void displayBoard(char arr[ROWS][COLS]) {
system("cls");
printf("------------------扫雷------------------\n");
for (int i = 0; i <= ROW; i++) {
printf(" %d |", i);
}
printf("\n");
for (int i = 0; i <= ROW; i++) {
printf("----");
}
printf("\n");
for (int i = 1; i <= ROW; i++) {
printf(" %d |", i);
for (int j = 1; j <= COL; j++) {
if (arr[i][j] == 'X') {
if (win != 0) {
printf(" \033[31m%c\033[0m |", arr[i][j]);
}
else {
printf(" \033[32m%c\033[0m |", arr[i][j]);
}
}
else {
printf(" %c |", arr[i][j]);
}
}
printf("\n");
for (int j = 0; j <= COL; j++) {
printf("----", arr[i][j]);
}
printf("\n");
}
printf("------------------扫雷------------------\n");
}
void setMine(char arr[ROWS][COLS], int count) {
while (count) {
int x = rand() % ROW + 1;
int y = rand() % COL + 1;
if (arr[x][y] == '0') {
arr[x][y] = '1';
count--;
}
}
}
//游戏结束,把地雷的位置在用户表上标记出来
static void markMine(char arr1[ROWS][COLS], char arr2[ROWS][COLS]) {
for (int i = 1; i <= ROW; i++) {
for (int j = 1; j <= COL; j++) {
if (arr1[i][j] == '1') {
arr2[i][j] = 'X';
}
}
}
}
//计算坐标周围雷的数量
static void getMineCount(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int x, int y) {
if(arr2[x][y] == '*'){
int count = arr1[x - 1][y - 1] + arr1[x - 1][y] +
arr1[x - 1][y + 1] + arr1[x][y - 1] +
arr1[x][y + 1] + arr1[x + 1][y - 1] +
arr1[x + 1][y] + arr1[x + 1][y + 1] - 8 * '0';
if (count == 0) {
arr2[x][y] = ' ';
win--;
getMineCount(arr1, arr2, x - 1, y - 1);
getMineCount(arr1, arr2, x - 1, y);
getMineCount(arr1, arr2, x - 1, y + 1);
getMineCount(arr1, arr2, x, y - 1);
getMineCount(arr1, arr2, x, y + 1);
getMineCount(arr1, arr2, x + 1, y - 1);
getMineCount(arr1, arr2, x + 1, y);
getMineCount(arr1, arr2, x + 1, y + 1);
}
else {
arr2[x][y] = count + '0';
win--;
}
}
}
void findMine(char arr1[ROWS][COLS], char arr2[ROWS][COLS]) {
while (win) {
int x, y;
printf("请输入坐标,并用空格隔开:");
scanf("%d %d", &x, &y);
if (arr1[x][y] == '1') {
markMine(arr1, arr2);
displayBoard(arr2);
printf("\033[31m很遗憾,游戏结束!!!\033[0m\n");
break;
}
else {
//统计这个坐标周围有几个雷,若是0;则变为' ',并自动计算周围八个格子的值
getMineCount(arr1, arr2, x, y);
displayBoard(arr2);
}
}
if (win == 0) {
markMine(arr1, arr2);
displayBoard(arr2);
printf("\033[32m恭喜你,排雷成功!!!\033[0m\n");
}
}
main.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//打印菜单
void menu() {
printf("****************************\n");
printf("******* 1.play *******\n");
printf("******* 0.exit *******\n");
printf("****************************\n");
}
//游戏函数
void game() {
//地雷区和扫雷得到的数字分别存放在两个数组中
char mine[ROWS][COLS];
char show[ROWS][COLS];
//初始化两张表:把地雷表数据初始化为'0',数字表初始化为'*'
initBoard(mine,0,0,ROWS,COLS,'0');
initBoard(show,0,0,ROWS,COLS,' ');
initBoard(show,1,1,ROW,COL,'*');
//布置地雷
setMine(mine, _EASY);
//显示用户表
displayBoard(show);
//排查地雷-->若是地雷则游戏结束,反之计算这个坐标位置的数值,并显示结果
findMine(mine, show);
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("输入 1 开始游戏:");
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
break;
default:
printf("输入有误,请重新输入\n");
}
} while (input);
}
结果展示
1、排雷成功。ps:我们提前把地雷的数量设置为了1。
2、排雷失败
总结:
在本篇博客中,我们详细介绍了如何用C语言实现扫雷游戏。通过阅读这篇博客,您将了解到扫雷游戏的基本规则、整体框架以及代码实现。希望本篇博客能帮助您更好地学习和理解C语言编程。