扫雷---C语言初阶小游戏(二)

扫雷—C语言初阶小游戏(二)

1.头文件game.h

在头文件的部分,我们得先想清楚我们该如何实现各个步骤,需要哪些函数,这个时候不需要想的太细致,只需有思路,相关参数,返回类型可以之后完善。

在这里,我先提出几个比较核心的问题:
1.如何埋雷,手动埋吗
2.在棋盘(二维数组)中,如何同时把雷的坐标记录好,又把每个坐标周围的雷个数记录好,会引起混乱吗?
3.每个坐标周围的雷个数如何统计?

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

#define EASY_COUNT 10

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//布置雷
void SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

相信看到这里,你一定一脸懵逼 ,没关系,我会在具体的函数实现过程中把每个步骤细节讲到。

2.源文件game.c

首先,我们需要两个二维数组。一个布置雷,一个排查雷也就是玩游戏时看到的界面,会显示被选中格子的周围雷个数)。

为什么要两个二维数组?
很显然,我们需要一个二维数组来存放数据,存什么呢,第一,雷;第二,每个格子周围的雷个数。这样存储看上去并没有什么弊端,因为一个格子如果有雷,就不会显示周围雷个数,所以不会造成一个格子存两种数据。
但是,当我们企图统计每个格子周围的雷个数时,就会变得棘手,我们假定雷为‘1’,无雷区为‘0’,当我们要统计无雷格子周围的雷个数时,遍历四周八个格子,却发现有的格子存着每个格子周围的雷个数,我们在遍历时就要跳过这类格子,只关注有没有雷,这使我们的程序更复杂,可读性也更弱。
所以这里我们使用两个数组,一个布置雷,一个排查雷(显示周围雷数),避免上述问题。

实际上,布置雷的数组不会显示(显示了还玩啥??),玩家只会看到排雷的数组。我们输入我们想排查的坐标,如果正好是雷,就游戏失败,如果不是雷,就显示当前坐标的周围雷个数,一直到所有雷被找出胜利。

在这里,我们初始规定,布置雷数组 初始化为‘0’,雷为‘1’。排查雷数组 初始化为 ‘*’。 所以打开游戏,你会看到满盘的 * 号。

这里还有一个小细节,我们的数组改设置多大?(假设游戏为9*9个格子,10个雷)。实际上,这里设置应该设置11,倒不是为了好看之类的,是因为当我们要统计无雷格子周围的雷个数时,遍历四周八个格子,会存在边缘或角落格子,他们周围根本没有八个格子,这时候我们遍历的条件很肯能就不适合了,当然你可以分类讨论,改一改条件,不过不如把数组上下左右都拓宽一个,只把数据放在中间,这样所有格子周围都有八个格子,不用分类了。

大致思路解决了,接下来我们开始实现:

1.初始化函数

布置雷数组 初始化为‘0’。
排查雷数组 初始化为 ‘*’。
ps:初始化函数只有一个,但我们得调用两次,而且赋值不同,所以初始化的值也要作为参数传入,即定义char set的原因.

void InitBoard(char board[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++)
		{
			board[i][j] = set;
		}
	}
}

2.打印函数

这里我们为了美观,加入了行 ,列序号,毕竟各自太多容易看走眼

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("---------扫雷游戏---------\n");
	//打印列序号
	for (i = 0; i <= col; i++)//列序号
	{
		printf("%d ", i);
	}
	printf("\n");
	
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);//行序号
		
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");

	}
	printf("---------扫雷游戏---------\n");
}

3.布置雷

随机产生雷,并给相应坐标赋值为‘1’.

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
	int cout = EASY_COUNT;
	while (cout)
	{
		//产生随机坐标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			cout--;
		}
	}
}

4.统计周围雷函数

static int get_mine_cou(char mine[ROWS][COLS], int x, int y)
{
	return 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';
		

}

5.排查雷

void FindMine(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("请输入要排查的坐标:>");
		scanf_s("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;
			}
			else
			{
				int cout = get_mine_cou(mine, x, y);
				show[x][y] = cout + '0';//把返回的ASCALL变回数字
				//显示排除查信息
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("坐标不合法,请重新输入\n");
		}
	}
}

3.测试文件test.c

#include"game.h"

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

void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };

	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	DisplayBoard(show, ROW, COL);

	SetMine(mine, ROW, COL);

	FindMine(mine, show, ROW, COL);
}
int main()
{
	int input = 0;

	do
	{
		menu();
		printf("请输入:>");
		scanf_s("%d", & input);
		switch (input)
		{
		case 1:
			game();//扫雷游戏
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			break;
		}
	} while (input);

	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ornamrr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值