C语言初阶习题(4数组)【20】扫雷游戏

1.用C语言实现扫雷游戏

本博客和三子棋游戏比较大的区别是,三子棋游戏是写完了再总结的,本博客是边代码实现边编辑博客,所以本博客会比较详细的po出每一步骤,在每实现一个小功能的时候我们都先验证下效果,再继续下一步。

2.思路

总体的思路和三子棋游戏是一样的,我们把游戏实现部分放在game.c和game.h中,把游戏的测试代码放到test.c中。main函数在test.c中。
小tips:我们把需要包含的头文件都放在game.h中,game.c和test.c中只需要包含我们的game.h一个头文件即可。

2.1 test.c函数实现

2.1.1 main()函数和test()函数实现

在main函数中只简单调用我们的test()函数,在test()函数中打印游戏菜单,实现让玩家选择开始游戏还是结束游戏。

  • game.h中的代码实现
#pragma once //这个是我创建.h文件的时候自动出现的,不是自己手敲的
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
  • test.c中的代码实现
#include "game.h"
void manu()
{
   
	printf("===========================\n");
	printf("========1:开始游戏=========\n");
	printf("========0:结束游戏=========\n");
	printf("===========================\n");
}
void test()
{
   
	int input = 0;
	do
	{
   
		manu();
		printf("请输入您的选择:\n");
		scanf("%d", &input);
		switch(input)
		{
   
			case 1:
				//game(); 因为还没有实现game()所以这里我屏蔽掉了。
				break;
			case 0:
				printf("游戏结束,欢迎下次再来!\n");
				break;
			default:
				printf("您的输入有误,请重新输入:\n");
		}
	} while (input);
}
int main()
{
   
	test();
	return 0;
}
  • 验证

在这里插入图片描述

2.1.2 test.c中的game()函数实现思路

设计扫雷游戏之前,先进行思考

  1. 创建地图,9*9的二维数组,元素类型是什么?
  2. 每个格子的状态有以下状态
    a)未翻开(草地)
    b)已翻开(数字)
    c)是地雷
    d)不是地雷
    四种状态是两大类,我们用两个二维数组表示。
    第一个数组表示翻开状态showMap:
    char类型表示,如果是 * 表示未翻开 ; 如果是阿拉伯数字,就表示翻开
    第二个数组表示是否地雷状态mineMap:
    char 类型表示 如果是 【1】:表示是地雷 【0】:表示不是地雷 、 也可以int 类型表示 如果是数字1:地雷; 数字0:不是地雷
  3. 这里还有个需要考虑的是虽然9×9数组是我们的目标,但是在边角位置,我们要对周围8个位置进行数雷的个数,非常容易数组越界,这里的解决思路有两个,其一是每次都需要判定我们的翻开位置是否是边角位置,这样比较繁琐。其二是直接创建两个11×11的数组,这样我们使用我们9*9的地图的时候就没有这个风险。这里使用的是第二个思路。

扫雷游戏的思路

  1. 先创建地图(两个地图一个是我们放雷的地图mineMap,一个是我们的展示地图showMap),并进行初始化
    a)针对showMap 默认初始化全是 *,表示未知,等待玩家翻开
    b)针对mineMap 默认初始化都是字符’0’,之后我们初始化10个地雷(根据随机位置来摆放) 没地雷用字符’0’ 表示,地雷位置用字符’1’表示
  2. 打印地图showMap
  3. 给mineMap地图布置雷。
  4. 排查雷
    a)提示玩家输入要翻开的位置坐标,并进行校验
    b) 判定当前位置是否是雷,如果是雷则游戏失败,游戏结束
    c) 如果当前位置是最后一个“不是雷的格子”那么游戏胜利,游戏结束
    d)如果不是雷,更新翻开的当前位置,把【* 】替换成一个数字(就把showMap中对应位置的 * 修改成一个具体的数字)这个数字要根据当前位置周围8个格子的地雷数目来决定。
  5. 下一步从2继续开始,直到游戏结束。

2.2 test.c中的game()函数和game.c中的函数实现

2.2.1 地图创建

  • 在test.c中的game()函数中创建两个char类型的二维数组,需要设置两个全局变量,我们放在game.h中,这里我们先设置两个为9的行和列,由于我们为了避免数组越界所以又定义了一个,MAX_ROW和MAX_COL变量,这样设置,之后打印的时候不需要写很多个9了,直接用这个全局变量。
//game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1

#define ROW 9
#define COL 9
#define MAX_ROW ROW+2
#define MAX_COL COL+2

#include <stdio.h>
//test.c
void game()
{
   
	//1.地图创建
	char showMap[MAX_ROW][MAX_COL] = {
    0 };
	char mineMap[MAX_ROW][MAX_COL] = {
    0 };
}

2.2.2 地图初始化

  1. game函数中只需要调用init函数,init函数的实际的实现在game.c中。
void game()
{
   
	//1.地图创建
	char showMap[MAX_ROW][MAX_COL] = {
    0 };
	char mineMap[MAX_ROW][MAX_COL] = {
    0 };
	//2.地图初始化
	init(showMap, MAX_ROW,MAX_COL,'*');
	init(mineMap, MAX_ROW, MAX_COL, '0');
}

  1. init函数具体实现

先在game.h中声明

//game.h
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char i);

然后在game.c中具体实现
可以用for循环,也可以使用库函数memset,这里因为我们需要初始化两个数组,但是两个数组的内容不同,所以给init函数添加了一个参数,用来传入我们要初始化的值。

//game.c
//1.地图初始化
void init(char board[MAX_ROW][MAX_COL], int row, int col, char set)
{
   
#if 0
	int i = 0;
	int j = 0;
	for (i = 0; i < col; i++)
	{
   
		for (j = 0; j < col; j++)
		{
   
			board[i][j] = set;
		}
	}
#endif 
	
	memset(board, set, row * col * sizeof(char));
}

2.2.3 地图打印

  1. game函数中只需要调用Print函数,Print函数的实际的实现在game.c中。
//test.c
void game()
{
   
	//1.地图创建
	char showMap[MAX_ROW][MAX_COL] = {
    0 };
	char mineMap[MAX_ROW][MAX_COL] = {
    0 };
	//2.地图初始化
	init(showMap, MAX_ROW,MAX_COL,'*');
	init(mineMap, MAX_ROW, MAX_COL, '0');
	//3. 地图打印
	Print(showMap, ROW, COL); //打印地图我们只需要9行9列
	Print(mineMap, ROW, COL);
}
  1. Print函数具体实现

先在game.h中声明

//game.h
//1.地图初始化
void init(char showMap[MAX_ROW][MAX_COL], int row, int col, char set);

//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col);

在game.c中具体实现

第一版本

//game.c
//2.地图打印
void Print(char board[MAX_ROW][MAX_COL], int row, int col)
{
   
	//我们只需要打印9*9的,但是我们必须用11*11的接收,
	// 因为数组的存储方式决定了,我们不可能只单单把中间元素取出来,只能按顺序取
	int i = 0;
	int j = 0;
	for (i = 1; i < row-1; i++)
	{
   
		for (j = 1; j < col
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值