C语言扫雷---递归展开

C语言扫雷---递归展开,第1张

高内聚低耦合!高内聚低耦合!高内聚低耦合!尽量保证函数内部没有无关紧要的代码,昨天写了一半的代码今天早上起来我已经凌乱了,自己写的代码把我自己绕晕了,本着将错就错好过重来的原则我继续给这段破代码写下半段,总之一个扫雷小游戏让我见识的bug也够它吹一辈子牛了,刚刚好不容易才将代码维护的能跑起来,许多功能已经舍弃,不过好在递归展开还能在代码上跑动,也算是有个看样了;

目前存在的缺陷

1.只有中等模式能够正常运行,要调难度只能自己手动改宏定义参数(传二维数组参数不到位)

2.舍弃了自定义

3.舍弃了标点,代码太乱实在不想浪费时间了

1.头文件的包含--game.h
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include 
 #include 
#include 
 
#define ROW1 11 //简单模式大小和雷数
#define COL1 11
#define MINE1 10 

#define ROW2 22 //中等模式大小和雷数
#define COL2 22
#define MINE2 50 

#define ROW3 42 //专家模式大小和雷数
#define COL3 42
#define MINE3 200 


void initialization(char dark[ROW2][COL2], int row, int col, char wt);//初始化棋盘函数

void lay_mines1(int number, char dark[ROW2][COL2], int row, int col); //为简单暗棋盘埋雷

void checkerboard( char bright[ROW2][COL2], int row, int col);//显示棋盘

int mine_clearance(char dark[ROW2][COL2], char bright[ROW2][COL2], int row, int col);//排雷

int recursion(char dark[ROW2][COL2], char bright[ROW2][COL2], int row, int col, int i, int y);//递归展开

int ergodic(char bright[ROW2][COL2], int row, int col, int thunder);//判断是否胜利


 2.函数主程序--扫雷.c
#include"game.h" 
void muve1()
{
	//system("color 0E " );
	printf("┏--------------------------------------------┓\n");
	printf("┃******************扫雷游戏******************┃\n");
	printf("┃                                            ┃\n");
	printf("┃                1.开始游戏                  ┃\n");
	printf("┃                                            ┃\n");
	printf("┃                0.退出游戏                  ┃\n");
	printf("┃                                            ┃\n");
	printf("┗--------------------------------------------┛\n");
	//printf("┃━  ┓  ┗  ┏  ┛ ■ ● ☆");字符复制
	 
}

void muve2()
{
	//system("color 0E " );
	printf("┏--------------------------------------------┓\n");
	printf("┃******************扫雷游戏******************┃\n");
	printf("┃                                            ┃\n");
	printf("┃                1.简单模式                  ┃\n");
	printf("┃                2.中等模式                  ┃\n");
	printf("┃                3.专家模式                  ┃\n");
	printf("┃                4.自定义                    ┃\n");
	printf("┃                5.说明书                    ┃\n");
	printf("┃                0.返回菜单                  ┃\n");
	printf("┗--------------------------------------------┛\n");
	//printf("┃━  ┓  ┗  ┏  ┛ ■ ● ☆");字符复制

}

void muve3()
{
	system("cls");
	printf("                                               ┏--------------------------------------------┓\n");
	printf("                                               ┃******************扫雷游戏******************┃\n");
	printf("                                               ┃ 1.简单模式:                               ┃\n");
	printf("                                               ┃  棋盘大小规格9*9,雷数10个;               ┃\n");
	printf("                                               ┃                                            ┃\n");
	printf("                                               ┃ 2.中等模式:                               ┃\n");
	printf("                                               ┃  棋盘大小规格20*20,雷数50个;             ┃\n");
	printf("                                               ┃                                            ┃\n");
	printf("                                               ┃ 3.专家模式:                               ┃\n");
	printf("                                               ┃  棋盘大小规格40*40,雷数200个;            ┃\n");
	printf("                                               ┃  建议放大窗口                              ┃\n");
	printf("                                               ┃                                            ┃\n");
	printf("                                               ┃ 4.自定义:                                 ┃\n");
	printf("                                               ┃  玩家自定义棋盘大小和雷的个数;            ┃\n");
	printf("                                               ┃                                            ┃\n");
	printf("                                               ┃ 5.返回菜单:                               ┃\n");
	printf("                                               ┃  游戏开始时返回菜单输入坐标(636,636);  ┃\n");
	printf("                                               ┃                                            ┃\n");
	printf("                                               ┃ 6.透视暗棋盘:                             ┃\n");
	printf("                                               ┃  输入坐标(963,963)透视所有雷的位置;    ┃\n");
	printf("                                               ┃                                            ┃\n");
	printf("                                               ┃**********    输入任意数字返回    **********┃\n");
	printf("                                               ┃           ☆无法识别数字外的符号☆         ┃\n");
	printf("                                               ┗--------------------------------------------┛\n");
	int ks[5] = {0};
	scanf("%d", &ks[0]);
}
//*******************************************************************************
 


void carryout(int x,char dark[ROW2][COL2], char bright[ROW2][COL2],int row,int col)//游戏开始创建
{
	char borek[ROW1][COL1] = { 0 }; //第三个数组来模拟递归展开并标记已经探索过的坐标
	initialization(dark, row, col,'0');//将暗棋盘0初始化
	initialization(bright, row, col,'*');//将明棋盘■初始化
	lay_mines1(x, dark,row,col);//为暗棋盘埋雷
	 
	checkerboard(bright,row,col);//显示明棋盘
	int i = 0;
	int y = 0;
	while (1)
	{
		printf("请输入排查坐标x,y>>");
		scanf("%d,%d", &i, &y);
		int judge=mine_clearance(dark, bright, row, col,i,y);//玩家排雷

		 recursion(dark, bright, row, col, i, y);//测试递归能否展开

		system("cls");
		if (judge == 1||judge==3)
		{
			system("cls");
			if (judge == 3)//显示暗棋盘
			{
				checkerboard(dark, row, col);
				printf("\n");
			}
			checkerboard(bright, row, col);//显示棋盘
			int js = ergodic(bright, row, col, x);//遍历棋盘,判断是否胜利
			if (js == 666)
			{
				 
				printf("┃**********************************┃\n");
				printf("┃         恭喜你,游戏胜利         ┃\n");
				printf("┃**********************************┃\n");
				Sleep(3000);
				break;

			}
		}
		else if (judge == 2)
		{
			system("cls");
			break;
		}
		else if (judge == 4)
		{
			printf("坐标非法,重新输入\n");
		}
		else if(judge==0)
		{
			system("cls");
	
			checkerboard(bright, row, col);//让玩家死的明白
			printf("********很遗憾你被炸死了!*********\n");
			Sleep(3500);
			break;
		}
	 }
}
//*******************************************************************
void startup()// 游戏菜单主函数
{
	system("cls");
	int option = 0;
	char dark1[ROW1][COL1] = { 0 };
	char bright1[ROW1][COL1] = { 0 };//简单模式二维数组
	char dark2[ROW2][COL2] = { 0 };
	char bright2[ROW2][COL2] = { 0 };//中等模式二维数组
	char dark3[ROW3][COL3] = { 0 };
	char bright3[ROW3][COL3] = { 0 };//专家模式二维数组
	do
	{
		system("cls");
		muve2();
		scanf("%d", &option);
		switch (option)
		{
		case 1:            //简单模式9*9规格,10个雷
			system("cls");
			carryout(MINE1, dark1, bright1,ROW1,COL1);
			break;
		case 2:            //中等模式20*20规格,50个雷    
			system("cls");
			carryout(MINE2, dark2, bright2, ROW2, COL2);
			break;
		case 3:            //困难模式40*40规格,200个雷 
			system("cls");
			carryout(MINE3, dark3, bright3, ROW3, COL3);
			break;
		case 4:             //玩家自定义

			break;
		case 5:             //说明书  
			muve3();
			system("cls");
			break;
		case 0:
			break;
		default:
			system("cls");
			printf("请输入正确的数字\n");
			break;
		}
	} while (option);
}
//****************************************************************************
int main() //程序主函数
{
	srand((unsigned)time(NULL));
	int input = 0;
	do
	{
		system("cls");
		muve1();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			startup();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			system("cls");
			printf("请输入正确的数字\n");
			break;
		}
	} while (input);

	return 0;
}

 3.游戏实现函数---game.c
#include"game.h" 

void initialization(char dark[ROW2][COL2], int row, int col, char wt)//初始化棋盘函数
{
	int x = 0;
	int y = 0;
	for (x = 0; x < row; x++)
	{
		for (y = 0; y < col; y++)
		{
			dark[x][y] = wt;
		}
	}
}

void lay_mines1(int number, char dark[ROW2][COL2], int row, int col) //为暗棋盘埋雷
{
	int jun = number;
	while (jun)
	{
		int x = rand() % row - 1;
		int y = rand() % col - 1;

		if (x > 0 && y > 0)
		{
			if (dark[x][y] == '0')
			{
				dark[x][y] = '1';
				jun--;
			}
		}
	}
}


void checkerboard(char bright[ROW2][COL2], int row, int col)//显示棋盘
{
	int x = 0;
	int y = 0;

	for (x = 0; x < row - 1; x++)
	{
		printf("%02d|", x);
	}
	printf("\n");

	for (x = 1; x < row - 1; x++)    
	{
		printf("%02d|", x);
		for (y = 1; y < col - 1; y++)  
		{

			if (bright[x][y] == '*')//未排查区域
			{
				printf("■|");
			}
			else if (bright[x][y] != '0' && bright[x][y] != '#'&&bright[x][y]!='&')//排查的坐标周围有雷
			{
				printf("%02c|", bright[x][y]);
			}
			else if (bright[x][y] == '#')//排查的坐标是雷
			{
				printf("☆|");
			}
			else if(bright[x][y]=='&')     //排查的坐标周围没有雷
			{
				
				printf("  |");

			}
			else
			{
				printf("  |");
			}

		}
		printf("\n");

	}

}
 

int mine_clearance(char dark[ROW2][COL2], char bright[ROW2][COL2],int row, int col,int x,int y)//排雷
{
	 
	while (1)
	{
		if (x == 636 && y == 636)//返回菜单的坐标
		{
			return 2;
		}
		if (x == 963 && y == 963)//作弊模式的坐标
		{
			return 3;
		}
		if ((x > 0 && y > 0) && (x < row - 1 && y < col - 1))
		{
			if (dark[x][y] == '0') //输入的坐标不是雷的情况遍历坐标周围的雷数
			{
				int i = 0;
				int j = 0;
				int count = 0;
				for (i = x - 1; i < x + 2; i++)
				{
					for (j = y - 1; j < y + 2; j++)
					{
						if (dark[i][j] == '1')
						{
							count++;
						}
					}
				}
				 
					bright[x][y] = count + 48;
					return 1;
				 
			}
			else             //输入的坐标是雷
			{
				bright[x][y] = '#';
				return 0;
			}
		}
		else                  //坐标不正确返回4
		{
			return 4;
		}
	}
}

//这个统计坐标周围雷数函数我重新写了一遍,因为之前的函数封装的太乱了
int mine_clearance1(char dark[ROW2][COL2],char bright[ROW2][COL2],int row,int col,int i,int y)
{
	int h = 0;
	int z = 0;
	int count = 0;
	for (h = i - 1; h < i + 2; h++)
	{
		for (z = y - 1; z < y + 2; z++)
		{
			if (dark[h][z] == '1')
			{
				count++;
			}
		}
	}
	return count;
}
recursion(char dark[ROW2][COL2], char bright[ROW2][COL2], int row, int col, int i, int y)
{
	if (i > 0 && i < row && y>0 && y < col)
	{
		int sun = mine_clearance1(dark, bright, row, col, i, y);
		if (bright[i][y] == '#' || bright[i][y] == '&')//坐标已经递归过或者坐标是雷
		{
			return;
		}
		
		else if (sun!= 0 )//坐标周围有雷的情况
		{
			
			bright[i][y] = sun + '0';
			return;
		}

		else
		{
			bright[i][y] = '&';
			int n = 0;
			int m = 0;
			for (n = -1; n <= 1; n++)
			{
				for (m = -1; m <= 1; m++)
				{
					recursion(dark, bright, row, col, i + n, y + m);
					 
				}
			}
			 
		}
		 
		 
	}
}


int ergodic(char bright[ROW2][COL2], int row, int col, int thunder)//判断是否胜利
{
	int count = 0;
	int i = 0;
	int j = 0;
	for (i = 1; i < row - 1; i++)
	{
		for (j = 1; j < col - 1; j++)
		{
			if (bright[i][j] != '*')
			{
				count++;
			}
		}
	}
	if (count == (row - 2) * (col - 2) - thunder)
	{
		return 666;
	}
	else
	{
		return 555;
	}
}

 

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/langs/875175.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-13
下一篇2022-05-13

发表评论

登录后才能评论

评论列表(0条)

    保存