c语言扫雷

雷盘可拓展,我们这里以9*9做示范=)

1.首先管他三七二十一先写出一个简易的游戏菜单=)

void menu()//游戏菜单界面
{
	printf("****************************************************\n");
	printf("*********输入1开始游戏     输入0退出游戏************\n");
	printf("****************************************************\n");
}

(这个东西写出一个后,之后再用直接cv就可=)我就是复制以前的哈哈)


行了,到这里,咱们来回想一下扫雷的游戏过程

剖析一下就是:

  1. 游戏先布置雷
  2. 我们通过点击来查找雷(我目前还不知道怎么实现点击(哭),就只能以输入坐标的形式了)
  • 若是周围没雷,就会延伸出一大片(敲黑板划重点啦!!!这块是扫雷的难点)
  • 如果点的地方刚好是雷,你就死翘翘啦
  • 如果周围有雷,就会显示九宫格内的雷的数量(这里也要划下重点捏)
  1. 如何判断周围有雷呢?
  • 就是以点击的该点位置为中心,判断周围8个格子
  • 但是,我们如果要用代码实现的话,就是用二维数组创建雷盘,那么在所生成的雷盘边边处,它其中的某一下标已经是0了,若我们要判断周围,则会导致部分的数组越界啦!所以,聪明的人类选择在雷盘周围扩大一格,就像侵染一样,长宽各增长2格(上下和左右均扩大一格了哦)
  • 总结就是,我们真正创建的数组行和列都要比实际看到的+2(我们在打印的时候还是生成9*9哈)
  • 所以,我们打印时的i变量和j变量都得从1开始(这是我常用的for循环变量)

c语言扫雷_第1张图片c语言扫雷_第2张图片

 

 就像是这样的关系(右图是我们看到的雷的布局,左图是实际的布局)

for (i = 0; i < h; i++) {
	for (j = 0; j < l; j++) {
		printf("%d ", orgin[i][j]);
	}
	printf("\n");
}

for (i = 1; i <= hh; i++) {
	for (j = 1; j <= ll; j++) {
		printf("%d ", orgin[i][j]);
	}
	printf("\n");
}

 代码中有用到我宏定义的常量

#define _CRT_SECURE_NO_WARNINGS

#define hh 9
#define ll 9
#define bomb 10

#define h hh+2
#define l ll+2

#include
#include
#include

int orgin[h][l];
char show[h][l];

void init(int m, int n);
void lay(int m, int n);
void display(int m, int n);
void seek(int m, int n);
void round(int a, int b);
void flag(int a,int b);
  •  hh和ll是我们打印用的,h和l是我们拓展后的数组,这样我们只需要修改hh和ll两处的值(很方便捏)
  • bomb是炸弹的数量

2.之后就是熟悉的初始化啦,但和三子棋有所不同哦

void init(int m, int n) {
	int i = 0, j = 0;
	for (i = 0; i < m; i++) {
		for (j = 0; j < n; j++) {
			show[i][j] = ' ';
			orgin[i][j] = 0;
		}
	}
}
  1. 我们来分析分析扫雷的雷盘布置
  • 首先用一个数组储存放雷的位置(就是那个orgin数组),如果我们直接用该数组打印,那么雷的位置就被我们看到啦,达咩
  • 所以我们应该创建另一个数组专门用来展示(我把它叫做show数组)
  1. 因为在最开始时,雷盘上应该什么都没有,所以展示用的show数组初始化为空格
  2. 放雷的数组先初始化为0,每放一个雷,赋值1

3.还是一样的顺序,该生成雷盘

c语言扫雷_第3张图片

  •  这是我在三子棋的棋盘的基础上修改的(改死我了),但现在看来确实不难(可恶)
  • 我琢磨出的小技巧就是你把实际的数代进去就行,你需要几个,for循环就设置几次,当然如果用到下标的话,还得按照实际再修改修改
void display(int m, int n) {
	int i = 1, j = 0;
	while (i <= ll) {
		printf("   %d", i++);
	}
	printf("\n");
	for (i = 1; i <= m-1 ; i++)//以给定的行数 重复打印
	{
		for (j = 0; j < n-1 ; j++)
		{
			if (j == 0) {
				printf(" ");
			}
			printf("|");

			if (j < n-2)
			{
				printf("---");
			}

		}//打印出分割行
		printf("\n");
		if (i < n-1)
		{//一行的内容
			for (j = 1; j <= n -1; j++)
			{
				if (j == 1&&i<=m-2) {
					printf("%d", i);
				}
				printf("|");
				if (j <= n-2&&i<=n-2)
					printf(" %c ", show[i][j]);
				    /*printf(" %d ", orgin[i][j]);*/

			}//打印出有数据的一行
		}
		printf("\n");
	}
}

4.接下来就该确定雷的位置

void lay(int m, int n) {
	int x = 0, y = 0;
	int count = bomb;
	while (count) {
		x = rand() % hh + 1;
		y = rand() % ll + 1;
		if (orgin[x][y] == 0) {
			orgin[x][y] = 1;
			count--;
		}
	}
}

还是熟悉的配方,还是熟悉的味道,随机数它又来啦!

c语言扫雷_第4张图片

  这是我在五子棋那里解释过的,就不多赘述啦,感兴趣的可以去看看哦

初始化的时候我的orgin数组全为0,那么放一个雷就赋值1

5.接下来就是查找操作

我们首先要确定胜利条件

排除所有的雷我们就胜利啦,因此我们设置一个win变量来计数

void seek(int m, int n) {
	printf("若您在游戏过程中想要标记某点,请您输入该游戏的雷盘行数+1,列数+1\n");

//这是我设置的如何进入标记操作

	int x = 0, y = 0;
	int i = 0, j = 0;
	while (1) {  
		if (win == hh * ll - bomb) {       //获胜条件写最前面,这样满足了直接就出去
			printf("恭喜你获得了胜利!\n");
			printf("是否要重新开始:");
			break;
		}
		printf("\n请输入你要查找的坐标:");
		scanf("%d%d", &x, &y);
		int i = 0, j = 0;
		if (x >= 1 && x <= hh && y >= 1 && y <= ll) {      //保证输入的坐标合法
			if (orgin[x][y] == 1) {
				show[x][y] = '*';    
				display(h, l);
				printf("\n很遗憾,你被炸死了");
				printf("\n是否要重新开始:");
				break;
			}
			else {
				round(x, y);      //没踩到就进入判断函数
				display(h, l);
			}
		}
		else {
			if (x == hh + 1 && y == ll + 1) {     //这里就是我设置的进入标记函数的标志
				flag(h, l);
			}
			else {
				printf("\n输入的坐标非法,请重新输入:");
			}
		}
	}
}

 踩到雷了就把该坐标标记一下然后打印雷盘,可以让你死的明明白白,视觉效果会更好

c语言扫雷_第5张图片

就像这样捏~

在查找的过程中我们还嵌套了不少函数,我们来一一说道说道(display函数前面讲过了哦)

 6.round函数(实现对show函数赋值以及如果周围无雷,向外继续判断)

void round(int a, int b) {
	if (a >= 1 && a <= hh && b >= 1 && b <= ll) {
		int count = find(a, b);
		show[a][b] = count + '0';
		win++;
		if (count == 0) {
			int i = 0, j = 0;
			for (i = a - 1; i <= a + 1; i++) {
				for (j = b - 1; j <= b + 1; j++) {
					if (show[i][j] == ' ') {
						round(i, j);
					}
				}
			}

		}
	}
	
}
  • 当我们排查到有一格的周围没有雷时,我们就需要继续对该格周围的八个格子排查,看是否还存在这样的情况
  • 而对周围每个格子的排查过程和第一次排查的过程相同,因此我们可以写一个递归来完成该操作
  • 而且要注意不能数组越界!!!这很重要!
  • 并且要保证该位置没有被排查过(用if,如果它仍是初始化后的状态,则没有被排查过,因此就可以继续调用round函数,并传入新的下标参数)

7.find函数(用来判断周围格子的雷数并赋值给show)

int find(int a, int b) {
	if(a>=1&&b>=1&&a<=hh&&b<=ll){
		return orgin[a - 1][b - 1] + orgin[a - 1][b] + orgin[a - 1][b + 1] + orgin[a][b - 1] + orgin[a][b + 1] + orgin[a + 1][b - 1] + orgin[a + 1][b] + orgin[a + 1][b + 1];
	}
	else {
		return 0;
	}
}

赋值就通过return实现,用show元素来接收(管他三七二十一,就是暴力的把八个格子的数加起来就行,因为有雷的地方是1,所以和就是雷的数量)

8.最后一个函数啦,flag函数(用来实现标记操作)

void flag(int a, int b) {
	int x = 0, y = 0;
	printf("\n请输入你要标记的坐标:");
	scanf("%d%d", &x, &y);
	if (x >= 1 && x <= hh && y >= 1 && y <= ll) {
		show[x][y] = '?';
		display(h, l);
		if (orgin[x][y] == 1) {
			win++;
		}
	}
	else {
		printf("\n输入的坐标非法,请重新输入:");
	}
}

首先还是要保证坐标合法,标记的地方用?代替,如果标记的地方就是雷的位置,别忘了win++哦

9.最后的最后

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

void menu()//游戏菜单界面
{
	printf("****************************************************\n");
	printf("*********输入1开始游戏     输入0退出游戏************\n");
	printf("****************************************************\n");
}

void game() {
	init(h, l);
	lay(h, l);
	//int i = 0, j = 0;
	//for (i = 1; i <= hh; i++) {
	//	for (j = 1; j <= ll; j++) {
	//		printf("%d ", orgin[i][j]);
	//	}
	//	printf("\n");
	//}
	display(h, l);
	seek(h, l);
}
void test()//游戏流程
{
	srand((unsigned int)time(NULL));
	int a = 0;
	menu();
	do
	{
		scanf("%d", &a);
		switch (a)
		{
		case 1:
			printf("开始我们的游戏吧!\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("请重新输入\n");
		}
	} while (a);
}

int main()//大框架
{
	test();
	return 0;
}

贴一下我的大框架,这个框架也是可以循环利用的哈哈=)

注释的地方是用来测试的,方便我看雷的情况


完结撒花啦~~~

孩子的第二篇博客终于赶出来了,今天一天就栽在扫雷上了(哭)

感谢您的观看哦~如果有什么想法和建议可以直接和我说哦,我会很感谢您的建议(鞠躬)

你可能感兴趣的:(代码小项目,c语言,游戏,游戏程序)