C语言初阶——扫雷游戏(函数,数组实现)

效果展示

第一次写应该会有点累赘。下面是最终实现:

20240201-0543-02.3771370

目录

效果展示

整体思路

1. 头文件

2. 打印菜单

3. game函数--游戏实现(核心)

(1)game函数整体  

(2)初始化函数,双循环赋值。

(3)打印函数,以下是初始化控制台显示

(4)埋雷函数 

(5)玩家操作

​编辑​编辑

 Kai函数用递归实现:

(6)选择难度(我是通过改变game函数的参数再分别放入副菜单啦。谢谢大家了。


20240201-0543-02.3771370

整体思路

首先创建两个字符数组,一个用来存储数据,另一个负责打印显示到控制台。考虑用‘1’表示雷,‘0’表示非雷,因为这样方便后续纪录雷的数量,为了方便同时防止后续记录雷数量时越界,会多加两行两列赋值为’0‘不可修改 作为边界。

1. 头文件

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//简单
#define ROW 9
#define QUEUE 9
#define ROW1 ROW + 2
#define QUEUE1 QUEUE + 2
#define LANDMINE 10
//中等
#define ROWII 16
#define QUEUEII 16
#define ROWII1 ROWII + 2 
#define QUEUEII1 QUEUEII + 2
#define LANDMINEII 40
//难
#define ROWIII 16
#define QUEUEIII 30
#define ROWIII1 ROWIII + 2 
#define QUEUEIII1 QUEUEIII + 2
#define LANDMINEIII 99

2. 打印菜单

副菜单用来选择难度

int main()
{

	do
	{
		srand(time(NULL)); //用于生成随机值后续埋雷用
		menu();
		int E = 0;
		scanf("%d", &E);
		system("cls");     //用来清屏
		switch (E)
		{
		case 1:
			game();        //游戏实现
			break;
		case 2:
			return;
		case 3:
			E = nan_du();  //链接副菜单
		default:
			if(E != 6)     //副菜单调用结束返回6进入主菜单
			printf("输入错误,请重试!\n");
		}
	} while (1);
    return 0;
}

//主菜单
void menu()
{
	printf("\n");
	printf(" ____________________________扫雷小游戏______________________________\n ");
	printf("|  1. PLAY(默认简单)  ||   2. EXIT    ||  3. 选择难度  ||  请选>>: ");
}
//副菜单
int nan_du()
{
	while (1)
	{
		printf("\n");
		printf(" _____________________________难度选择___________________________\n ");
		printf("|   1. 中等     ||   2.  难     ||   3. 返回   || 请选>>:");
		int i = 0;
		scanf("%d", &i);
		system("cls");  
		switch (i)
		{
		case 1:
			//把传参数据改一下
			gameII();
			return 6;
		case 2:
			gameIII();
			return 6;
		case 3:
			return 6;
		default:
			printf("输入错误,请重试!\n");
		}
	}
}


3. game函数--游戏实现(核心)

(1)game函数整体  

    

void game()
{
	printf("\n");
	//负责存雷否
	char base[ROW1][QUEUE1];
	//负责控制台显示
	char show[ROW1][QUEUE1];
	// 初始化数组
	initialize(base, ROW1, QUEUE1, '0');
	initialize(show, ROW1, QUEUE1, '*');
	// 埋雷
	landmine(base, LANDMINE, ROW, QUEUE);
    // 打印
	print(show, ROW, QUEUE);
	print(base, ROW, QUEUE);
    // 玩家操作
	realy(base, show, 1);
}

(2)初始化函数,双循环赋值。

// 初始化
void initialize(char diagram[ROW1][QUEUE1], int row, int queue, char ch)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < queue; j++)
			diagram[i][j] = ch;
	}
}

(3)打印函数,以下是初始化控制台显示

void print(char diagram[ROW1][QUEUE1], int row, int queue)
{
	int i = 0;
	printf("                ");
	for (i = 1; i <= queue; i++)
		printf("%-3d", i);
	printf("\n");

	// 打印行数
	printf("               ");
	for (i = 1; i <= queue; i++)
		printf("---");
	printf("-");
	printf("\n");

	//打印的核心
	for (i = 1; i <= row; i++)                    
	{
		int j = 0;
		printf("            %-2d| ",i);  // 打印列数
		for (j = 1; j <= queue; j++)
			printf("%c  ", diagram[i][j]);
		printf("|\n");
	}
	printf("               ");

	for (i = 1; i <= queue; i++)
		printf("---");
	printf("-");
	printf("\n");
}

07e986f27414415aafa5e8158760469b.png

(4)埋雷函数 

void landmine(char diagram[ROW1][QUEUE1],int land, int row, int queue)
{
	int i = land; //传10个雷
	while(i)
	{
		int r = rand() % row + 1;    //负责随机生成 不越界的 横坐标
		int q = rand() % queue + 1;  //负责随机生成 不越界的 纵坐标
		if (diagram[r][q] != '1')    //避免重复在同一位置埋雷
		{
			diagram[r][q] = '1';
			i--;
		}
	}
}

’1‘ 表示雷

923c05b0f5bd45a7975683123e619653.png

(5)玩家操作

//玩家操作
void realy(char diagram[ROW1][QUEUE1], char show[ROW1][QUEUE1],int i)
{
	int X = 0, Y = 0, Z = 0;
	switch (i)  // 这里用来选择难度
	{
	case 1:
		X = ROW; Y = QUEUE; Z = LANDMINE;
		break;
	case 2:
		X = ROWII; Y = QUEUEII; Z = LANDMINEII;
		break;
	case 3:
		X = ROWIII; Y = QUEUEIII; Z = LANDMINEIII;
		break;
	}

	int Count = X * Y - Z;  //总格子数减去雷数 
	while (Count)           //当空白格子全部被展开时,循环停止
	{
		printf("请选择坐标>>;");
		int x = 0, y = 0;
		scanf("%d,%d", &x, &y);
		system("cls");
        
        //判断是否触雷
		if (diagram[x][y] == '1') //游戏结束用'!'显示所有的雷
		{
			for(int i = 1; i <= X; i++)
			{ 
				for (int j = 1; j <= Y; j++)
				{
					if (diagram[i][j] == '1')
						show[i][j] = '!';
				}
			}
		
			print(show, X, Y);
			printf("你已被炸死,失败,游戏结束。\n");
			return;
		}

		else
		{
			
			Kai(diagram, show, x, y, X, Y);  //用于自动展开一片空白格子
			print(show, X, Y);
			Count--;
		}
	}
	printf("恭喜你通关!\n");
}

这里把雷放慢进行检查

e946444e0b5f4fe18b5b85e4c5efd8b8.png8d2e49f86fae4609a7a843090a8747ee.png

f78451d10cd24f32aa34ef829f09062f.pngea51076763b142c5adcdb4c06c096e7e.png

 Kai函数用递归实现:

//计雷数
char num(char diagram[ROW1][QUEUE1],int x, int y)
{
	char h = (diagram[x - 1][y]
		+ diagram[x - 1][y + 1]
		+ diagram[x][y + 1]
		+ diagram[x + 1][y + 1]
		+ diagram[x + 1][y]
		+ diagram[x + 1][y - 1]
		+ diagram[x][y - 1]
		+ diagram[x - 1][y - 1]) - 7 * '0';
	if (h != '0')
	{
		return h;
	}
	else return ' ';
}

//开图
void Kai(char diagram[ROW1][QUEUE1], char show[ROW1][QUEUE1], int x, int y, int row, int queue)
{
	if ((x >= 1 && x <= row) && (y >= 1 && y <= queue)) //防止越界访问
	{
		char count = num(diagram, x, y);  //调用num判断此坐标周围有没有雷。
		if (' ' == count)
		{
			show[x][y] = ' ';

           // 双循环递归判断8个方向
			for (int i = x - 1; i <= x + 1; i++)
			{
				for (int j = y - 1; j <= y + 1; j++)
				{
					if ('*' == show[i][j])              //避免重复
					{
						Kai(diagram,show, i, j, row, queue);
					}
				}
			}
		}

		else
		{
			show[x][y] = count;
		}
	}
}

然后就可以自动展开啦!

ee11f93f463348fdb7d0ea1466ccf47b.png0cdf3aca12f5429fa7bad9c62f50fb2c.png

(6)选择难度(我是通过改变game函数的参数再分别放入副菜单啦。谢谢大家了。

void game()
{
	printf("\n");
	//负责存雷否
	char base[ROW1][QUEUE1];
	//负责控制台显示
	char show[ROW1][QUEUE1];
	// 初始化数组
	initialize(base, ROW1, QUEUE1, '0');
	initialize(show, ROW1, QUEUE1, '*');
	// 埋雷
	landmine(base, LANDMINE, ROW, QUEUE);
	print(show, ROW, QUEUE);
	print(base, ROW, QUEUE);
	realy(base, show, 1);
}

void gameII()
{
	printf("\n");
	char base[ROWII1][QUEUEII1];
	char show[ROWII1][QUEUEII1];
	initialize(base, ROWII1, QUEUEII1, '0');
	initialize(show, ROWII1, QUEUEII1, '*');
	landmine(base, LANDMINEII, ROWII, QUEUEII);
	print(show, ROWII, QUEUEII);
	print(base, ROWII, QUEUEII);
	realy(base, show, 2);
}

void gameIII()
{
	printf("\n");
	char base[ROWIII1][QUEUEIII1];
	char show[ROWIII1][QUEUEIII1];
	initialize(base, ROWIII1, QUEUEIII1, '0');
	initialize(show, ROWIII1, QUEUEIII1, '*');
	landmine(base, LANDMINEIII, ROWIII, QUEUEIII);
	print(show, ROWIII, QUEUEIII);
	print(base, ROWIII, QUEUEIII);
	realy(base, show, 3);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ヾ慈城

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

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

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

打赏作者

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

抵扣说明:

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

余额充值