#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文件,导入生成迷宫(选做);
迷宫路径求解:
① 采用回溯算法求解一条从入口到出口的通路;
② 探索生成多条通路:找出所有通路,计算每条路径长度,并选出最短路径(选做);
迷宫显示:
① 显示符号:墙■;空□;入口位置/出口位置〓;当前位置㊣;不可通位置☒;当前路径→↓←↑;
② 动态显示迷宫路径探索过程:每探索一步,刷新一次迷宫显示;
注意:★当前路径的箭头方向问题;
★屏幕刷新时的闪屏问题;
*/