首先,在搭建扫雷在这个游戏之前,小伙伴们需要先了解扫雷的规则:
这里呢,up建议小伙伴们先去体验几盘扫雷,这有利于理解代码哦!!
up这里给上扫雷的网页版链接,小伙伴们可以先去体验体验~~
扫雷游戏在线玩 - Minesweeper (saolei123.com)
那么在了解完扫雷的规则之后呢,小伙伴们就要跟随up一起共同探索如何用c实现扫雷游戏啦!
# 知识补充
1.首先,在构建游戏前,up想带着小伙伴们一起认识以下几个函数:
【1】srand函数
---引用时需要引用头文件,即#include<stdlib.h>
---为rand函数生成随机值而提供先决条件,返回值为unsigned int类型,通常与time函数一起使用,即srand((unsigned int)time(NULL));
【2】rand函数
---引用时需要引用头文件,即#include<stdlib.h>
---达到生成随机数的目的,通常将其返回值存到变量里,即int ret=rand();
【3】time函数
---引用时需要引用头文件,即#include<time.h>
---为rand函数生成随机值而提供先决条件,通常作为无参函数与srand函数一起使用,即srand((unsigned int)time(NULL));
【4】Sleep函数
---引用时需要引用头文件,即#include<windows.h>
---Sleep();括号里写具体想要停滞的时间,单位为ms,达到停滞界面的效果
【5】cls函数
---引用时需要调用头文件,即#include<windows.h>
---system("cls");达到清屏的目的
# 函数实现
2.其次,搭建这么一个游戏,必然是需要分模块实现的
!!!up这里分为game.c和test.c两个源文件,以及game.h这个头文件。那么为啥需要这么做呢?原因就是可以使得整体布局更清晰直观,达到分工明确的目的。那么,话不多说,上代码!!
【1】:game.h头文件
//game.h
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
//在构建扫雷游戏之前,小伙伴们需要先明白扫雷游戏的原理,
//那么在了解扫雷的原理后,要干些啥呢?
//=>既然要排雷=>那么自然也就要装雷
//怎么装雷呢?拿什么装雷?
//=>拿表格装雷,常见的扫雷图是9x9,那么up也以9x9作为范例
//so,要先创建表格,又考虑到扫雷时边界的问题,为了防止数组越界访问而造成扫雷时的程序错误,就要创建更大的数组,
//=>即搭建11x11的表格,对11x11的表格进行初始化(使其得以可控),再对9x9表格进行扫雷操作即可
//所以,滤清思路,步骤为:
//创建表格=>初始化表格=>装雷=>排雷=>判断被炸or排雷成功
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
#define NUM 10 //宏定义雷的数目,便于修改
//表格初始化
void ini(char chart[ROWS][COLS], int row, int col,char ch);
//装雷
void set_mychart(char chart[ROW][COL], int row, int col);
//打印输出表格
void print(char chart[ROWS][COLS], int row, int col);
//排雷
void find_bomb(char showchart[ROWS][COLS],char mychart[ROWS][COLS], int row,int col);
//判断周围有几个雷
int how_many(char mychart[ROWS][COLS], int x, int y);
【2】.game.c源文件
//game.c
#include"game.h"
void ini(char chart[ROWS][COLS], int row, int col, char ch)
{
int i = 0;
int j = 0; //需要注意的是:
for (i = 0; i < ROWS ; i++) //考虑到9x9扫雷时的边界问题,边界以外不是扫雷区,自然无雷,但为了使排雷时判断统一,
{ //因此设置11x11的棋盘,并给其初始化,但在打印棋盘的时候,只打印9x9的棋盘
for (j = 0; j < COLS ; j++)
{
chart[i][j] = ch;
}
}
}
void set_mychart(char chart[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
int count = NUM;
while (count)
{
x = rand() % row + 1;//取用1~9的数
y = rand() % col + 1;
if (chart[x][y] == '0')
{
chart[x][y] = '1';//装雷处设为'1',为啥设'1'呢?后文会讲到,是为了方便统计
count--;
}
}
}
void print(char chart[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < ROWS - 1; i++)
{
printf("%d ", i);
}
printf("\n"); //这里都是布置棋盘,达到美观的效果,铁子们运行一下就知道具体啥效果了
for (i = 1; i < ROWS-1; i++)
{
printf("%d ", i);
for (j = 1; j < COLS-1; j++)
{
printf("%c ", chart[i][j]);
}
printf("\n");
}
}
void find_bomb(char showchart[ROWS][COLS], char mychart[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = 0;
int win = 0;
while ((ROW * COL - NUM) - win > 0)
{
printf("请小主输入想要排查的坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if ('*'==showchart[x][y])
{
if ('1' == mychart[x][y])
{
printf("可怜的小主被炸死了555\n");
print(mychart, row, col);
break;
}
else
{
count = how_many(mychart, x, y);
showchart[x][y] = '0' + count;//字符-字符=整型数,所以字符+整型数=字符
print(showchart, ROW, COL);//如'1'-'0'=49-1=1,所以'0'+2='2'
win++; //成功排雷一次,就win++
}
}
else
printf("小主输入的坐标重复,请重新输入!\n");
}
else
printf("小主输入的坐标不在棋盘内,请重新输入!\n");
}
if (win == (ROW * COL - NUM))
printf("恭喜小主排雷成功!!小主赛高!!\n");
}
int how_many(char mychart[ROWS][COLS], int x, int y)
{
return (mychart[x - 1][y] + mychart[x - 1][y + 1]
+ mychart[x][y + 1] + mychart[x + 1][y + 1] + mychart[x + 1][y]
+ mychart[x + 1][y - 1] + mychart[x][y - 1] + mychart[x - 1][y - 1]) - 8 * '0';
//为啥这么做呢?字符数据相减,对应其ASCII相减,如'1'-'1'=0,这也就是为啥装雷的时候要把雷设成'1',就是为了方便统计排雷处周围的雷数
}
【3】.test.c源文件
//test.c
#include"game.h"
void menu();
void game();
int main()
{
int choice = 0;
do
{
menu();
printf("请小主输入选项:>");
scanf("%d", &choice);
switch (choice)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("小主输入有误,请检查后重新输入\n");
break;
}
} while (choice);
}
void menu()
{
printf(" 1.play \n");
printf(" 0.exit \n");
}
void game()
{ //为啥设置两个数组呢?
//根据扫雷游戏设置,首先要对放雷在棋盘里,也就意味着棋盘里所对应的数组元素是会存放数据(倘若是字符数据)的,那么在给玩家排雷的时候,
//显示的一定是都为同一字符的内容,如都为'*',一个数组元素里至多存放一个字符,如果仅设置一个棋盘,又要达到初始化棋盘的目的,
//还要达到存雷的目的,那怎么可能呢??难道说一个数组元素可以同时存两个字符变量?显然是不可以的。因此,要设置两个数组。
//一个数组用于设置雷,另一个数组用于给玩家排雷,排到的地方与设置雷的数组进行比较,进而确定用于排雷处的周围有多少个雷。
char mychart[ROWS][COLS] = { 0 };//mychart数组用于放雷(电脑随机在棋盘里放雷),showchart数组用于显示(给玩家看)和排雷(给玩家排)
char showchart[ROWS][COLS] = { 0 };
ini(mychart, ROWS, COLS,'0');//调用初始化函数对两个棋盘进行初始化
ini(showchart, ROWS, COLS,'*');//mychart用'0'初始化,showchart用'*'初始化
set_mychart(mychart, ROW, COL);//调用装雷函数对mychart棋盘进行装雷
print(showchart, ROWS, COLS);//调用函数对showchart棋盘进行打印输出
find_bomb(showchart, mychart,ROW,COL);//调用排雷函数对排雷处进行判断
Sleep(5000);
system("cls");
}
制作不易,还请小老板们留下3连再走吧~~~
制作不易,还请小老板们留下3连再走吧~~~
制作不易,还请小老板们留下3连再走吧~~~