扫雷小游戏!由b站2粉丝(未来的百大up主自制)

Posted 起个名字好难嗷

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫雷小游戏!由b站2粉丝(未来的百大up主自制)相关的知识,希望对你有一定的参考价值。

写在前面

博主的gitee仓库地址!<==欢迎大家来访! (点击左侧蓝色字体进行跳转)

视频展示扫雷小游戏!!!!!!!<==点击左侧蓝色字体,跳转到视频处!求三连!求三连!

下面的扫雷代码属于实现了扫雷的基本功能,但是诸如递归版扫雷,还有能够实现一次展开一片,能标记雷的扫雷小游戏,博主暂时还没有什么好的想法(因为菜)

在这里插入图片描述


读者读完我的文章以后可以参考一下两位大佬的文章,(内含递归版扫雷等)

大佬一号文章 <==点击左侧跳转,含炼狱递归等

大佬二号文章<==点击左侧跳转,含递归扫雷注释详解等


扫雷小游戏简介

《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。


游戏大致思路

在写这个游戏之前,我们首先要明确的一点就是,我们需要首先创立两个源文件和一个头文件。

在这里插入图片描述


test.c部分思路讲解

游戏菜单

首先,我们需要建立一个游戏菜单,来让玩家选择是进入游戏,还是选择终止游戏,这个界面最好是简单且清晰。

代码如下


void menu()
{
	printf("******************************\\n");
	printf("******    1. play      *******\\n");
	printf("******    0. exit      *******\\n");
	printf("******************************\\n");
}

最终效果

在这里插入图片描述


游戏主干部分


既然有了上图的菜单,那么接下来我们要做的就是通过这个菜单来进行延伸,为接下来游戏操作部分的写入提供基础,就像是一处地基一样.

代码如下

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();//扫雷游戏
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default:
			printf("选择错误,重新选择\\n");
			break;
		}
	} while (input);

	return 0;
}

如图,当我们输入1时,会通过switch语句进入case1中,执行game()这个游戏进程,而这个游戏进程就是我们要在game.c中具体操作的,这个我们先按下不表,后面进行详解。

同理,输入0时,退出游戏,而当输入其他数字,比如3或4时,由于defult语句的存在,会打印出“选择错误。重新选择。”在这我们要注意的一点是,defult语句并不是必须要写在最后,但是为了养成良好的代码风格,我们最好将它写在最后面,既美观也方便操作。


game.c部分思路讲解

思考

这个时候我们先不要急着写,我们联想一下扫雷游戏的大致规则,思考一下我们接下来想走的路,由扫雷传统的游戏规则知道。

在这里插入图片描述

在这里插入图片描述


首先,假设当前是9×9的棋盘
1.应该先把雷布置进去,然后记录下去
先要有一个存放雷的棋盘,是雷的地方给1,不是雷的地方给0.
但可能会产生歧义,红色的是雷?还是打印出雷的信息?这个时候,我们要注意,打印的东西太多了,不太好,会很混乱(此时有三种信息)
所以呢,我们还需要一个数组,专门存放排查雷的信息!

2.排查雷


思考总结

1.两个数组

2 .一个数组存放布置好雷的信息 (char数组)

3.一个数组存放排查出的雷的信息 (char数组)


在这里插入图片描述

特别提醒!,如果想实现9×9的棋盘,数组的大小设成11×11会比较好,(把数组开大一点)雷是不会到框框里的!雷只会在中间!

注意!如果每个字符存一个字符,那么就得是char类型数组!*

char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息

代码逐句解析

上代码

在这里插入图片描述


在这里插入图片描述


接下来是很关键的一步

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = EASY_COUNT;
	while (count)
	{
		//生产随机的下标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

int x = rand() % row + 1;
int y = rand() % col + 1;

在这里,我们使用之前要调用srand(time)(null),null是一个空指针。
查询msdn我们可以知道

在这里插入图片描述
它的头文件是<stdlib.h>,它后面需要强制类型转换一下,否则会有警告。time-t本质就是一种整型。

msdn可以私信作者获取。


最后一步

static int get_mine_count(char mine[ROWS][COLS], 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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	//1. 输入排查的坐标
	//2. 检查坐标处是不是雷
	   // (1) 是雷   - 很遗憾炸死了 - 游戏结束
	   // (2) 不是雷  - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续

	int x = 0;
	int y = 0;
	int win = 0;

	while (win < row * col - EASY_COUNT)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d%d", &x, &y);//x--(1,9)  y--(1,9)

		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
				//不是雷情况下,统计x,y坐标周围有几个雷
				int count = get_mine_count(mine, x, y);
				show[x][y] = count + '0';
				//显示排查出的信息
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("坐标不合法,请重新输入\\n");
		}
	}

	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\\n");
		DisplayBoard(mine, row, col);
	}
}

game.h部分

主体菜单

这个代码应该是我们一开始就想到的

在这里插入图片描述


定义

接下来要定义一下,注意定义要大写。

在这里插入图片描述

【11】【11】也会用到,这样更加方便。


游戏全部代码展示

test.c部分

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void menu()
{
	printf("******************************\\n");
	printf("******    1. play      *******\\n");
	printf("******    0. exit      *******\\n");
	printf("******************************\\n");
}

void game()
{
	char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息
	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');//'0'
	InitBoard(show, ROWS, COLS, '*');//'*'

	//打印一下棋盘
	DisplayBoard(show, ROW, COL);

	//布置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(mine, ROW, COL);

	//排查雷
	FindMine(mine, show, ROW, COL);
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));

	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();//扫雷游戏
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default:
			printf("选择错误,重新选择\\n");
			break;
		}
	} while (input);

	return 0;
}

game.h部分

#define _CRT_SECURE_NO_WARNINGS
#pragma once


#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define EASY_COUNT 10

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2


//初始化棋盘的
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);


(重点)game.c部分

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"


void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;
		}
	}
}

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("---------扫雷游戏-----------\\n");
	//打印列号
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\\n");
	}
	printf("---------扫雷游戏-----------\\n");
}


void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int count = EASY_COUNT;
	while (count)
	{
		//生产随机的下标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

//static
//1. 修饰局部变量
//2. 修饰全局变量
//3. 修饰函数

static int get_mine_count(char mine[ROWS][COLS], 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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	//1. 输入排查的坐标
	//2. 检查坐标处是不是雷
	   // (1) 是雷   - 很遗憾炸死了 - 游戏结束
	   // (2) 不是雷  - 统计坐标周围有几个雷 - 存储排查雷的信息到show数组,游戏继续

	int x = 0;
	int y = 0;
	int win = 0;

	while (win < row * col - EASY_COUNT)
	{
		printf("请输入要排查的坐标:>");
		scanf("%d%d", &x, &y);//x--(1,9)  y--(1,9)

		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
				//不是雷情况下,统计x,y坐标周围有几个雷
				int count = get_mine_count(mine, x, y);
				show[x][y] = count + '0';
				//显示排查出的信息
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("坐标不合法,请重新输入\\n");
		}
	}

	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\\n");
		DisplayBoard(mine, row, col);
	}
}

玩游戏

我如果选择退出游戏

在这里插入图片描述

我如果选择玩游戏

在这里插入图片描述

视频展示扫雷小游戏!!!!!!!<==点击左边蓝色字体,跳转到视频处!求三连!求三连!


结语

其实这个代码还有许多可以改进的地方,由于本人水平有限,如文章中有不当之处,还请私信作者,或在评论区指出! 作者将尽力力修改。

以上是关于扫雷小游戏!由b站2粉丝(未来的百大up主自制)的主要内容,如果未能解决你的问题,请参考以下文章

怎么查看B站他人账号的每日粉丝数据?

分析了10万条B站UP主数据后,我知道了成为百万粉丝UP主的一些秘密

B站UP主自制的开源OCR翻译器走红Github,用一次就粉了

b站新人up主怎么起步?

党妹为啥叫pty?

bilibili粉丝数量变化怎样查询呀?