扫雷游戏的制作

思路/思想

代码

思路/思想

  1. 函数的使用思想
  2. 该位置周围地雷的个数与是否为地雷应该如何区分开
  3. 在判断周围地雷个数时候怎么解决越界问题
  4. 为什么需要设置ROWS 与 COLS 而不是直接传入参数 11
  5. 如何初始化棋盘
  6. 怎么随机设置地雷
  7. 如何寻找地雷
  8. 当周围地雷为0时候如何平铺展开

函数的使用思想

由于有一部分代码会 重复出现(打印用户界面的棋盘、输入查看位置的下标…),如果重复写那么就会冗余,不仅分析代码的时候会很麻烦,而且修改代码的时候需要重复修改,所以要使用函数。


在该位置周围地雷的个数与是否为地雷应如何区分开

可以设置两个不同的二维数组,一个用来存放地雷的下标(程序员检查代码可以查看),另一个用来存放周围地雷的个数(用户界面)


在判断周围地雷个数时候怎么解决越界问题

假设我们是需要打印 9(ROW) * 9(COL) 范围的棋盘,可以设置 11 (ROWS)* 11(COLS) 的数组(在周围加上一圈)其中 ROWS = ROWS + 2 , COLS = COL + 2


为什么需要设置ROWS 与 COLS 而不是直接传入参数 11

这样可以降低代码修改时的冗余,如果直接传入参数 11,那么当要修改的时候(也就是棋盘变大)就要将所有的 11 都修改,而使用宏,那么就只需要修改一处即可


如何初始化棋盘

首先,因为需要初始化的棋盘的大小是 ROWS * COLS 那么传入的数组大小也是应该为 ROWS * COLS,
由于需要初始化不同的棋盘(元素的个数不一样),那么设置函数的时候就应该专门为其设置一个变量来替代它 代码


怎么随机设置地雷

  1. 如何设置地雷:可以用一个 count 变量来表示,当该位置没有设置过地雷时,就可以设置,然后 count - 1,否则继续循环,直到 count 为0的时候
  2. 如何随机:需要引入 <stdlib.h> 和 <time.h>,前者可以设置伪随机,后者可以用来设置时间戳。由于是伪随机,而rand 默认种子为1,不设置那么就不会改变,所以先调用 srand 来改变种子,而srand的传入的参数就是用时间戳 代码


如何寻找地雷(重要)

  1. 由于需要判断地雷的位置和返回地雷的个数,那么就需要分别传入数组 inner(内部,用来存放地雷的位置)和 show(外部,用来存放周围地雷的个数
  2. 由于需要重复输入下标,所以用循环
  3. 两种退出条件:一种的被炸死,另一种是玩家胜利
  4. 玩家炸死:当输入的下标与地雷的下标相等时,就退出循环,并打印 inner
  5. 如何判断玩家胜利:I. 当剩余的个数为零时候可以退出。 II. 当原来的字符全被替换的时候即可退出(不推荐,因为每输入一个数就要遍历一次,增加运行时间,所以下面思路主要是前一个功能的实现
  6. total_count(总共剩余的个数) = ROW * COL - MINE_COUNT (地雷的个数),如果输入坐标合法且不是地雷,那么 total_count减1,循环输入,直到 total_count = 0 时候即可退出
  7. 如何判定合法:I. 下标不越界。 II. 下标不重复输入 代码


当周围地雷为0时候如何平铺展开

  1. 知识点:递归指针
  2. 条件:I. 该位置没有地雷。II. 该位置是没有查询过(如果没有这个,假如上下都没有地雷,那么就会重复递归,也就形成了死递归)
  3. 当该位置没有地雷时, 就要递归四周的位置,直到遇见地雷边界
  4. 每次递归后,由于会查询该位置,total_count 就要减1
  5. 如何使total_count减1:由于要影响到外部的total_count,所以需要传入指针 代码


代码

全部的代码(gitee仓库)

如何初始化棋盘

//由于是初始化整个数组,所以传入 rows cols, set 为需要初始化为什么的参数
void init_board(char arr[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++) {
			arr[i][j] = set;
		}
	}
}

返回


怎么随机设置地雷

void set_mine(char arr[ROWS][COLS], int row, int col) {
	int count = EASY_MINE;//是地雷的总个数
	int x = 0;
	int y = 0;
	while (count) {
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (arr[x][y] == '0') {//防止重复
			arr[x][y] = '1';
			count--;
		}
	}

返回


如何寻找地雷(重要)

void find_mine(char inner[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
	int x = 0;
	int y = 0;
	int time = 0;
	int total_count = row * col - EASY_MINE;
	while (total_count)
	{	
		int flag = 0;
		printf("请输入下标(行/列):>");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (show[x][y] == '*') {
				if (inner[x][y] == '1') {
					printf("很遗憾,你被炸死了 (x.x)\n");
					print_board(inner, ROW, COL);
					break;
				}
				else {
					//由于会在repeat_board函数中替换掉,但是又不能在函数里先减去(否则会多减)
					//所以total_count现在这里减去1
					total_count--;
					repeat_board(inner, show, x, y, &total_count);//平铺的函数
					print_board(show, ROW, COL);//打印棋盘
					printf("请输入下标(行/列):>");
				}
			}
			else {
				printf("该位置已经被排查,请重新输入 < (-︿-)> \n");
			}
		}
		else
		{
			printf("下标越界,请重新输入!< (-︿-)> \n");
		}
	}
	if (total_count == 0) {
		printf("恭喜你,成功通关!(^▽^)\n");
		print_board(inner, ROW, COL);
	}
}

返回


当周围地雷为0时候如何平铺展开

void repeat_board(char inner[ROWS][COLS], char show[ROWS][COLS], int x, int y, int* total_count) {
	
	int row = ROW;
	int col = COL;
	int num = mine_num(inner, x, y);//求周围地雷的个数
	show[x][y] = num + '0';
	int count1 = 0;
	if (num == 0) {
		int i = 0;
		for (i = x - 1; i <= x + 1; i++) {
			int j = 0;
			for (j = y - 1; j <= y + 1; j++) {
				//该位置没有调查过,且该位置没有越界
				if (show[i][j] == '*' && i >= 1 && i <= row && j >= 1 && j <= col) {
					*total_count -= 1;
					repeat_board(inner, show, i, j, total_count);
				}
			}
		}
	}
}

返回

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值