数组和函数实践: 扫雷游戏

嗨,小伙伴们,大家好!还记得电脑桌面里面的扫雷游戏吗?

今天我们就来动手实践一下这款休闲小游戏---扫雷,准备好了吗? 我们开始咯!

1.扫雷游戏分析和设计

1.1扫雷游戏的功能说明

  • 使用控制台实现经典的扫雷游戏

  • 游戏可以通过菜单实现继续玩或者退出游戏

  • 扫雷的棋盘是 9*9的格子

  • 默认随机布置10个雷

  • 可以排查雷

    1.       如果位置不是雷,就显示周围有几个雷
    2.       如果位置是雷,就被炸死 ,游戏结束

       把除10个雷以外的所有非雷都找出来,排雷成功,游戏结束     

 游戏的界面:

开始界面                                              排雷界面                                排雷失败界面

1.2 游戏的分析和设计

为了实现扫雷游戏,我们需要在 9*9 的棋盘上布置雷的信息和排查雷,我们首先想到的就是创建一个 9*9 的数组来存放信息

                                                 

但是边界的位置,我们需要额外设置一个棋盘,在原来棋盘的基础上进行延伸并将其赋予0的数值

          

我们把棋盘设定好后,就可以开始啦

首先,为扫雷游戏创建一个主菜单 menu() 函数,1表示,进入游戏; 0表示,退出游戏

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

接下来,我们到 main 函数中调用 menu() 函数

int main() {
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		menu();
		printf("请选择:(1/0)>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

整体思路清晰后,我们就可以设置棋盘了,我们将棋盘放在game()函数中

第一步,我们要用两个数组,分别存放雷的信息('1'表示这个位置是地雷,'0'表示这个位置无地雷)和存放排查出的雷的信息

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

第二步,我们需要对两个数组初始化

mine数组(布置好雷的数组初始化全为'0',表示这个数组暂时还没有设置地雷)

show数组(初始化全为'*')

	//初始化棋盘
	// mine数组最开始全是'0'
	// show数组最开始全是'*'
	initBoard(mine, ROWS, COLS, '0');
	initBoard(show, ROWS, COLS, '*');

我们新建一个 game.h 的头文件包含所有棋盘与雷的函数声明,并新建一个 game.c 来完成函数的实现,并在测试文件 test.c 文件中完成对扫雷游戏的测试(注意: test.c 文件中包含  game.h)

game.h

我们要先规划好在 game.h 头文件中所包含的内容,首先定义棋盘 的 行列大小 和 隐藏棋盘的大小

首先,在 game.h 的头文件中建一个 初始化函数 ,用来 初始化 我们的两个棋盘

注意啦,这里有四个参数, 我们的棋盘 行 列 还有 字符 ,然后完成对两个棋盘的 初始化

 实际参数的两个函数如下:

完成之后,我们定义一个 DisplayBoard() 函数 来打印我们的棋盘, 并展示"show"这个棋盘,这里要规划好我们的形式参数(只能打印 9*9 的玩家可排查雷的区域)

实际参数的函数:

接下来我们看一下打印效果:

我们知道数组第一位下标为0,那我们可以在第一位打上数字方便后续的排查

设置完棋盘之后,我们就可以布置雷了

定义  SetBoard()  函数,利用 rand() 函数随机埋雷,将 '1' 当做是 雷 '0' 代表 非雷

当然咯,这里虽然是随机埋雷,但是其"种子"相同,即我们每次打开雷的地方相同,这时候,我们在主函数中引入 srand()函数 , 来改变其种子

埋雷后,就该找雷了,我们此时设置 CheckBoard()函数 ,同时传递我们开始所建立的两个棋盘,如果踩到雷即展示所有的雷并退出

我们首先定义一个 EASY_COUNT 表示雷的数量,这里我来赋值为 10

while语句 条件表示为 排查的次数 , row*col 表示 所有的格数,减去雷的值 即为我们 要排查的空白值,将这个值设置为 win。如果 win 与 后面的值相等,说明我们已经找到了所有的空位,剩下的全都是雷,意味着我们扫雷成功,结束游戏

//排查棋盘
void CheckBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
	int x = 0;
	int y = 0;
	int win = 0;//要排查的空白值
	while (win < row*col-EASY_COUNT) {
		printf("请输入要排查雷的坐标:\n");
		scanf("%d", &x);
		scanf("%d", &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {	
			//键盘录入的 x,y 坐标在合法的范围内
			if (mine[x][y] == '1') {
			//该坐标为雷
				printf("很遗憾,你被炸死了!\n");
				DisplayBoard(mine, ROW, COL);
			//打印 mine数组 存放雷的信息
				break;
			//退出循环
			}
			else {
				//该坐标不是雷
				//统计这个坐标周围雷的个数
				int count = CountBoard(mine, x, y);
				show[x][y] = count + '0';
				//在 show数组 中在该坐标处填入数字字符
				DisplayBoard(show, ROW, COL);
				win++;
				//每排查完一次,找到的空位数自加一次
			}
		}
		else {
			//x或y或者x和y的坐标都不合法,重新输入
			printf("输入的坐标有误,请重新输入!\n");
		}
	}

	if (win == row * col - EASY_COUNT) {
//如果 win 与 后面的值相等,说明我们已经找到了所有的空位,剩下的全都是雷
//意味着我们扫雷成功,结束游戏
		printf("恭喜你,排查成功!\n");
		DisplayBoard(mine, ROW, COL);//打印 mine数组存放雷的信息
	}
}

上述中,我们需要新建一个函数来表示周围雷的个数

(Tips: 字符'0'的ASCII码值为48,字符'1'的ASCII码值为49, 字符'2'的ASCII码值为50,'0' - '0' = 0, '1' - '0' = 1, '2' - '0' = 2 ,'4' - '0' = 4, 不难发现,任意一个数字字符字符'0' 相减,可以得到相应的数字)

那么统计这个坐标周围雷的个数,我们只需要把这个坐标周围的八个坐标字符都相加,再和字符'0'相减,就可以得到这个坐标周围雷的个数,把这个数值存放在 count 里面。此时我们需要打印 show 数组, 展示给玩家这个坐标周围雷的个数(字符型),因此,我们需要 count + '0',存入到相应的 show 数组 该点的坐标中

这个时候,简易版的扫雷游戏就完成啦,我们来看看它的实际效果

这里是完整代码:

game.h

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

#define ROW 9	//玩家可以排查雷的行数
#define COL 9	//玩家可以排查雷的列数

#define ROWS ROW+2	//为了防止最底下一层的坐标越界,
					//我们在设计的时候,将数组扩大一圈
#define COLS COL+2	//雷还是布置在中间的 9*9 的坐标上,
					//周围一圈不去布置雷,解决了越界问题

#define EASY_COUNT 10
//初始化棋盘
void initBoard(char arr[ROWS][COLS], int rows, int cols, char set);

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

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

//排查雷
void CheckBoard(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col);

game.c

#include"game.h"

//初始化棋盘
void initBoard(char arr[ROWS][COLS], int rows, int cols, char set) {
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++) {
			arr[i][j] = set;
		}
	}
}

//打印棋盘
void DisplayBoard(char arr[ROWS][COLS], int row, int col) {
	printf("--------------扫雷游戏---------------\n");
	for (int i = 0; i <= row; i++) {
		printf("%d ", i);		//打印一行的 0 1 2 3 4 5 6 7 8 9
	}
	printf("\n");				//打印完之后换行
	for (int i = 1; i <= row; i++) {
		printf("%d ", i);		//打印一列的 1 2 3 4 5 6 7 8 9
		for (int j = 1; j <= col; j++) {
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

//布置棋盘
void SetBoard(char arr[ROWS][COLS], int row, int col) {
	int count = EASY_COUNT;			//布置10个雷
	while (count != 0) {
		int x = rand() % row + 1;	//生成随机坐标
		int y = rand() % col + 1;

		if (arr[x][y] == '0') {		//该坐标为非雷区域
			arr[x][y] = '1';		//将雷布置在此坐标
			count--;				//每布置完一个雷,雷的总数减1
		}
	}
}

//统计这个坐标雷的个数
int CountBoard(char arr[ROWS][COLS], int x, int y) {
	return arr[x - 1][y - 1] + arr[x - 1][y] +
		arr[x - 1][y + 1] + arr[x][y - 1] +
		arr[x][y + 1] + arr[x + 1][y - 1] +
		arr[x + 1][y] + arr[x + 1][y + 1] - 8 * '0';

}


//排查棋盘
void CheckBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
	int x = 0;
	int y = 0;
	int win = 0;//要排查的空白值
	while (win < row*col-EASY_COUNT) {
		printf("请输入要排查雷的坐标:\n");
		scanf("%d", &x);
		scanf("%d", &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {	
			//键盘录入的 x,y 坐标在合法的范围内
			if (mine[x][y] == '1') {
			//该坐标为雷
				printf("很遗憾,你被炸死了!\n");
				DisplayBoard(mine, ROW, COL);
			//打印 mine数组 存放雷的信息
				break;
			//退出循环
			}
			else {
				//该坐标不是雷
				//统计这个坐标周围雷的个数
				int count = CountBoard(mine, x, y);
				show[x][y] = count + '0';
				//在 show数组 中在该坐标处填入数字字符
				DisplayBoard(show, ROW, COL);
				win++;
				//每排查完一次,找到的空位数自加一次
			}
		}
		else {
			//x或y或者x和y的坐标都不合法,重新输入
			printf("输入的坐标有误,请重新输入!\n");
		}
	}

	if (win == row * col - EASY_COUNT) {
//如果 win 与 后面的值相等,说明我们已经找到了所有的空位,剩下的全都是雷
//意味着我们扫雷成功,结束游戏
		printf("恭喜你,排查成功!\n");
		DisplayBoard(mine, ROW, COL);//打印 mine数组存放雷的信息
	}
}

test.c

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include"game.h"
void menu() {
	printf("******************************\n");
	printf("******   1. play  ************\n");
	printf("******   0. exit  ************\n");
	printf("******************************\n");
}
void game() {
	char mine[ROWS][COLS];	//存放布置好的雷
	char show[ROWS][COLS];	//存放排查出雷的信息

	//初始化棋盘
	// mine数组最开始全是'0'
	// show数组最开始全是'*'
	initBoard(mine, ROWS, COLS, '0');
	initBoard(show, ROWS, COLS, '*');

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

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

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

}
int main() {
	srand((unsigned int)time(NULL));
	int input = 0;
	do {
		menu();
		printf("请选择:(1/0)>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误,请重新选择!\n");
			break;
		}
	} while (input);
	return 0;
}

好啦,今天就到这里啦,我们下次再见!

  • 32
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值