前言
这篇文章主要是使用C语言来实现一个最简单的扫雷游戏的程序并对这个过程的实现做一个较为详细的叙述。这个游戏的实现会采用多文件的形式。而我们会用到三个文件。
game.h 中是这个程序的函数声明及预处理指令、库函数头文件等。
game.c 中是这个程序游戏执行函数的具体实现。
test.c 中是这个程序测试框架的实现。
(最后附源码)
注:我们需要在game.c 及 test.c 中均包含我们自己写的头文件
一、菜单面板及游戏测试部分
通常我们在玩游戏时都会有一个主菜单来让我们选择我们想要执行的功能,就像“开始游戏”,“设置”之类的选项。下面呢是一个扫雷游戏的页面,当然我们要实现的这个版本十分的简单,主要是游戏的进行和推出这两个选项。
1.菜单的简单实现
在c语言中呢我们可以用printf函数来实现一个简单的菜单并将它打印在屏幕上,同时呢封装一个menu函数方便代码的编写。
2.主函数测试逻辑的实现
游戏的一般逻辑呢,首先是让玩家在主菜单中选择相应的功能然后执行,这时我们发现菜单是必须在游戏开始前就呈现在屏幕上的而且在一次游戏结束后还需要继续出现提供下一次选择。要实现这样的功能我们就需要 do while 语句与 switch 语句相结合。
游戏部分的具体实现我们将它封装在 game 函数中,由于是多文件的形式,这里game函数中只包含函数调用语句。
图片中呢就是我们游戏运行的逻辑,下面我们就要将它们一一实现。
二、游戏逻辑部分
这部分代码是写在 game.c 文件中的。并且要在 game.h 中加入函数的声明。
1.棋盘的创建
如果我们要在一个9 * 9的区域中布置十个雷,首先我们需要一个9 * 9的“棋盘”来放置这十个雷,这个"棋盘"的创建就需要用到二维数组。
一个棋盘用来布置雷,一个棋盘呢用来打印在屏幕上展示玩家排查后的结果。棋盘的大小我们设置为12 * 12的区域,这样呢是为了防止排查雷的时候造成数组越界。(文章末尾会解释越界原因)
1.1用于展示的棋盘
这个数组中存放的是类似于网页扫雷的图形界面(我们用*代替)以及用户输入的坐标附近雷的分布信息。
1.2用于布置雷的棋盘
这个数组中存放的就是我们随机布置的雷的位置信息。我们用字符‘1’来表示雷,用字符‘0’来表示其它的位置。
1.3棋盘的初始化
初始化棋盘我们要遍历数组的每个元素,给数组的每个元素赋值。因为两个棋盘的功能不同,所以它们的初始化内容也不同。用于展示的数组我们要初始化为’*'来代表图形界面。布置雷的数组要全部初始化为字符‘0’,以便于和布置的雷做区分。
1.4棋盘的打印
棋盘的打印就是打印数组
2.雷的布置
雷的布置最重要的就是随机布置,关于C语言中随机值的生成在我的另一篇文章中已经写过C语言中随机值的生成方法
这里不再赘述。
随机布置雷就是在我们想要布置雷的区域范围内生成随机的坐标并将这些坐标的值改为符号‘1’。
3.雷的排查
我们排查雷首先需要玩家输入一个在范围内且没有被排查过的坐标,然后我们需要判断这个位置上是不是雷,如果是雷那么游戏就失败了,如果不是雷那我们就要判断这个坐标周围一圈的坐标有没有雷,有几个雷并将这个结果呈现在屏幕上。
4.游戏结束条件
4.1失败
玩家在没有排查完除十个雷之外的所有坐标之前被炸死游戏就失败了。
4.2成功
假如玩家将除去十个雷之外的坐标全部排查过后那么我们的游戏就获胜了。
结语
这是一个用c语言实现的最简单的扫雷程序,还可以扩展类似标记雷的位置,展开没有雷的区域的功能以及制作图形化界面等等。希望这篇文章可以帮助到大家,感谢阅读。
附:
数组越界的原因
虽然我们需要布置雷的区域是 9 * 9 的一个区域,但是我们在排查雷时,当我们输入棋盘边缘的坐标时,由于我们需要排查周围一圈的位置,如果是 9 * 9 的棋盘,那么就会有一些位置不在数组范围内导致数组越界。
源码
test.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 show[rows][cols] = { 0 };
char set[rows][cols] = { 0 };
//初始化棋盘
//show初始化为"*"
init_board(show, rows, cols,'*');
//set初始化为"0"
init_board(set, rows, cols,'0');
//布置雷
setMine(set, row, col);
//打印棋盘
print_board(show, row, col);
print_board(set, row, col);
//排雷
findMine(show, set, row, col);
}
int main()
{
int select = 0;
//测试
do
{
//菜单页面
menu();
printf("请选择>:");
scanf("%d", &select);
switch (select)
{
case 1:
//游戏代码实现
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新输入\n");
break;
}
} while (select);
return 0;
}
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘
void init_board(char board[rows][cols], int r, int c,char a)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
board[i][j] = a;
}
}
}
//打印棋盘
void print_board(char board[rows][cols], int r, int c)
{
printf("-------扫雷-------\n");
for (int i = 0; i <= c; i++)
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <= r; i++)
{
printf("%d ", i);
for (int j = 1; j <= c; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//随机布置雷
void setMine(char board[rows][cols], int r, int c)
{
int count = EASY_COUNT;
srand((unsigned int) time(NULL));
while (count)
{
//生成随机坐标
int x = rand() % r + 1;
int y = rand() % c + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
//排查雷
//只能内部链接
static int countMine(char set[rows][cols],int x,int y)
{
int count = 0;
if (set[x][y] != '1')
{
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
if (set[x + i][y + j] == '1')
{
count++;
}
}
}
}
return count;
}
void findMine(char show[rows][cols], char set[rows][cols], int r, int c)
{
//输入要排查的坐标
int x, y;
int win = 0;
//判断坐标是否合法
while (win<r*c- EASY_COUNT)
{
printf("输入要排查的坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= r && y >= 1 && y <= c)
{
//判断是不是雷
if (set[x][y] == '1')
{
printf("炸死\n");
print_board(set, r, c);
break;
}
else
{
if (show[x][y] == '*')
{
//统计该坐标周围雷的个数
int count = countMine(set, x, y);
show[x][y] = count;
print_board(show, r, c);
}
else
{
printf("该坐标已排查过,请重新输入\n");
}
}
}
else
{
printf("坐标不合法,重新输入\n");
}
}
if (win == r * c - EASY_COUNT)
{
printf("恭喜你排除了所有的雷\n");
print_board(set, row, col);
}
}
game.h
#pragma once
#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 init_board(char board[rows][cols], int r, int c,char set);
void print_board(char board[rows][cols], int r, int c);
void setMine(char board[rows][cols], int r, int c);
void findMine(char show[rows][cols], char set[rows][cols], int r, int c);