工口迷宫:数据结构实践课作业

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#include<string.h>
#include<stdbool.h>
#include<assert.h>
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
int str[60][60],vis[60][60],fa[3010],cnt;
int n,m,X,Y,TX,TY;
struct MAZE
{int n,m,Sx,Sy,Tx,Ty,str[60][60];}maze[110];
struct EYZ
{int x,y;}eyz[3010];
int getfa(int x)
{return fa[x]==x?x:(fa[x]=getfa(fa[x]));}
int wujie(int mapid,int n,int m,int Sx,int Sy,int Tx,int Ty)
{
	for(int i=1;i<=(m+1)*(n+1);i++)fa[i]=i;
	// printf("%d %d ",getfa(Sx*(m+1)+Sy),getfa(Tx*(m+1)+Ty));
	for(int x=1;x<=n;x++)
	for(int y=1;y<=m;y++){
		if(maze[mapid].str[x][y]==1)continue;
		for(int i=0;i<4;i++){
			int xx=x+dx[i],yy=y+dy[i];
			if(xx<1||xx>n||yy<1||yy>m||maze[mapid].str[xx][yy]==1)continue;
			fa[getfa(xx*(m+1)+yy)]=getfa(x*(m+1)+y);
		}
	}
	// assert(getfa(2*(m+1)+1)==getfa(19*(m+1)+20));
	// printf("%d %d\n",getfa(Sx*(m+1)+Sy),getfa(Tx*(m+1)+Ty));
	return getfa(Sx*(m+1)+Sy)!=getfa(Tx*(m+1)+Ty);
}
void init()
{
	system("chcp 65001");
	system("mode con cols=100 lines=60");
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//得到窗口句柄
	SetConsoleTitle("《工口迷宫》"); //设置窗口标题
	SMALL_RECT rc = {0,0,99,79}; //{Y位置,X位置,宽,高}
	SetConsoleWindowInfo(hOut,true,&rc);//重置窗口位置和大小
	SetConsoleScreenBufferSize(hOut,(_In_ COORD){100,80});
	srand(time(0));
	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cor_info = { 1, 0 };
	SetConsoleCursorInfo(hout, &cor_info);
	int str[25][25]={
		{},
		{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
		{0,2,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1},
		{0,1,1,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1},
		{0,1,0,0,1,0,1,0,1,0,1,1,1,1,1,1,0,1,1,0,1},
		{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1},
		{0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,1,1,1,1,0,1},
		{0,1,0,1,1,0,1,0,1,1,0,0,0,0,0,1,0,1,1,0,1},
		{0,1,0,0,0,0,1,0,1,1,1,1,1,0,1,1,0,1,1,0,1},
		{0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1},
		{0,1,1,1,1,0,1,0,1,1,1,0,1,0,1,1,0,0,1,0,1},
		{0,1,0,0,1,0,1,0,1,1,1,0,1,0,1,1,0,1,1,0,1},
		{0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1},
		{0,1,0,1,1,0,0,1,1,1,1,1,1,0,1,0,0,1,0,0,1},
		{0,1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,1,0,0,1},
		{0,1,0,1,1,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1},
		{0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1},
		{0,1,0,0,0,0,0,1,0,0,1,0,1,1,1,0,1,1,0,1,1},
		{0,1,0,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,0,1,1},
		{0,1,0,1,1,1,0,1,0,0,1,1,0,0,0,0,0,0,0,0,3},
		{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
	};
	for(int i=1;i<=20;i++)
	for(int j=1;j<=20;j++)
		maze[0].str[i][j]=str[i][j];
	maze[0].n=maze[0].m=20;
	maze[0].Sx=2;maze[0].Sy=1;
	maze[0].Tx=19;maze[0].Ty=20;
	do{
		maze[1]=maze[0];
		for(int i=0;i<=30;i++)
		for(int j=0;j<=30;j++)
			maze[1].str[i][j]=1;
		memset(vis,0,sizeof vis);
		for(int i=1;i<=500;i++)fa[i]=i;
		maze[1].str[2][1]=maze[1].str[19][20]=cnt=0;
		maze[1].str[2][2]=maze[1].str[19][19]=cnt=0;
		for(int i=2;i<=19;i++)
		for(int j=2;j<=19;j++){
			cnt++;
			eyz[cnt].x=i;
			eyz[cnt].y=j;
			// eyz[++cnt]=(EYZ){i,j};
		}
		srand(time(0));
		for(int i=1;i<=cnt;i++){
			int j=rand()%cnt+1;
			eyz[j].x^=eyz[i].x^=eyz[j].x^=eyz[i].x;
			eyz[j].y^=eyz[i].y^=eyz[j].y^=eyz[i].y;
		}
		for(int i=1;i<=cnt;i++){
			int x=eyz[i].x,y=eyz[i].y;
			if(maze[1].str[x][y]==0)
				continue;
			int f[10]={},tot=0,tot2=0;
			for(int j=0;j<4;j++){
				int xx=x+dx[j],yy=y+dy[j];
				if(xx<1||xx>20||yy<1||yy>20||maze[1].str[xx][yy]==1)continue;
				f[++tot]=getfa(xx*21+yy);
			}
			for(int j=1;j<=tot;j++)
			for(int k=j+1;k<=tot;k++)
				if(f[j]==f[k])
					tot2++;
			if(!tot2){
				maze[1].str[x][y]=0;
				for(int j=0;j<4;j++){
					int xx=x+dx[j],yy=y+dy[j];
					if(xx<1||xx>20||yy<1||yy>20||maze[1].str[xx][yy]==1)continue;
					fa[getfa(xx*21+yy)]=getfa(x*21+y);
				}
			}
		}
		maze[1].str[2][1]=2;maze[1].str[19][20]=3;
	}while(wujie(1,20,20,2,1,19,20));
	do{
		// printf("ABC\n");
		maze[2].n=maze[2].m=50;
		maze[2].Sx=2;maze[2].Sy=1;
		maze[2].Tx=49;maze[2].Ty=50;
		for(int i=0;i<=55;i++)
		for(int j=0;j<=55;j++)
			maze[2].str[i][j]=1;
		memset(vis,0,sizeof vis);
		for(int i=1;i<=3000;i++)fa[i]=i;
		maze[2].str[2][1]=maze[2].str[49][50]=cnt=0;
		maze[2].str[2][2]=maze[2].str[49][49]=cnt=0;
		for(int i=2;i<=49;i++)
		for(int j=2;j<=49;j++){
			cnt++;
			eyz[cnt].x=i;
			eyz[cnt].y=j;
			// eyz[++cnt]=(EYZ){i,j};
		}
		srand(time(0));
		for(int i=1;i<=cnt;i++){
			int j=rand()%cnt+1;
			eyz[j].x^=eyz[i].x^=eyz[j].x^=eyz[i].x;
			eyz[j].y^=eyz[i].y^=eyz[j].y^=eyz[i].y;
		}
		for(int i=1;i<=cnt;i++){
			int x=eyz[i].x,y=eyz[i].y;
			if(maze[2].str[x][y]==0)
				continue;
			int f[10]={},tot=0,tot2=0;
			for(int j=0;j<4;j++){
				int xx=x+dx[j],yy=y+dy[j];
				if(xx<1||xx>50||yy<1||yy>50||maze[2].str[xx][yy]==1)continue;
				f[++tot]=getfa(xx*51+yy);
			}
			for(int j=1;j<=tot;j++)
			for(int k=j+1;k<=tot;k++)
				if(f[j]==f[k])
					tot2++;
			if(!tot2){
				maze[2].str[x][y]=0;
				for(int j=0;j<4;j++){
					int xx=x+dx[j],yy=y+dy[j];
					if(xx<1||xx>50||yy<1||yy>50||maze[2].str[xx][yy]==1)continue;
					fa[getfa(xx*51+yy)]=getfa(x*51+y);
				}
			}
		}
		maze[2].str[2][1]=2;maze[2].str[49][50]=3;
	}while(wujie(2,50,50,2,1,49,50));
}
void initmap(int mapid)
{
	system("cls");
	memcpy(str,maze[mapid].str,sizeof str);
	n=maze[mapid].n;m=maze[mapid].m;
	X=maze[mapid].Sx;Y=maze[mapid].Sy;
	TX=maze[mapid].Tx;TY=maze[mapid].Ty;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++)
		if(str[i][j]==0)printf("  ");
		else if(str[i][j]==1)printf("口");
		else if(str[i][j]==2)printf("工");
		else printf("〓");
		printf("\n");
	}
	Sleep(1000);
}
void gotoxy(int x,int y)
{SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),(COORD){x,y});}
void text(int x,int y,char *s)
{
	gotoxy((y-1)*2,x-1);
	printf(s);
}
int dfs(int x,int y,int D)
{
	text(x,y,"工");
	if(x==TX&&y==TY)
		return D;
	Sleep(50);
	vis[x][y]=1;
	for(int i=0;i<4;i++){
		int xx=x+dx[i],yy=y+dy[i];
		if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]||str[xx][yy]==1)continue;
		if(i==0)text(x,y,"↑");
		if(i==1)text(x,y,"↓");
		if(i==2)text(x,y,"←");
		if(i==3)text(x,y,"→");
		int temp=dfs(xx,yy,D+1);
		if(temp!=-1)
			return temp;
		text(x,y,"人");
	}
	Sleep(50);
	text(x,y,"  ");
	vis[x][y]=0;
	return -1;
}
void run()
{
	memset(vis,0,sizeof vis);
	dfs(X,Y,0);
	gotoxy(0,n+1);
}
int getmapid()
{
	system("cls");
	printf("输入0选择内置迷宫,输入1选择随机迷宫,输入2选择大尺寸随机迷宫\n注意:选择大尺寸时,请全屏或缩小字体,确保地图能完全显示在一个界面。\n");
	char str[110];
	scanf("%s",str+1);
	if(strlen(str+1)!=1||str[1]<'0'||str[1]>'2'){
		system("cls");
		printf("错误,请重新输入");
		Sleep(1000);
		return getmapid();
	}
	return str[1]-'0';
}
int main()
{
	while(1){
		init();
		int mapid=getmapid();
		initmap(mapid);
		run();
		system("pause");
	}
}
/*

《动感迷宫》功能要求:
迷宫生成:迷宫为正方形;
      ① 内置:20×20的规模;
      ② 随机生成:
           要求:★迷宫规模可以由用户配置(15×15 ~ 50×50);
                      ★生成的迷宫必须是有解的;
                      ★入口位置坐标(1, 0)、出口位置坐标(n-1, n)
      ③ 文件导入:用户配置TXT文件,导入生成迷宫(选做);
迷宫路径求解:
      ① 采用回溯算法求解一条从入口到出口的通路;
      ② 探索生成多条通路:找出所有通路,计算每条路径长度,并选出最短路径(选做);
迷宫显示:
      ① 显示符号:墙■;空□;入口位置/出口位置〓;当前位置㊣;不可通位置☒;当前路径→↓←↑;
      ② 动态显示迷宫路径探索过程:每探索一步,刷新一次迷宫显示;
           注意:★当前路径的箭头方向问题;
                      ★屏幕刷新时的闪屏问题;
*/
posted @ 2024-10-25 10:09  zYzYzYzYz  阅读(9)  评论(0编辑  收藏  举报