C语言之迷宫小游戏2.0版(随机生成地图,可变颜色,优化游戏体验)

Posted 星辰大海为征途

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言之迷宫小游戏2.0版(随机生成地图,可变颜色,优化游戏体验)相关的知识,希望对你有一定的参考价值。

目录

前言

一、迷宫随机地图的生成——深度优先算法

二、相比上一版本的优化

1.加入主菜单

2.按键

3.色彩

附完整代码如下:

注意事项:


前言

在经过了一段时间的学习后,笔者对上一篇文章简单的走迷宫小游戏中所写的程序进行了大量的优化和升级,改进了文章最后所提及的几项缺点。今写此文,望各位大佬看后,仍能给予宝贵的意见和建议。

一、迷宫随机地图的生成——深度优先算法

迷宫随机生成地图,无非是指在有限的区域内,随机生成路径、陷阱,当然也可随机生成起点和终点。针对迷宫随机生成地图的问题,笔者在翻阅了大量文章和资料后,选择采用深度优先算法。而在各篇讲解深度优先算法的文章中,最后参考了CSDN博主 jjwwwww 所写的文章:随机迷宫生成算法——深度优先算法。下面是有关思路和代码:

1.假设迷宫只有一条正确的道路。

2.把自己想象成一只地鼠,要在这个区域不停的挖,直到任何一块区域再挖就会挖穿了为止。

3.我们挖的道路就像树结构,树上有很多的分支,分支也有子分支,每个子分支都不能相交,相交了就说明墙被挖穿了,那么此时的迷宫就可能存在多条正确道路,这不是我想看到的。

4.那么基于唯一道路的原则,我们向某个方向挖一块新的区域时,要先判断新区域是否有挖穿的可能,如果可能挖穿要立即停止并换个方向再挖。如图:

5.所以,挖之前要确保上下左右四个位置中只有一个位置是路。依照以上思路,便可得以下代码:

void createmap(int **map_way,int x,int y) 
{
	map_way[x][y]=WAY;
	//确保四个方向随机
	int direction[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
	for (int i=0;i<4;i++) 
	{
		int r=rand()%4;
		int temp=direction[0][0];
		direction[0][0]=direction[r][0];
		direction[r][0]=temp;
		temp=direction[0][1];
		direction[0][1]=direction[r][1];
		direction[r][1]=temp;
	}
	//向四个方向开挖
	for (int i=0;i<4;i++) 
	{
		int dx=x;
		int dy=y;
		//控制挖的距离,由Rank来调整大小
		int range=1+(Rank==0?0:rand()%Rank);
		while (range>0) 
		{
			dx+=direction[i][0];
			dy+=direction[i][1];
			//排除掉回头路
			if (map_way[dx][dy]==WAY) 
				break;
			int count=0;
			for (int j=dx-1;j<dx+2;j++) 
			{
				for (int k=dy-1;k<dy+2;k++) 
				{
					if (abs(j-dx)+abs(k-dy)==1&&map_way[j][k]==WAY) 
						count++;
				}
			}
			if (count>1) 
				break;
			//确保不会挖穿时,前进
			--range;
			map_way[dx][dy]=WAY;
		}
		//没有挖穿危险,以此为节点递归
		if (range<=0) 
			createmap(map_way,dx,dy);
	}
}

但是考虑到为了防止挖路时挖出边界,我们把最外层全部设为路径。编写函数void map_make(int **map_way);在这个函数中,笔者不但调用了上一步所写的地图随机生成函数,还写入了随机生成终点和陷阱的代码。其中终点随机生成在路径上,考虑到起点位置定于地图左上角,故选择将终点位置限定在右下角区域内。而陷阱的生成,则限定在墙壁所在的位置,确保不会出现终点被墙壁和陷阱“包围”等无路可走的情况。此外陷阱生成的个数,由pow(N/6,2)决定,其中N为地图边长,即地图越大,陷阱越多,且增长越快。

void map_make(int **map_way)
{
	for (int i=0;i<N;i++) //将最外层全部设为路径 
	{
		map_way[i][0]=WAY;
		map_way[0][i]=WAY;
		map_way[i][N-1]=WAY;
		map_way[N-1][i]=WAY;
	}
	createmap(map_way,2,2);
	while(1) //随机确定终点位置 
	{
		int i=rand()%(N/2),j=rand()%(N/2);
		if (i>1&&j>1&&map_way[N-i][N-j]==WAY) 
		{
			map_way[N-i][N-j]=3;
			break;
		}
	}
	for(int k=pow(N/6,2);k>0;k--) //重复生成陷阱 
	{
		while(1) //随机确定陷阱位置 
		{
			int i=rand()%(N-2),j=rand()%(N-2);
	 
			if(i>1&&j>1&&map_way[i][j]==WALL)
			{
				map_way[i][j]=2;
				break;
			} 
		} 
	}
	 
}

二、相比上一版本的优化

除了地图可以随机生成外,2.0版本还有着以下几点的优化

1.加入主菜单

有了菜单选择界面,可对地图难易度(即地图大小N)、初始生命值进行调节。代码如下:

void menu_1()
{
	color(Menu_color); 
	goto_xy(48,4);
	printf("****************************************************");
	goto_xy(48,5);
	printf("*          《迷宫2.0》           *"); 
	goto_xy(48,6);
	printf("*       制作人:星辰大海为征途       *");
	goto_xy(48,7);
	printf("****************************************************");
	goto_xy(48,8);
	Sleep(3500);
}

void menu_2()
{
	goto_xy(48,4);
	printf("****************************************************");	
	goto_xy(48,5);
	printf("*          游戏规则           *");
	goto_xy(48,6);
	printf("*    玩家控制人物向终点移动,每掉入一次陷阱,  *");
	goto_xy(48,7);
	printf("*  生命值减一。当生命值减至零时,游戏结束。抵达 *");
	goto_xy(48,8);
	printf("*  终点,则成功通关。              *");
	goto_xy(48,9);
	printf("****************************************************");
	goto_xy(48,10);
	printf("*          主菜单选项          *");	
	goto_xy(48,11);
	printf("*          1.开始游戏          *");
	goto_xy(48,12);
	printf("*          2.难度调整          *");
	goto_xy(48,13);
	printf("*          3.初始生命值         *");
	goto_xy(48,14);
	printf("*          4.游戏说明          *");
	goto_xy(48,15);
	printf("****************************************************"); 
} 

int menu()
{
	char anjian;
	int num; 
	menu_1(); 
	while(1)
	{
		int i=4;
		system("cls");
		menu_2();
		goto_xy(48,16);
		printf("输入选项:"); 
		anjian=getch();
		system("cls");
		if(anjian=='1')
		{
			goto_xy(48,4);
			printf("游戏即将开始...");
			Sleep(1500);
			break;	
		}
		switch(anjian)
		{
			case '2':
				goto_xy(48,4);	
				printf("选择难度(1~5的整数):");
				anjian=getch();
				switch(anjian)
				{
					case '1':
						N=24;
						break;
					case '2':
						N=30;
						break;
					case '3':
						N=36;
						break;
					case '4':
						N=42;
						break;
					case '5':
						N=48;
						break;					
					default:
						break;
				}
				goto_xy(48,5);
				printf("设定成功! 当前地图边长为:%d",N-2);
				goto_xy(48,6);
				printf("即将返回主菜单..."); 
				Sleep(2000);
				break;
			case '3':
				system("cls");
				goto_xy(48,4);
				printf("设定初始生命值:(1~%d的整数):",N/4);
				while(1)
				{	
					scanf("%d",&LIFE);
					goto_xy(48,++i);
					if(LIFE<1||LIFE>N/4)
						printf("无效生命值!请重新输入:");
					else
					{
						printf("设定成功! 当前生命值为:%d",LIFE);
						goto_xy(48,i+1);
						printf("即将返回主菜单...");	
						Sleep(2000);
						break;
					}	
				}
				break;
			case '4':
				system("cls");
				goto_xy(48,4);
				printf("******************************");
				goto_xy(48,5);
				printf("* 上:↑   墙壁: \\"");	color(Well_color);	printf("▓");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,6);
				printf("* 下:↓   陷阱:\\"");	color(Trap_color);	printf("⊙");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,7);
				printf("* 左:←   终点:\\"");	color(Exit_color);	printf("★");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,8);
				printf("* 右:→   人物:\\"");	color(Man_color);	printf("☆");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,9);
				printf("******************************");
				goto_xy(48,12);
				printf("按任意键返回主菜单。");
				goto_xy(48,13);
				getch();
				break; 
			default:
				break;
		}
	} 
	return 0;
}

2.按键

相比之前版本对人物移动的按键控制,通过用getch()替换getchar()、对键盘“↑↓←→”按键的读取,实现了直接使用键盘“↑↓←→”按键控制人物移动,且无需每输入一个字符按一下enter键,无疑提升了游戏体验。

代码如下:

int move(int **map_way)  //为了能在运行过程中通过返回值的方式,提前退出当前函数,故将函数定义为了int型 
{	
	int i,j;
	char anjian;
	goto_xy(N*2,7);
	color(Menu_color);
	printf("当前生命值:%d",LIFE);
	goto_xy(man_x*2,man_y);
	color(Man_color); 
	printf("☆");
	while(1)
	{
		goto_xy(N*2,0); 
		if (ch1=getch())
        { 
            ch2=getch();//第一次调用getch(),返回值224
            switch (ch2)//第二次调用getch()
            {
            	case 72: 
				if(map_way[man_y-1][man_x]==WALL)
				{
					zhuangqiang();
					break;
				}
				else if(map_way[man_y-1][man_x]==TRAP)
				{
					trap();
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					}
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y-1);
					color(Man_color);
					printf("☆");
					man_y--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break; 
				} 
				else if(map_way[man_y-1][man_x]==EXIT)
				{
					pass();
					return 0;
				}
				else if(map_way[man_y-1][man_x]==WAY)
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y-1);
					color(Man_color);
					printf("☆");
					man_y--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					goto_xy(N*2,6); 
					color(7);
					printf("				       		");
					break;
				}
	            case 80: 
				if(map_way[man_y+1][man_x]==WALL)
				{
					zhuangqiang();
					break;	
				}
				else if(map_way[man_y+1][man_x]==TRAP)
				{
					trap();
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					} 
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y+1);
					color(Man_color);
					printf("☆");
					man_y++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break;
				} 
				else if(map_way[man_y+1][man_x]==EXIT)
				{
					pass();
					return 0;
				}
				else if(map_way[man_y+1][man_x]==WAY)
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y+1);
					color(Man_color);
					printf("☆");
					man_y++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					goto_xy(N*2,6); 
					printf("				       		");
					break;
				} 
	            case 75: 
				if(map_way[man_y][man_x-1]==WALL)  //与墙壁相冲突 
				{
					zhuangqiang();
					break;	
				}
				else if(map_way[man_y][man_x-1]==TRAP) //掉入陷阱
				{
					trap(); 
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					} 
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆");  
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆");
						color(Way_color);
						printf(" ");  
					}
					man_x--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break;
				}
				else if(map_way[man_y][man_x-1]==EXIT)  //到达终点 
				{
					pass();  //打印提示语句 
					return 0; //退出 
				}
				else if(map_way[man_y][man_x-1]==WAY) //将人物向指定位置移动 
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆"); 
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆");
						color(Way_color);
						printf(" ");
					}
					man_x--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");  //抹去之前打印的提示语句 
					goto_xy(N*2,6); 
					printf("			       			");
					break;
				}  
	            case 77: 
				if(map_way[man_y][man_x+1]==WALL)
				{
					zhuangqiang();
					break;	
				}
				else if(map_way[man_y][man_x+1]==TRAP)
				{
					trap();
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					} 
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
						color(Man_color);
						printf("☆");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" ");
						color(Man_color);
						printf("☆");
					} 
					man_x++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break;
				} 
				else if(map_way[man_y][man_x+1]==EXIT)
				{
					pass();
					return 0;
				}
				else if(map_way[man_y][man_x+1]==WAY)
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
						color(Man_color);
						printf("☆");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" ");
						color(Man_color);
						printf("☆");
					} 
					man_x++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					goto_xy(N*2,6); 
					printf("		       				");
					break;
				}
				default:
					break;                               
        	}  	
		}	
	}
} 

3.色彩

通过编写自定义函数void color(const unsigned short color1);实现了改变特定字符的颜色和背景色。使得游戏界面看起来更美观(花里胡哨)。

代码如下:

/****************************************
	文字颜色对应值:
  0=黑色                8=灰色  
   1=蓝色                9=淡蓝色                                          
  2=绿色                10=淡绿色                
  3=湖蓝色              11=淡浅绿色         
  4=红色                12=淡红色          
  5=紫色                13=淡紫色                  
  6=黄色                14=淡黄色                  
  7=白色                15=亮白色    

	背景颜色对应值:
	0=黑色                128=灰色  
   16=蓝色               144=淡蓝色                                          
  32=绿色               160=淡绿色                
  48=湖蓝色             176=淡浅绿色         
  64=红色               192=淡红色          
  80=紫色               208=淡紫色                  
  96=黄色               224=淡黄色                  
  112=白色              240=亮白色

	若要同时改变背景色和文字颜色,只需
	将文字颜色对应值与背景色对应值相加
	如:蓝字红底=1+64=65 
*****************************************/
void color(const unsigned short Color)
{        
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), Color |FOREGROUND_INTENSITY);
}

未改变颜色(黑白):

改变颜色后(彩色):

附完整代码如下:

#include<stdio.h>
#include<Windows.h>
#include<time.h>
#include<math.h>
#include<conio.h>
 
//墙和路径的标识
#define WALL  0
#define WAY 1
#define TRAP 2 
#define EXIT 3
/****************************************
	文字颜色对应值:
  0=黑色                8=灰色  
   1=蓝色                9=淡蓝色                                          
  2=绿色                10=淡绿色                
  3=湖蓝色              11=淡浅绿色         
  4=红色                12=淡红色          
  5=紫色                13=淡紫色                  
  6=黄色                14=淡黄色                  
  7=白色                15=亮白色    

	背景颜色对应值:
	0=黑色                128=灰色  
   16=蓝色               144=淡蓝色                                          
  32=绿色               160=淡绿色                
  48=湖蓝色             176=淡浅绿色         
  64=红色               192=淡红色          
  80=紫色               208=淡紫色                  
  96=黄色               224=淡黄色                  
  112=白色              240=亮白色

	若要同时改变背景色和文字颜色,只需
	将文字颜色对应值与背景色对应值相加
	如:蓝字红底=1+64=65 
*****************************************/
#define Well_color 7	//控制墙壁的颜色 
#define Trap_color 2	//控制陷阱的颜色 
#define Exit_color 4	//控制终点的颜色
#define Way_color 144	//控制道路的颜色 
#define Man_color 5		//控制人物的颜色 
#define Menu_color 6	//控制主菜单的颜色 

static int Rank = 0;
int man_x=2,man_y=2,N=18,LIFE=4,Time,ch1=0,ch2=0;

void color(const unsigned short color1);
void menu_1();
void menu_2();
int menu();
void createmap(int **map_way,int x,int y) ;
void map_make(int **map_way);
void goto_xy(int x,int y);
void map_draw(int **map_way);
void zhuangqiang();
void trap();
int move(int **map_way);
void pass();
void end(int **map_way);

int main(void) 
{
	menu();
	Time=time(NULL);
	srand((unsigned)time(NULL));
	int **map_way=(int**)malloc(N*sizeof(int *));
	for (int i=0;i<N;i++) 
		map_way[i]=(int*)calloc(N,sizeof(int));
	system("cls");
	map_make(map_way);
	map_draw(map_way);
 	move(map_way);
	end(map_way);
	system("pause");
	goto_xy(N*2,9);

	return 0;
}

void color(const unsigned short Color)
{        
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), Color |FOREGROUND_INTENSITY);
}

void menu_1()
{
	color(Menu_color); //改变 
	goto_xy(48,4);
	printf("****************************************************");
	goto_xy(48,5);
	printf("*          《迷宫2.0》           *"); 
	goto_xy(48,6);
	printf("*       制作人:星辰大海为征途       *");
	goto_xy(48,7);
	printf("****************************************************");
	goto_xy(48,8);
	Sleep(3500);
}

void menu_2()
{
	goto_xy(48,4);
	printf("****************************************************");	
	goto_xy(48,5);
	printf("*          游戏规则           *");
	goto_xy(48,6);
	printf("*    玩家控制人物向终点移动,每掉入一次陷阱,  *");
	goto_xy(48,7);
	printf("*  生命值减一。当生命值减至零时,游戏结束。抵达 *");
	goto_xy(48,8);
	printf("*  终点,则成功通关。              *");
	goto_xy(48,9);
	printf("****************************************************");
	goto_xy(48,10);
	printf("*          主菜单选项          *");	
	goto_xy(48,11);
	printf("*          1.开始游戏          *");
	goto_xy(48,12);
	printf("*          2.难度调整          *");
	goto_xy(48,13);
	printf("*          3.初始生命值         *");
	goto_xy(48,14);
	printf("*          4.游戏说明          *");
	goto_xy(48,15);
	printf("****************************************************"); 
} 

int menu()
{
	char anjian;
	int num; 
	menu_1(); 
	while(1)
	{
		int i=4;
		system("cls");
		menu_2();
		goto_xy(48,16);
		printf("输入选项:"); 
		anjian=getch();
		system("cls");
		if(anjian=='1')
		{
			goto_xy(48,4);
			printf("游戏即将开始...");
			Sleep(1500);
			break;	
		}
		switch(anjian)
		{
			case '2':
				goto_xy(48,4);	
				printf("选择难度(1~5的整数):");
				anjian=getch();
				switch(anjian)
				{
					case '1':
						N=24;
						break;
					case '2':
						N=30;
						break;
					case '3':
						N=36;
						break;
					case '4':
						N=42;
						break;
					case '5':
						N=48;
						break;					
					default:
						break;
				}
				goto_xy(48,5);
				printf("设定成功! 当前地图边长为:%d",N-2);
				goto_xy(48,6);
				printf("即将返回主菜单..."); 
				Sleep(2000);
				break;
			case '3':
				system("cls");
				goto_xy(48,4);
				printf("设定初始生命值:(1~%d的整数):",N/4);
				while(1)
				{	
					scanf("%d",&LIFE);
					goto_xy(48,++i);
					if(LIFE<1||LIFE>N/4)
						printf("无效生命值!请重新输入:");
					else
					{
						printf("设定成功! 当前生命值为:%d",LIFE);
						goto_xy(48,i+1);
						printf("即将返回主菜单...");	
						Sleep(2000);
						break;
					}	
				}
				break;
			case '4':
				system("cls");
				goto_xy(48,4);
				printf("******************************");
				goto_xy(48,5);
				printf("* 上:↑   墙壁: \\"");	color(Well_color);	printf("▓");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,6);
				printf("* 下:↓   陷阱:\\"");	color(Trap_color);	printf("⊙");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,7);
				printf("* 左:←   终点:\\"");	color(Exit_color);	printf("★");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,8);
				printf("* 右:→   人物:\\"");	color(Man_color);	printf("☆");	color(Menu_color);	printf("\\"  *");
				goto_xy(48,9);
				printf("******************************");
				goto_xy(48,12);
				printf("按任意键返回主菜单。");
				goto_xy(48,13);
				getch();
				break; 
			default:
				break;
		}
	} 
	return 0;
}

//生成迷宫
void createmap(int **map_way,int x,int y) 
{
	map_way[x][y]=WAY;
	//确保四个方向随机
	int direction[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
	for (int i=0;i<4;i++) 
	{
		int r=rand()%4;
		int temp=direction[0][0];
		direction[0][0]=direction[r][0];
		direction[r][0]=temp;
		temp=direction[0][1];
		direction[0][1]=direction[r][1];
		direction[r][1]=temp;
	}
	//向四个方向开挖
	for (int i=0;i<4;i++) 
	{
		int dx=x;
		int dy=y;
		//控制挖的距离,由Rank来调整大小
		int range=1+(Rank==0?0:rand()%Rank);
		while (range>0) 
		{
			dx+=direction[i][0];
			dy+=direction[i][1];
			//排除掉回头路
			if (map_way[dx][dy]==WAY) 
				break;
			int count=0;
			for (int j=dx-1;j<dx+2;j++) 
			{
				for (int k=dy-1;k<dy+2;k++) 
				{
					if (abs(j-dx)+abs(k-dy)==1&&map_way[j][k]==WAY) 
						count++;
				}
			}
			if (count>1) 
				break;
			//确保不会挖穿时,前进
			--range;
			map_way[dx][dy]=WAY;
		}
		//没有挖穿危险,以此为节点递归
		if (range<=0) 
			createmap(map_way,dx,dy);
	}
}

void map_make(int **map_way)
{
	for (int i=0;i<N;i++) //将最外层全部设为路径 
	{
		map_way[i][0]=WAY;
		map_way[0][i]=WAY;
		map_way[i][N-1]=WAY;
		map_way[N-1][i]=WAY;
	}
	createmap(map_way,2,2);
	while(1) //随机确定终点位置 
	{
		int i=rand()%(N/2),j=rand()%(N/2);
		if (i>1&&j>1&&map_way[N-i][N-j]==WAY) 
		{
			map_way[N-i][N-j]=3;
			break;
		}
	}
	for(int k=pow(N/6,2);k>0;k--) //重复生成陷阱 
	{
		while(1) //随机确定陷阱位置 
		{
			int i=rand()%(N-2),j=rand()%(N-2);
	 
			if(i>1&&j>1&&map_way[i][j]==WALL)
			{
				map_way[i][j]=2;
				break;
			} 
		} 
	}
	 
}

void goto_xy(int x,int y)  //移动光标到指定位置 
{
	HANDLE hout;
	hout=GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos={x,y};
	SetConsoleCursorPosition(hout,pos);
}

void map_draw(int **map_way)  //打印地图 
{
	for (int i=0;i<N;i++) 
	{
		for (int j=0;j<N;j++) 
		{
			if (map_way[i][j]==WAY) 
			{
				color(Way_color);
				printf("  ");
			}
			else if(map_way[i][j]==3)
			{
				color(Exit_color);
				printf("★");	
			} 
			else if(map_way[i][j]==2)
			{
				color(Trap_color);
				printf("⊙");	
			} 
			else
			{	
				color(Well_color);
				printf("▓");
			}
		}
		printf("\\n");
	}
}

void zhuangqiang()
{
	goto_xy(N*2,5); 
	color(Menu_color);
	printf("撞墙!");
}

void trap()
{
	goto_xy(N*2,6); 
	color(Menu_color);
	printf("很遗憾,你掉入了陷阱,生命值减一!");  //打印提示语句 
	goto_xy(N*2+12,7);
	printf("%2d",--LIFE);
}


int move(int **map_way)  //为了能在运行过程中通过返回值的方式,提前退出当前函数,故将函数定义为了int型 
{	
	int i,j;
	char anjian;
	goto_xy(N*2,7);
	color(Menu_color);
	printf("当前生命值:%d",LIFE);
	goto_xy(man_x*2,man_y);
	color(Man_color); 
	printf("☆");
	while(1)
	{
		goto_xy(N*2,0); 
		if (ch1=getch())
        { 
            ch2=getch();//第一次调用getch(),返回值224
            switch (ch2)//第二次调用getch()
            {
            	case 72: //上 
				if(map_way[man_y-1][man_x]==WALL)
				{
					zhuangqiang();
					break;
				}
				else if(map_way[man_y-1][man_x]==TRAP)
				{
					trap();
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					}
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y-1);
					color(Man_color);
					printf("☆");
					man_y--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break; 
				} 
				else if(map_way[man_y-1][man_x]==EXIT)
				{
					pass();
					return 0;
				}
				else if(map_way[man_y-1][man_x]==WAY)
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y-1);
					color(Man_color);
					printf("☆");
					man_y--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					goto_xy(N*2,6); 
					color(7);
					printf("			    	       		");
					break;
				}
	            case 80: //下 
				if(map_way[man_y+1][man_x]==WALL)
				{
					zhuangqiang();
					break;	
				}
				else if(map_way[man_y+1][man_x]==TRAP)
				{
					trap();
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					} 
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y+1);
					color(Man_color);
					printf("☆");
					man_y++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break;
				} 
				else if(map_way[man_y+1][man_x]==EXIT)
				{
					pass();
					return 0;
				}
				else if(map_way[man_y+1][man_x]==WAY)
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" "); 
					}
					goto_xy(man_x*2,man_y+1);
					color(Man_color);
					printf("☆");
					man_y++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					goto_xy(N*2,6); 
					printf("			   	       		");
					break;
				} 
	            case 75: //左 
				if(map_way[man_y][man_x-1]==WALL)  //与墙壁相冲突 
				{
					zhuangqiang();
					break;	
				}
				else if(map_way[man_y][man_x-1]==TRAP) //掉入陷阱
				{
					trap(); 
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					} 
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆");  
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆");
						color(Way_color);
						printf(" ");  
					}
					man_x--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break;
				}
				else if(map_way[man_y][man_x-1]==EXIT)  //到达终点 
				{
					pass();  //打印提示语句 
					return 0; //退出 
				}
				else if(map_way[man_y][man_x-1]==WAY) //将人物向指定位置移动 
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆"); 
						color(Trap_color);
						printf("⊙");
					}
					else
					{
						goto_xy(man_x*2-2,man_y);  //代表人物的字符☆占两个标准字符位置,应此要乘2 
						color(Man_color);
						printf("☆");
						color(Way_color);
						printf(" ");
					}
					man_x--;
					goto_xy(N*2,5);
					color(7);
					printf("      ");  //抹去之前打印的提示语句 
					goto_xy(N*2,6); 
					printf("			       			");
					break;
				}  
	            case 77: //右 
				if(map_way[man_y][man_x+1]==WALL)
				{
					zhuangqiang();
					break;	
				}
				else if(map_way[man_y][man_x+1]==TRAP)
				{
					trap();
					if(LIFE==0)
					{ 
					 	Sleep(500);
					 	system("cls");
					 	return 0;
					} 
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
						color(Man_color);
						printf("☆");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" ");
						color(Man_color);
						printf("☆");
					} 
					man_x++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					break;
				} 
				else if(map_way[man_y][man_x+1]==EXIT)
				{
					pass();
					return 0;
				}
				else if(map_way[man_y][man_x+1]==WAY)
				{
					if(map_way[man_y][man_x]==TRAP)
					{
						goto_xy(man_x*2,man_y);
						color(Trap_color);
						printf("⊙");
						color(Man_color);
						printf("☆");
					}
					else
					{
						goto_xy(man_x*2,man_y);
						color(Way_color);
						printf(" ");
						color(Man_color);
						printf("☆");
					} 
					man_x++;
					goto_xy(N*2,5);
					color(7);
					printf("      ");
					goto_xy(N*2,6); 
					printf("		       				");
					break;
				}
				default:
					break;                               
        	}  	
		}	
	}
} 

void pass()
{
	int sec,min,time_now;
	time_now=time(NULL);
	sec=(time_now-Time)%60;
	min=(time_now-Time)/60%60;
	system("cls");
	color(Menu_color);
	goto_xy(48,4);
	printf("**************************************************");
	goto_xy(48,5);
	printf("*         恭喜你,成功通关!       *"); 
	goto_xy(48,6);
	printf("*         耗时:%2d分 %2d秒        *",min,sec); 
	goto_xy(48,7);
	printf("**************************************************");
	Sleep(1500);
}

void end(int **map_way)
{
	system("cls");
	goto_xy(48,4);
	printf("**************************************************");
	goto_xy(48,5);
	printf("*           游戏结束          *"); 
	goto_xy(48,6);
	printf("*          GAME OVER!         *");
	goto_xy(48,7);
	printf("**************************************************");	
	goto_xy(48,8);
	for (int i=0;i<N;i++) 
		free(map_way[i]);
	free(map_way);
}


 

注意事项:

1.笔者所用编译器为Dev-C++,若用VC编译部分代码可能会报错,需进行修改。

2.运行时需将窗口调大。默认情况过窄(如图):

调整方法为:右键窗口空白处,点击属性,将“屏幕缓冲区大小”的第一栏改为300,点击确定。关闭窗口,再次运行即可。如图所示:

以上是关于C语言之迷宫小游戏2.0版(随机生成地图,可变颜色,优化游戏体验)的主要内容,如果未能解决你的问题,请参考以下文章

C语言之迷宫小游戏2.0版(随机生成地图,可变颜色,优化游戏体验)

windows开源迷宫游戏|自动寻径|随机生成迷宫地图|UI|闯关|地图反转

C/C++实现:迷宫游戏(进阶版),深度优先算法实现案例

C/C++实现:迷宫游戏(进阶版),深度优先算法实现案例

C语言——简单的走迷宫小游戏(无指针,无链表,无......!!!)

简单的走迷宫小游戏(C语言编写,无指针,无链表)