C语言实现扫雷游戏的方法
相信大家对扫雷一定都不陌生吧!但是你敢信仅仅使用一些C语言的初阶基础知识就能够制作一个扫雷简单小游戏?今天,我将带领大家一起走进扫雷,探究其基础算法奥秘。
一、基本思路
首先,既然是玩游戏,我们应该设计相应的菜单。
输入1后继续让玩家选择游戏难度:
我们在这里设计简单模式为6x6大小的面板,雷埋10个;中等模式为10x10大小的面板,雷埋30个;困难模式为14x14大小的面板,雷埋50个。
为了方便雷的布置与显示,我们设计了两张面板:show_board[ROW][COL]和mine_board[ROW][COL],其中show面板负责显示“空格”,mine面板负责记录周围雷的个数。
玩家通过输入每个格子所对应的坐标进行扫雷操作。
char** show_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));//二维数组动态内存分配
for (int i = 0; i < ROW + grade * 4; i++) {
show_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));
memset(show_board[i], ' ', (COL + grade * 4));//数组全部赋值为空格
}
char** mine_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));
for (int i = 0; i < ROW + grade * 4; i++) {
mine_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));
memset(mine_board[i], '0', (COL + grade * 4));//数组全部赋值为‘0'
}
二、代码实现
Step1.画图
想要进行扫雷游戏,首先应该有扫雷界面的设计,如下:
我们建立Showboard函数进行面板的基本绘制:
static void Showboard(char **board,int grade)//面板制作
{
printf(" ");
for (int i = 1; i <= ROW-2+4*grade; i++) {
printf(" %3D", i);
}
printf("\n");
for (int i = 1; i <= ROW-2+4*grade; i++){
printf(" ");
for (int k = 1; k <= COL-2+4*grade; k++) {
printf("----");
}
printf("\n");
printf("%2d|",i);
for (int j = 1; j <= COL-2+4*grade; j++){
printf(" %c |",board[i][j]);
}
printf("\n");
}
printf(" ");
for (int k = 1; k <= COL-2+4*grade; k++) {
printf("----");
}
printf("\n");
}
成果图如下:
Step2. 埋雷
埋雷应做到一下几点:
1.展示面板show_board(这里传参后以形参board替代)赋值为1(BOOM宏定义为1) ;
2.为了提高用户体验,在被炸后能够展示出雷的位置,我们又建立了一个lei_board数组用来显示,并在埋雷时将对应位置赋值为'*';
3.埋雷要具有随机性,所以这里引用rand函数(主函数要种随机数种子);
static void SetMines(char **board,char **lei_board,int grade)
{
int i = 1;
int x, y;
while (i <= NUM+grade*20) {
x = rand() % (ROW-2+4*grade) + 1;
y = rand() % (COL-2+4*grade) + 1;
if (board[x][y] != BOOM) {
board[x][y] = BOOM;
lei_board[x][y] = '*';
i++;
}
}
}
Step3.计算周围雷的个数
当我们计算周围雷的个数时,自然而然地就会想到统计周围九宫格的雷的个数。如果要搜索的位置在面板中间,这很简单,但如果是以下这类情况,比如顶点格或者边格怎么办?如何知道该算哪个格?
为了避免这种特殊情况所带来的问题,我们不如直接在外面再套一圈,对于各类面板(即二维数组)的建立也直接按照增大的来,这样就无需讨论边角的特殊性了。
统计函数直接通过简单的函数返回来实现:
static int CountMine(char **board,int x,int y)
{
return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \
board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \
board[x + 1][y] + board[x + 1][y + 1] - 8 * '0';
}
三、完整代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define BOOM '1'
#define ROW 8
#define COL 8
#define NUM 10
static void SetMines(char **board,char **lei_board,int grade)//埋雷
{
int i = 1;
int x, y;
while (i <= NUM+grade*20) {
x = rand() % (ROW-2+4*grade) + 1;
y = rand() % (COL-2+4*grade) + 1;
if (board[x][y] != BOOM) {
board[x][y] = BOOM;
lei_board[x][y] = '*';
i++;
}
}
}
static void Showboard(char **board,int grade)//面板制作
{
printf(" ");
for (int i = 1; i <= ROW-2+4*grade; i++) {
printf(" %3d", i);
}
printf("\n");
for (int i = 1; i <= ROW-2+4*grade; i++){
printf(" ");
for (int k = 1; k <= COL-2+4*grade; k++) {
printf("----");
}
printf("\n");
printf("%2d|",i);
for (int j = 1; j <= COL-2+4*grade; j++){
printf(" %c |",board[i][j]);
}
printf("\n");
}
printf(" ");
for (int k = 1; k <= COL-2+4*grade; k++) {
printf("----");
}
printf("\n");
}
static int CountMine(char **board,int x,int y)//统计周围雷的数目
{
return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \
board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \
board[x + 1][y] + board[x + 1][y + 1] - 8 * '0';
}
void Game(int grade)//游戏函数,grade为游戏难度等级
{
char** show_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));
for (int i = 0; i < ROW + grade * 4; i++) {
show_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));
memset(show_board[i], ' ', (COL + grade * 4));
}
char** mine_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));
for (int i = 0; i < ROW + grade * 4; i++) {
mine_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));
memset(mine_board[i], '0', (COL + grade * 4));
}
char** lei_board = (char**)malloc(sizeof(char*) * (ROW + grade * 4));
for (int i = 0; i < ROW + grade * 4; i++) {
lei_board[i] = (char*)malloc(sizeof(char) * (COL + grade * 4));
memset(lei_board[i], ' ', (COL + grade * 4));
}
SetMines(mine_board,lei_board,grade);
int x = 0, y = 0;
int total = 0;
while (1)
{
Showboard(show_board, grade);
printf("请输入坐标:");
//printf("%d", '*');
scanf("%d %d", &x, &y);
if (!(x > 0 && x <= ROW + 4 * grade - 2 && y > 0 && y <= COL + 4 * grade - 2)) {
printf("扫雷的位置有问题!\n");
continue;
}
if (show_board[x][y] != ' ') {
printf("该位置已经扫过了!\n");
continue;
}
if (mine_board[x][y] == '1') {
printf("对不起,你被炸死了!\n");
Showboard(lei_board, grade);
break;
}
else {
int count = CountMine(mine_board, x, y);
show_board[x][y] = count + '0';
total++;
system("cls");
}
if ((ROW - 2) * (COL - 2) - total <= NUM) {
printf("恭喜你,游戏通过!\n");
break;
}
}
for (int i = 0; i < ROW + grade * 4; i++) {
free(show_board[i]);
}
free(show_board);
for (int i = 0; i < ROW + grade * 4; i++) {
free(mine_board[i]);
}
free(mine_board);
for (int i = 0; i < ROW + grade * 4; i++) {
free(lei_board[i]);
}
free(lei_board);
}
void Menu()
{
printf("#########################################\n");
printf("## 1.play ##\n");
printf("## 0.exit ##\n");
printf("#########################################\n");
}
int main()
{
srand((unsigned long)time(NULL));
int quit = 0;
while (!quit)
{
int select;
Menu();
printf("请输入游戏选项:");
scanf("%d", &select);
switch (select)
{
case 1:
printf("#########################################\n");
printf("## 1.easy ##\n");
printf("## 2.middle ##\n");
printf("## 3.difficult ##\n");
printf("#########################################\n");
printf("请输入游戏难度:");
scanf("%d", &select);
switch (select)
{
case 1:
Game(0);
break;
case 2:
Game(1);
break;
case 3:
Game(2);
break;
}
break;
case 0:
quit = 1;
printf("感谢使用!");
break;
default:
printf("输入有误,请重新输入!\n");
break;
}
}
}
期待大家在这个代码的基础上加入更多创新与改进,写出用户体验感更好,更加智能高端的扫雷程序!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
相关文章