前言
-
扫雷游戏规则
游戏目标
在不触发地雷的前提下,揭开所有非雷的格子。若成功,则游戏胜利;若踩中雷,则游戏失败
示例说明
1.若揭开某格子后显示 3,表示其周围 8 个格子中有 3 个雷
2.若标记了所有雷的位置,且未触发任何雷,则游戏胜利
如图中红色框框中间的显示的是1,表示其周围 8 个相邻格子 中的地雷数量一共有1个

-
整体的游戏框架
-
基本内容
打印菜单
在编程语言中,我们对main函数最好从简,然后再使用嵌套式的函数,这使得代码简洁易高效。所以我们在main函数中只需要从一个函数入手。
然后再从test函数进行写入
由于打印菜单的界面过于繁琐,不利于代码的简洁美观,所以我们可以把菜单页面放到函数menu中去


进入游戏

-
核心内容
创建两个数组棋盘
在这里我们需要初始化两个二维数组,一个是含雷的(这个不能被看到),另一个是打印在我们需要看的。

之所以后续定义了ROWS和LISTS,是因为在排雷的过程中,如果遇到周围没有8个相邻格子的情况,我们需要创建一个11x11的二维数组,(这里以9x9的为例)来确保周围都有8个相邻格子的情况,为后续写函数提供便利

对棋盘初始化
为了能更好地能编辑设置二维数组的元素,我们在函数中用变量set来代替手动输入‘0‘和’*‘,这样只需要在调用函数的时候修改,有利于后续的优化修改

二维数组的大小也是一样 故在game.h头文件中定义ROW和LIST,后续想修改二维数组大小只需要修改ROW和LIST即可,注意,要在主函数中要声明#include “game.h”头文件

打印棋盘
打印给我们看的棋盘,我们用一个函数来表达,设置雷的棋盘不能被展示出来
为了更好的确定棋盘内每个元素的坐标,我们可以打印坐标,有利于我们观察
布置雷
布置雷有几个前提
1.布置雷
2.在合法的坐标内
3.设置的点没有雷
4.设置的雷要随机
下面注释掉的这一行是当我们编程的时候,想要确定写的对不对,便可以打印代码出来查看,但实际应用的时候应该注释掉

这里我们用count来保存想要放置雷的个数
x坐标和y坐标要保持在坐标1~9范围内

因为使用rand函数要设置随机值,我们可以依据时刻变化的时间来代值![]()
排查雷
老规矩,还是为排查雷设置一个函数FindMine

排查雷也有几个前提
1.判断坐标的合法性
这时候我们就可以使用if语句

2.确认这个坐标没有被排查过
3.统计周围有几个雷

需要注意打印的2并非是2,而是需要2-‘0’才能得到计算机的2,1也是同理
所以在最后赋值的时候要加上‘0’


我们还要假设一种情况:如果我们设置了80个雷(这里以9x9的棋盘为例,那么一共就有81个格子,当我们排除完所有的未含雷的格子后,程序应该结束,不应该再继续下去,所以我们要设置一个条件循环

源码
game.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define LIST 9
#define ROWS ROW+2
#define LISTS LIST+2
#define EASY_count 80
//初始化棋盘
void Initboard(char board[ROWS][LISTS], int r, int c , char set);
//打印棋盘
void DisplayedBoard (char board[ROWS][LISTS], int r, int c );
//布置雷
void SetMine(char board[ROWS][LISTS], int r, int c);
//排查雷
void FindMine(char mine[ROWS][LISTS], char show[ROWS][LISTS], int r, int c);
game.c
#include "game.h"
int GetMineCount(char mine[ROWS][LISTS], 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 Initboard(char board[ROWS][LISTS], int r, int c,char set)
{
int i = 0;
for (i = 0;i <r ;i++)
{
int j = 0;
for (j = 0;j < c;j++)
{
board[i][j] = set;
}
}
}
void DisplayedBoard (char board[ROWS][LISTS], int r, int c)
{
int i = 0;//打印列
for (i = 0;i <= c;i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1;i <= r;i++)
{
int j = 0;//打印行
printf("%d ", i);
for (j = 1;j <= c;j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//1.布置雷
//2.在合法的坐标内
//3.设置的点没有雷
void SetMine(char board[ROWS][LISTS], int r, int c)
{
int count = EASY_count;
while (count)
{
int x = rand() % ROW + 1 ;
int y = rand() % LIST + 1 ;
if (board[x][y] == '0')
{
board[x][y] = '1';
count--;
}
}
}
void FindMine(char mine[ROWS][LISTS], char show[ROWS][LISTS], int r, int c)
{
int x = 0;
int y = 0;
int flag = 0;
int win = 0;
while ( win<r*c-EASY_count )
{
printf("输入坐标排查雷\n");
scanf_s("%d %d", &x, &y);
//判断坐标的合法性
if (x >= 1 && x <= r && y >= 1 && y <= c)
{
if (mine[x][y] == '1')
{
printf("失败,雷的位置在\n");
DisplayedBoard(mine, ROW, LIST);
flag = 1;
break;
}
else
{
//如果这个坐标没有被排查过
if (show [x][y] == '*')
{
//统计周围有几个雷
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayedBoard(show, ROW, LIST);
win++;
}
else
{
printf("此坐标已经被排查过,请重新输入坐标\n");
}
}
}
else
{
printf("输入坐标有误,请重新输入\n");
}
}
if (flag != 1)
{
printf("排雷成功,游戏胜利\n");
}
}
main.c
#include "game.h"
void menu()
{
printf("***** 扫雷游戏 *****\n");
printf("***** 1.开始游戏 *****\n");
printf("***** 0.退出游戏 *****\n");
}
void game()
{
char mine[ROWS][LISTS];
char show[ROWS][LISTS];
//初始化棋盘
Initboard(mine, ROWS, LISTS, '0');//‘0’为雷
Initboard(show, ROWS, LISTS, '*');//'*''
DisplayedBoard( show, ROW, LIST );
//DisplayedBoard( mine, ROW, LIST );
//布置雷
SetMine(mine, ROW, LIST);
//DisplayedBoard( mine, ROW, LIST );
//排查雷
FindMine(mine,show,ROW,LIST);
}
void test()
{
menu();
int input = 0;
printf("请输入:");
do {
scanf_s("%d", &input);
switch (input)
{
case 1:
srand((unsigned int)(time(NULL)));
printf("开始游戏\n");
game();
break;
case 0:
break;
default :
printf("输入错误 请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
return 0;
}
拓展
1.我们发现这个代码还没有实现周围遇到0个雷的时候能自动向外拓展,直至出现相邻格子有雷的情况才会停止
2.或许我们还能在推断出雷的位置的时候,通过某种功能给有雷的地方做上标记,例如鼠标右键
...
我们可以看后进一步思考看如何做,而不拘泥于这一个简单的功能。
结语
扫雷小游戏是对c语言简单语言的综合性运用,学习并熟练运用其中的知识对提升写代码水平很有帮助。本人花了两天时间才完全自主写出来,其中也遇到许多的困难:比如打印数组时的坐标显示错误,初始化棋盘有问题等等.....学习总是充满坎坷的,但坚持学下去更可贵。
学习过程中不要抄代码,自己写才知道自己出现的错误点在哪里,这样才能反思总结,有所进步。
当秋天的第一片梧桐叶落下时,你会突然发现:那些曾经以为永远跨不过的坎,早已成为身后模糊的风景线。你值得被自己的勇气温柔以待。
1万+

被折叠的 条评论
为什么被折叠?



