解构童年游戏--经典版扫雷

我们前面已经学习了c语言的函数与数组,那么我们能不能用我们所学的知识复原童年游戏呢?当然可以!今天我将带大家一起回味童年,解构扫雷。

我们首先整理一下我们的思路,我们需要制作一个可以一直玩的游戏框架,这就与我们前期制作的猜数字游戏一个原理,可以使用do...while循环,再打印一个菜单,输入相应数字进行开始或结束游戏。

int main() {
	int a;
	do {
		menu();//菜单
		scanf("%d",&a);
		switch (a) {
		case 1:
			game();//游戏设计
		case 0:
			printf("游戏结束\n");
			break;
		default :
			printf("输入有误,请重新输入:\n");
		}
		
	} while (a);
}

我们在做一个项目时有时候多人协作,代码都写在一个文件上很降低我们的效率,这时候我们可以将项目分在不同的文件。在扫雷项目中我将分为三个文件,分别是头文件game.h用于存放需要的各种头文件,源文件game.c用于存放游戏设计,test.c用于放我们的主函数以及测试。在源文件中我们要引用我们自定义的头文件game.h

下面我们来学习游戏设计

首先我们要制作我们的扫雷棋盘,这里我们可以用二维数组实现,同时将里面统一初始化;但是我们需要存放的雷不被玩家看到,这时候我们就需要制作一个让玩家看到的棋盘,所以这里我们要制作两个数组棋盘,我们命名为mine和show数组。

char mine[ROWS][COLS];
char show[ROWS][COLS];

我们再做一个函数,任务是初始化数组

void InitBoard(char arr[ROWS][COLS], int r, int c, char set) {
	for (int i = 0;i < r;i++) {
		for (int j = 0;j < c;j++) {
			arr[i][j] = set;
		}
	}
}
//ROWS和COLS代表着行和列,我们可以在头文件中定义
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//在我们的数组中需要9*9的,但是我们如果要进行排雷时边缘会没有格子,就要特殊计算,为降低复杂度,我们干脆创建一个11*11的,只要保证雷不在四周就可以
//我们在mine数组中存放雷的信息,在show数组中显示给玩家看,所以两个数组的初始化是不同的,我们加上字符set可以对于不同的数组做出不同的赋值
//接下来在test.c的game函数中调用即可
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');

初始化数组后我们还要打印棋盘

void printboard(char arr[ROWS][COLS], int r, int c) {
	printf("-----扫雷------\n");
	for (int i = 0;i <= r;i++) {
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1;i <= r;i++) {
		printf("%d ", i);
		for (int j = 1;j <=c;j++) {
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}
//我们在打印棋盘前加上扫雷的提示会显得更加美观
//由于我们制作的是简易扫雷,所以在每行每列前面加上行数列数便于玩家查找

打印完棋盘后我们接下来在我们的mine数组中埋雷

void setboard(char arr[ROWS][COLS], int r, int c) {
	int count = numlei;//与我们的ROW一样,常数可以在头文件中进行定义赋值,也便于修改
	while (count) {
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (arr[x][y] != '1') {//在mine数组中,我们用字符'1'表示雷,'0'表示不是雷
			arr[x][y] = '1';//如果不是雷就随机赋值为雷,如果已经是雷则不做处理,直到布置十个雷
			count--;
		}
	}
}
//由于我们是随机埋雷,就需要用到前面的rand函数知识点,同样在test.c文件中种下“种子”
int main() {
	int a;
	srand((unsigned int)time(NULL));//强制类型转换
}

布置完雷后我们就准备开始最刺激的排雷了,这个游戏的核心!

int lei(char mine[ROWS][COLS], int x, int y) {//lei函数用于/判断周围有多少个雷
	int n=0;
	for (int i = -1;i <= 1;i++) {//我们只需要判断我们的四周8个位置,可以确定x,y坐标不是雷,所以可以直接用循环
		for (int j = -1;j <= 1;j++) {
			if (mine[x+i][y+j] == '1') {
				n++;
			}
		}
	}
	return n;
}
void findboard(char mine[ROWS][COLS], char show[ROWS][COLS], int r, int c) {
	int x, y;//雷的坐标
	int n=0 ;
	do {
		printf("请输入雷的坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= r && y >= 1 && y <= c) {//用于判断输入的坐标是否合法
			if (mine[x][y] == '1') {
				printf("很遗憾,你踩到雷了\n");
				printf("如果想继续玩可重新选择\n");
				printboard(mine, ROW, COL);//在玩家游戏失败后展示一下哪些位置有雷,不然死不瞑目了
				break;
			}
			else {
				if (show[x][y] == '*') {//判断该位置是否已经被排查过
					int c = lei(mine, x, y);//lei函数用于/判断周围有多少个雷
					show[x][y] = c + '0';//由于我们存放的是字符,用到我们的ACSII码值,字符数字是连续排序的
					printboard(show, ROW, COL);//将排查后的棋盘重新打印一遍
					n++;
				}
				else {
					printf("此坐标已经被排查过\n");
				}
				
			}
		}
		else {
			printf("坐标输入有误,请重新输入:\n");
		}
	} while (n<r*c- numlei);//当所有不是雷的位置都排查出来则跳出循环
	if (n == r * c - numlei) {
		printf("恭喜你,排雷成功,你简直是神!!!\n");//此处我们可以随便输入一些有趣的
		printf("如果想继续玩可重新选择\n");
	}
}

这样我们的game.c的整个设计都设计好了,前面可知我们每个函数和常量的定义都在我们的头文件game.h中,所以在game.c创建的函数都要在game.h里声明,以下就是我们需要用到的头文件以及函数声明,这样在test.c文件里直接调用game.c里的函数

#include<stdio.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define numlei 10
void InitBoard(char arr[ROWS][COLS],int r,int c,char set);//初始化
void printboard(char arr[ROWS][COLS], int r, int c);//打印
void setboard(char arr[ROWS][COLS], int r, int c);//设置雷
void findboard(char mine[ROWS][COLS],char show[ROWS][COLS], int r, int c);//查找雷

以上就是我们整个基础扫雷的所有代码了,当然游戏还有很多可以改进的地方,在主包后续更新更多的编程知识大家也可以进行改良与创新,主包也会与你们一同进步共同学习的!

在线扫雷游戏:http://www.minesweeper.cn/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值