扫雷深入理解

扫雷新手刚出保护村?没错我学的时候也一样,遇到困难不能放弃,奥里给

文章录目

前言

一、什么是扫雷

二、扫雷整体的设计(会使用多个文件,达到简洁的效果)

 1.扫雷游戏的主体(test.c)

 为了整个游戏的运行和游戏的循环效果和实时更新页面所以我们的游戏主体是这样

 2.函数主体(game.c)【最后会把函数实现部分一块放出来】

  下面进行数组初始化了(第一步了加油加油)

 最后放上最后函数族主体的代码

 .函数声明部分以及宏的定义(game.h)


前言

大家好我是一个申请延长保护期的新手,O(∩_∩)O  ,我会尽我所能把扫雷讲的简单一点。我虽然不是正统计算机专业但是我会努力的!!!一起加油吧。


提示:开始我们奇妙幻想之路啦(我吹牛,一点都不奇妙!哈哈😄O(∩_∩)O)

一、什么是扫雷?

扫雷嘛,多多少少都玩过。无论是年幼时啥都不会乱按或是青春时期课下的一把娱乐,扫雷简短又富有挑战性。

1.扫雷游戏通常由一个方形的区域组成,被分成若干个小方格。
2. 每个方格可能会有一个地雷,也可能没有。玩家需要根据其他方格的状态来判断哪些方格是有雷的。
3. 一开始,所有方格都是暗的,玩家需要挖开一些方格来了解游戏的状态。
4.当玩家挖开一个没有地雷的方格时,方格上会显示数字。这个数字表示周围八个方格中有多少个是地雷。
5.玩家可以标记一些方格为有雷,以便在游戏过程中不会误挖到。
6.如果玩家挖到了一个地雷,游戏就结束了。
7.玩家需要通过逻辑推理来避免挖到地雷,这需要一定的耐心和技能。扫雷游戏有许多不同级别,难度也各异。一般来说,初级扫雷通
常由10个地雷组成,中级扫雷具有40个地雷,而高级扫雷则达到了99个地雷。

二、扫雷整体的设计(会使用多个文件,达到简洁的效果)

1.扫雷游戏的主体(test.c)

先不管游戏页面怎么样(虽然最后也不咋地)我们得让那一个区域的方块呈现吧(初级方块是9X9)所以我们会想到二维数组,所以雷和周围有几个雷肯定也储存在里面啦。在这个基础上,可以建立起相应的数组,然后进行初始化,采用随机数种子来生成雷区,随后计算每个位置(除雷区外)周围的雷的数量。在这些基本的信息准备完成之后,就进入正常的游戏流程。玩家输入坐标以表示需要排查的位置,系统由此给出相应位置的信息,并判断游戏状态。此外,游戏提供标记雷的位置的功能,方便玩家判断。

main函数是程序的入口所以首先我们让走到我们设置的第一个函数这里 :

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();//函数进入到这里我们可让页面更好看一点 
}

这里打印页面,当然可以打印各种各样的页面,这个看个人选择。

void menu()
{
	printf("***********************\n");
	printf("******1. 开始游戏******\n");//因为函数不需要返回值所以我们使用voidSSSSSSSS 
	printf("******0. 结束游戏******\n");
	printf("***********************\n");
	return 0;
}
vo
  1. 为了整个游戏的运行和游戏的循环效果和实时更新页面所以我们的游戏主体是这样

 当扫雷进行时我们可以看见

#include "game.h"  //其他的头文件我包含在game.h里面了所以包含了game.h也就包含了其他头文件
void menu()
{
	printf("***********************\n");
	printf("******1. 开始游戏******\n");//因为函数不需要返回值所以我们使用voidSSSSSSSS 
	printf("******0. 结束游戏******\n");
	printf("***********************\n");
	return 0;
}
void game()  //下面的函数我会放在game.h着头文件里讲
{
	char mine[ROWS][COLS];  //初始化设定棋盘(存放0,配合后续的打印函数我们自己可以看的)
	char show[ROWS][COLS];   //初始化设定棋盘(存放*,配合后续的打印函数给玩家看的)
	intiboard(mine, ROWS, COLS, '0');//存放0
	intiboard(show, ROWS, COLS, '*');//存放*
	prinboard(mine, ROW,  COL);   //这里打印,当然为了防止作弊我们这里要注释
	prinboard(show, ROW, COL);   //这个是玩家最后看见的
}
int main()
{
	int input = 0;    //玩家输入决定是否继续游戏
	srand((unsigned int)time(NULL));
	do
	{
		menu();//函数进入到这里我们可让页面更好看一点 //这里进入我们的menu函数
		printf("请选择:");
		scanf_s("%d",&input);
		switch (input) 
		{
		case 1:
			printf("开始游戏:");
			game();
			break;     //这里使用dreak是为了跳出否则会一直往下执行
		case 0:
			printf("退出游戏:");
			break;
		default:
			printf("输入错误,请重新输入:");

		}
	} while (input);  //do  while循环至少循环一次所以这里最合适,后续根据玩家输入决定是否继续
	return 0;
}

2.函数主体(game.c)【最后会把函数实现部分一块放出来】

游戏存在于9*9的方格里但是再仔细思考一下,我们平常玩的都是有统计效果的,如果到最后一行怎么办?会越界吧。仔细思考一下   是不是有思路了,对了我们用11*11的不就好了嘛。打印9*9。初始化用11*11这样就可以避免这个问题。另外我们可以用宏定义方便后续的修改(比如扩展成更大的棋盘)再继续分析,我们在棋盘上布置了雷,棋盘上雷的信息(1)和⾮雷的信息(0),假设我们排查了某 ⼀个位置后,这个坐标处不是雷,这个坐标的周围有1个雷,那我们需要将排查出的雷的数量信息记录 存储,并打印出来,作为排雷的重要参考信息的。那这个雷的个数信息存放在哪⾥呢?如果存放在布 置雷的数组中,这样雷的信息和雷的个数信息就可能或产⽣混淆和打印上的困难。 这⾥我们肯定有办法解决,⽐如:雷和⾮雷的信息不要使⽤数字,使⽤某些字符就⾏,这样就避免冲 突了,但是这样做棋盘上有雷和⾮雷的信息,还有排查出的雷的个数信息,就⽐较混杂,不够⽅便。 这⾥我们采⽤另外⼀种⽅案,我们专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期 排查参考。 同时为了保持神秘,show数组开始时初始化为字符 '*',为了保持两个数组的类型⼀致,可以使⽤同⼀ 套函数处理,mine数组最开始也初始化为字符'0',布置雷改成'1'。

#define ROW 9
//定义九的原因是打印的棋盘是9*9但是统计时
//会越界因为雷在周边时统计附近雷的个数会越界所以
//我们行和列分别多加两行
#define COL 9
#define ROWS ROW+2//这里是实际存放的数组+2是防止越界
#define COLS COL+2

 下面进行数组初始化了(第一步了加油加油)

void intiboard(char arr[ROWS][COLS], int rows, int cols, char ser)
//这边是函数初始化输入'0'和'*'由ser来判断,这一点很巧妙,要不然重新输入一组麻烦还出错。
{
	int i = 0;
	for (i = 0; i < rows; i++) {
		int j = 0;
		for (j = 0; j < cols; j++) {
			arr[i][j] = ser;
		}
	}
}

 函数初始化了就得打印出来看,对吧所以这里有自定义函数

void prinboard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("----------扫雷开始----------\n");
	for (i = 0; i < col; i++)
	{
		printf("%2d", i);
	}
	printf("\n");
	for (i = 1; i < row;i++)
	{
		printf("%2d", i);
		int j = 0;
		for (j = 1; j < col; j++)
		{
			printf("%2c", arr[i][j]);//%2d是为了更好看也能承受两位数数组导致的不整齐
		}
		printf("\n");
	}
}

void wsmbjr(char arr[ROWS][COLS], int row, int col)
{
	int count = XLNY ;//XLNY是为了让雷的数量可以随意改变所以用宏定义
	int x = 0;
	int y = 0;
	while(count)
	{
			x = rand() % 9 + 1;
//这里%9  一个数除9余数是0到8所以我们加1就得到了1到9(打印出来的棋盘是从1到9并且雷也是)
		y = rand() % 9 + 1;

		if (arr[x][y] == '0') {
			arr[x][y] = '1';
			count--;//当雷的个数到0时循环停止
		}
	}
	
}

 你点的那里如果没有雷那么会统计附近一圈雷的个数,然后返还给你点的位置,以此进行推理判断。

  •  这里的0和1都是字符所以不能直接进行普通的加减.这里我们就要知道如何进行换算。
  • 字符0到9的ASCII值是48到57,也就是说字符1减去字符1等于1。这里也可以轻易得出数字字符减去0就得到了这个数字。
int rcdborad(char mine[ROWS][COLS], int x, int y)
// 定义一个函数进行对周围的一个排查,然后进行一个累加返还雷的个数。
{
	int cot = 0;//初始化附近雷的个数
	cot= (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');
	return cot;//返还雷的个数

}

 下面进行雷的排查了哈哈;

 

void chkkmnl(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
//这边定义查找函数进行判断你输入的坐标是否为雷,不是则继续。
{
	int x = 0;
	int y = 0;
	int w = 0;
	while (w<row*col- XLNY)//游戏胜利的条件是所有雷都排了下来。这里进行
                           //循环当只剩雷时括号式为零循环结束游戏胜利
	{
		printf("请输入你的坐标:");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (mine[x][y] == 1) {
				printf("恭喜你被炸死了:哈哈");
				prinboard(mine, row, col);//这里炸死后可以看到雷在哪
				break;
			}
			else {
				int cots = rcdborad(mine, x, y);//
				show[x][y] = cots + '0';
				prinboard(show, row, col);
				w++;
			}
		}
		else {
			printf("输入错误!!!");
		}
	}
}

 最后放上最后函数族主体的代码

#include "game.h"
void intiboard(char arr[ROWS][COLS], int rows, int cols, char ser)
{
	int i = 0;
	for (i = 0; i < rows; i++) {
		int j = 0;
		for (j = 0; j < cols; j++) {
			arr[i][j] = ser;
		}
	}
}
void prinboard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("----------扫雷开始----------\n");
	for (i = 0; i < col; i++)
	{
		printf("%2d", i);
	}
	printf("\n");
	for (i = 1; i < row;i++)
	{
		printf("%2d", i);
		int j = 0;
		for (j = 1; j < col; j++)
		{
			printf("%2c", arr[i][j]);
		}
		printf("\n");
	}
}
void wsmbjr(char arr[ROWS][COLS], int row, int col)
{
	int count = XLNY ;
	int x = 0;
	int y = 0;
	while(count)
	{
			x = rand() % 9 + 1;
		y = rand() % 9 + 1;

		if (arr[x][y] == '0') {
			arr[x][y] = '1';
			count--;
		}
	}
	
}
int rcdborad(char mine[ROWS][COLS], int x, int y) {
	int cot = 0;
	cot= (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');
	return cot;

}
void chkkmnl(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int w = 0;
	while (w<row*col- XLNY)
	{
		printf("请输入你的坐标:");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (mine[x][y] == 1) {
				printf("恭喜你被炸死了:哈哈");
				prinboard(mine, row, col);
				break;
			}
			else {
				int cots = rcdborad(mine, x, y);
				show[x][y] = cots + '0';
				prinboard(show, row, col);
				w++;
			}
		}
		else {
			printf("输入错误!!!");
		}
	}
}

3.函数声明部分以及宏的定义(game.h)

#pragma once//防止类型重复出错
#include <stdio.h>
#include <stdlib.h>//这个头文件放在这里,然后其他的文件间包含这个头文件,
//就相当于包含了这里的所有文件
#include <time.h>//使用srand函数时需要一个种子生成随机数time就是这个种子,
//使用time时要包含这个头文件

#define ROW 9
//定义九的原因是打印的棋盘是9*9但是统计时
//会越界因为雷在周边时统计附近雷的个数会越界所以
//我们行和列分别多加两行
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define XLNY 10
void intiboard(char arr[ROWS][COLS],int rows,int cols,char ser);//初始化填入0和*
void prinboard(char arr[ROWS][COLS], int row, int col);//打印棋盘
void wsmbjr(char arr[ROWS][COLS], int row, int col);//填入雷
void chkkmnl(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);//排查雷

 最后谢谢大家看到这里希望我的文章可以给你们带来一点点的帮助谢谢大家O(∩_∩)O

 

  • 39
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值