扫雷拓展版 新增功能与源码(详解明天发布)

引言:

        扫雷拓展版已经制作完成,约为400-500行代码即可实现,但代码的详解还在制作中,为什么要先发这篇博客呢,因为如果直接看扫雷拓展版的话可能会看不懂,所以先提前告知一下,还有提前把源码发出来,有助于你们的个人理解,然后再通过我的博客来理解,可能更容易理解透彻

        所以:如果想要看明天的扫雷拓展版的教程的话,可以先去看一下基础版的教程(拓展版是基于基础版代码进行改造的,不看基础版可能看代码会有落差)

        这是基础版扫雷的教程链接:C语言制作扫雷游戏(基础版赋源码)-CSDN博客

       拓展版详解教程已发布,链接C语言制作扫雷游戏(拓展版赋源码)-CSDN博客

        那么我先讲一下拓展版新增的功能吧

                                                

新增功能:

        扫雷拓展版已经制作完成,基于基础版新增了3个功能

        1.难度选择

                新增了可以选择难度的功能,分为简单,中等,困难和自定义,如图

        

       

        2. 标记点

        可以对你觉得是雷的点进行标记," ! " 为确定有雷," ? " 为不确定是否有雷,但感觉可能是雷,被标记的点无法进行排雷,这样可以防止排雷时一不小心把你知道的雷排了,如图

        

 

        3.取消标记点

        可以对已经被标记的点进行取消标记,如图

 

注:若选择的是标记和取消标记,会一直重复,直到选择排雷,这就跟扫雷时候一样,你可以一直标点不扫雷,点击后,再进行扫雷判断

 

        4.排雷的展开(涉及dfs)

        基础版的时候,我们都是选一个坐标,返回那个坐标附近有几个雷,并不会展开,而拓展版里,实现了展开,如图

 

功能与网页版区别

        网页版与该拓展版的功能基本基本没有差别

        唯一的差别就是网页版有游玩时间的计时,而拓展版没有(计时涉及知识点过多,就没实现)

 

源代码

        那么,最后,我先把源代码发出来,可以复制过去一直玩玩看,如果觉得可以的话并且想知道怎么实现的,可以来看明天博客哟

        记得看基础版博客C语言制作扫雷游戏(基础版赋源码)-CSDN博客

 

        game.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#define EChang 9//好处是,想更改棋盘大小时候直接改这里就好了,不用在程序里一个个改,方便很多
#define EKuan 9

#define MChang 16
#define MKuan 16

#define HChang 30
#define HKuan 16

#define EChangs EChang+2
#define EKuans EKuan+2

#define MChangs MChang+2
#define MKuans MKuan+2

#define HChangs HChang+2
#define HKuans HKuan+2

#define ELeisum 10
#define MLeisum 40
#define HLeisum 99

void chu(char arr[][100], int hang, int lie, char fu);

void print(char arr[][100], int lie, int hang);

void set(char arr[][100], int hang, int lie, int ge);

void Findlei(char yin[][100], char xian[][100], int lie, int hang, int leisum);

 

        game.c

#define _CRT_SECURE_NO_WARNINGS

#include "game.h"

//初始化棋盘
void chu(char arr[][100],int hang,int lie,char fu)
{
	for (int i = 0; i < hang; i++)
	{
		for (int j = 0; j < lie; j++)
			arr[i][j] = fu;
	}
}

//打印棋盘
void print(char arr[][100], int hang, int lie)
{
	for (int i = 0; i <= lie; i++)
		printf("%2d ", i);
	printf("\n");
	for (int i = 1; i <= hang; i++)
	{
		printf("%2d ", i);
		for (int j = 1; j <= lie; j++)
			printf("%2c ", arr[i][j]);
		printf("\n");
	}
}

//布置雷
void set(char arr[][100],int hang,int lie,int ge)
{
	while (ge--)
	{
		int h = 1 + rand() % hang;
		int l = 1 + rand() % lie;
		if (arr[h][l] == '0')
		{
			arr[h][l] = '1';
		}
		else
			ge++;
	}
}


static void Choose()
{
	printf("******************\n");
	printf("*** 1.标记     ***\n");
	printf("*** 2.取消标记 ***\n");
	printf("*** 0.排雷     ***\n");
	printf("******************\n");
}

static void menubiao()
{
	printf("*********************\n");
	printf("**** 1.?(不确定) ****\n");
	printf("**** 2.!(肯定)  ****\n");
	printf("*********************\n");
}

//标记雷
void Biaolei(char arr[][100],int hang,int lie)
{
	int x = 0, y = 0;
	int type = 0;
	while (1)
	{
		printf("请输入要标记的坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>hang || y<1 || y>lie)
		{
			printf("输入的坐标有误,请重新输入\n");
			continue;
		}
		else if (arr[x][y] == '?' || arr[x][y] == '!')
		{
			printf("该位置已被标记,请重新输入\n");
			continue;
		}
		else if (arr[x][y] != '*')
		{
			printf("该坐标已被排查,无法标记,请重新输入\n");
			continue;
		}
		break;
	}
	menubiao();
	do
	{
		printf("请输入要标记的类型:");
		scanf("%d", &type);
		if (type != 1 && type != 2)
		{
			printf("不存在该选项,请重新输入\n");
			continue;
		}
		break;
	} while (1);

	switch (type)
	{
	case 1:
		arr[x][y] = '?';
		print(arr, hang, lie);
		break;
	case 2:
		arr[x][y] = '!';
		print(arr, hang, lie);
		break;
	}
}

//取消标记雷
void Clearlei(char arr[][100], int hang, int lie)
{
	int x = 0, y = 0;
	int type = 0;
	while (1)
	{
		printf("请输入要取消标记的坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>hang || y<1 || y>lie)
		{
			printf("输入的坐标有误,请重新输入\n");
			continue;
		}
		else if (arr[x][y] != '?' && arr[x][y] != '!')
		{
			printf("该位置未被标记,请重新输入\n");
			continue;
		}
		break;
	}
	arr[x][y] = '*';
	print(arr, hang, lie);
}

//展开
bool vis[100][100];
int fang[8][2] = { {0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
void zhanlei(char yin[][100], char xian[][100], int hang, int lie, int x, int y, int* ge)
{
	if (xian[x][y] != '0')
		return;
	for (int i = 0; i < 8; i++)
	{
		int x1 = x + fang[i][0];
		int y1 = y + fang[i][1];
		if (!vis[x1][y1] && yin[x1][y1] != '1' && x1 >= 1 && x1 <= hang && y1 >= 1 && y1 <= lie)
		{
			(*ge)++;
			xian[x1][y1] = '0';
			vis[x1][y1] = 1;
			for (int i = 0; i < 8; i++)
			{
				if (yin[x1 + fang[i][0]][y1 + fang[i][1]] == '1')
					xian[x1][y1]++;
			}
			zhanlei(yin, xian, hang, lie, x1, y1, ge);
		}
	}
}

//排查雷
void Findlei(char yin[][100], char xian[][100], int hang, int lie,int leisum)
{
	int x = 0, y = 0;
	int ge = 0;
	int biaoji = 0;
	int input = 0;

	while (1)
	{
		do
		{
			system("cls");
			print(xian, hang, lie);
			Choose();
			printf("请选择:");
			scanf("%d", &input);
			if (input != 1 && input != 2 && input != 0)
			{
				printf("输入有误,请重新输入\n");
			}
			if (biaoji >= leisum && input == 1)
			{
				printf("标记个数已超出雷数,请重新选择\n");
				continue;
			}
			if (biaoji <= 0 && input == 2)
			{
				printf("已经没有可以取消标记的点了,请重新选择\n");
				continue;
			}
			switch (input)
			{
			case 1:
				Biaolei(xian, hang, lie);
				biaoji++;
				break;
			case 2:
				Clearlei(xian, hang, lie);
				biaoji--;
				break;
			default:
				break;
			}
		} while (input);

		do
		{
			printf("请输入要排查的坐标(行 列):");
			scanf("%d %d", &x, &y);
			if (x<1 || x>hang || y<1 || y>lie)
			{
				printf("输入的坐标有误,请重新输入\n");
				continue;
			}
			else if (xian[x][y] == '?' || xian[x][y] == '!')
			{
				printf("该位置已被标记,请重新输入\n");
				continue;
			}
			else if (xian[x][y] != '*')
			{
				printf("该坐标已排查过,请重新输入\n");
				continue;
			}
			break;
		} while (1);

		if (yin[x][y] == '1')
		{
			system("cls");
			printf("很遗憾,你被炸死了,游戏结束\n");
			print(yin, hang, lie);
			break;
		}
		else
		{
			xian[x][y] = '0';
			vis[x][y] = 1;
			for (int i = 0; i < 8; i++)
			{
				if (yin[x + fang[i][0]][y + fang[i][1]] == '1')
					xian[x][y]++;
			}
			ge++;
			if(xian[x][y]=='0')
				zhanlei(yin, xian, hang, lie, x, y, &ge);
			system("cls");
			print(xian, hang, lie);
			if (ge + leisum == hang * lie)
			{
				system("cls");
				print(yin, hang, lie);
				printf("恭喜你,排雷成功\n");
				break;
			}
		}

	}
}

 

        扫雷.c

#define _CRT_SECURE_NO_WARNINGS

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

void Lelve()
{
	printf("************************\n");
	printf("*** 1.easy(9*9 10)   ***\n");
	printf("*** 2.mid(16*16 40)  ***\n");
	printf("*** 3.hard(30*16 99) ***\n");
	printf("*** 4.自定义         ***\n");
	printf("************************\n");
}

void game()
{
	//初始化函数
	int input = 0;
	int chang = 0, kuan = 0, lei = 0;
	Lelve();
	printf("请选择:");
	do 
	{
		scanf("%d", &input);
		if (input < 1 || input>4)
		{
			printf("输入有误,请重新输入:");
			continue;
		}
		break;
	} while (1);
	char cun[100][100] = { 0 };
	char show[100][100] = { 0 };
	switch (input)
	{
	case 1:
		chu(cun, EKuans, EChangs, '0');
		chu(show, EKuans, EChangs, '*');

		//布置雷
		set(cun, EKuan, EChang, ELeisum);

		//打印棋盘
		print(show, EKuan, EChang);


		//排查雷,标记雷
		Findlei(cun, show, EKuan, EChang, ELeisum);
		break;

	case 2:
		chu(cun, MKuans, MChangs, '0');
		chu(show, MKuans, MChangs, '*');

		//布置雷
		set(cun, MKuan, MChang, MLeisum);

		//打印棋盘
		print(show, MKuan, MChang);


		//排查雷
		Findlei(cun, show, MKuan, MChang, MLeisum);
		break;

	case 3:
		chu(cun, HKuans, HChangs, '0');
		chu(show, HKuans, HChangs, '*');

		//布置雷
		set(cun, HKuan, HChang, HLeisum);

		//打印棋盘
		print(show, HKuan, HChang);


		//排查雷
		Findlei(cun, show, HKuan, HChang, HLeisum);
		break;

	case 4:
		printf("请输入长度 宽度 雷的个数(长<=50 宽<=16 雷数<长*宽)\n");//过大控制台太小,屏幕会乱跳,不好操控
		do
		{
			scanf("%d %d %d", &chang, &kuan, &lei);
			if (chang > 50 || chang < 1 || kuan>50 || kuan < 1 || chang * kuan <= lei)
			{
				printf("输入有误,请重新输入:");
				continue;
			}
			break;
		} while (1);
		chu(cun, kuan+2, chang+2, '0');
		chu(show, kuan+2, chang+2, '*');

		//布置雷
		set(cun, kuan, chang, lei);

		//打印棋盘
		print(show, kuan, chang);


		//排查雷
		Findlei(cun, show, kuan, chang, lei);
		break;
	}
}

void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			system("cls");
			printf("游戏开始\n");
			game();
			break;
		case 0:
			system("cls");
			printf("欢迎下次游玩\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);
}

int main()
{
	test();
	return 0;
}

 

结语:

        敬请期待吧

        

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值