迷宫问题求解
一个迷宫可以看成是由 m×n 个房间组成的矩形,迷宫内部的每个房间有 8
个方向,每个方向或者有障碍(如墙)而不能通过,或者无障碍(如有门)而能
通过。入口为左上角房间,出口为右下角房间,问是否有简单路径从入口到出口,
若有则输出一条这样的路径;否则,提示“迷宫无入口到出口的路经”。
要求:
- 设计一个迷宫及其障碍的表示方式,并能随机或手动生成迷宫。
- 设计并实现一个非递归的算法,输出从入口到出口的一条路径(如存在)。
- 设计并实现一个递归的算法,找出从入口到出口的一条路径(如存在)。
- 如果有多条路径,设计并实现一个算法找到步数最少的路径(捷径)。
- 如果有多条路径,设计并实现一个算法找到所有路径。
- 以文件方式保存、并显示原始数据和结果
需要在d盘根目录下建立lujing.txt和migong.txt文件
#include <iostream>
#include <cstdlib>
#include <ctime>
struct Wall{
int x;
int y;
int direction;
int count;
Wall *next;
};
struct Path{
int length;
int path[2000][2];
};
struct Path All[2000];
int count[2000];
int M[100][100];
int MA[100][100];
int *Global;
int x ,y ;
int fx[8][2]={{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1},{0,1}};
int path[100][100][2];
//做一个栈
struct node{
int x;
int y;
int v;
node *next;
};//结点的”型”
typedef node *STACK;
STACK MakeNull()
{ STACK s = NULL;
s=new node;
s->next=NULL;
s->x=0;
s->v=0;
s->y=0;
return s;
}
bool Empty(STACK stk)
{ if (stk->next != NULL)
return false;
else
return true;
}
void Push( int x,int y,int v, STACK stk)
{
STACK s = NULL;
s=new node;
s->x=x;
s->y=y;
s->v = v;
s->next=stk->next;
stk->next=s;
}
void Pop( STACK stk )
{ STACK s = NULL;
if (stk->next){/*stk->next!=NULL*/
s=stk->next;
stk->next=s->next;
delete s; /* free(s) */
} }
STACK Top( STACK stk)
{ if (stk->next)
return stk->next;
else
return NULL; }
void output(STACK K,int counter){
FILE *fp1 = NULL;
fp1 = fopen("d:/lujing.txt", "a");
STACK p = K->next;
int t = 0;
int a[5000][2] = {0};
while (p != NULL){
a[t][0] = p->x;
a[t][1] = p->y;
t++;
p = p->next;
}
All[counter].length = t;
if (counter == 0){
fprintf(fp1,"所有路径为:\n");
}
for (int i = t-1,j = 0; i >=0; i--,j++) {
All[counter].path[j][0] = a[i][0];
All[counter].path[j][1] = a[i][1];
fprintf(fp1,"%d %d\n",a[i][0],a[i][1]);
printf("%d %d\n",a[i][0],a[i][1]);
}
fprintf(fp1,"###########\n");
fclose(fp1);
printf("###########\n");
}
void getShortcut(){
int flag = 0;
FILE *fp1 = NULL;
fp1 = fopen("d:/lujing.txt", "a");
for (int i = 1; All[i].length!=0; ++i) {
if (All[i].length < All[flag].length){
flag = i;
}
}
printf("最短路径的长度为:%d\n",All[flag].length);
fprintf(fp1,"最短路径的长度为:%d\n",All[flag].length);
printf("最短路径为:\n");
fprintf(fp1,"最短路径为:\n");
for (int j = 0; j < All[flag].length; j++) {
printf("%d %d\n",All[flag].path[j][0],All[flag].path[j][1]);
fprintf(fp1,"%d %d\n",All[flag].path[j][0],All[flag].path[j][1]);
}
}
void setway2(int i,int j,STACK s)
{ int top = 0,g = 0,h = 0,m = x-4,n = y-4,counter = 0,flag = 0;
MA[1][1] = 1;
Push(i,j,0,s);
do { g = i+fx[s->next->v][0] ;
h = j+fx[s->next->v][1] ;
if (( g == m) && ( h == n) && (MA[m][n] == 0 )){
flag = 1;
//MA[g][h]++;
//Push(g,h,v,s);
output(s,counter);
counter++;
}
if ((M[g][h] ==1) && MA[g][h] == 0 && !(g==m&&h==n)){
MA[g][h] = 1;
Push( g,h,0,s ) ;
i = g,j = h;
}
else if ( s->next->v < 7 )
s->next->v++;
else{
if (!Empty(s)){
while (s->next->v == 7){
Pop(s);
if (Empty(s)){
break;
}
MA[i][j]=0;
i = s->next->x;
j = s->next->y;}
if (!Empty(s)){
s->next->v++;
}
// if (s->next->v<7){
// s->next->v++;
// }
}
}
} while (!Empty(s)) ;
if (flag == 0) printf("路径不存在");
}
bool setWay(int i, int j) {
if(M[x-4][y-4] == 2){
return true;
} else if(M[i][j] == 1){
M[i][j]=2;
count[0]++;
path[0][count[0]][0] = i;
path[0][count[0]][1] = j;
if(setWay(i,j+1)) {
return true;
} else if(setWay(i+1,j+1)){
return true;
} else if(setWay(i+1,j)){
return true;
} else if(setWay(i+1,j-1)){
return true;
}else if (setWay(i,j-1)){
return true;
} else if (setWay(i-1,j-1)){
return true;
}else if(setWay(i-1,j)){
return true;
}else if (setWay(i-1,j+1)){
return true;
}else{
M[i][j]=1;
path[0][count[0]][0] = 0;
path[0][count[0]][j] = 0;
count[0]--;
return false;
}
}else{
return false;
}
}
int *CreateMap(int *map,int m,int n){
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
if (i == 0||i == m-1||j == 0||j == n-1){
map[i*n+j] = 1;
}
else if (i % 2 == 0&&j % 2 == 0){
map[i*n+j] = 1;
}
else{
map[i*n+j] = 0;
}
}
}
return map;
}
void Print(int *p){
for (int i = 0; i < x; ++i) {
for (int j = 0; j < y; ++j) {
printf("%d",p[i*y+j]);
}
printf("\n");
}
}
void Print1(int *p){
for (int i = 0; i < x-2; ++i) {
for (int j = 0; j < y-2; ++j) {
printf("%d",p[i*y+j]);
}
printf("\n");
}
}
int *Initialize(){
int *map2;
map2 = (int *)malloc(sizeof(int)*x*y);
//用0标记未走过的位置,用1标记走过的位置
for (int i = 0; i < x; ++i) {
for (int j = 0; j < y; ++j) {
if (i == 0||i == x-1||j == 0||j == y-1){
map2[i*y+j] = 1;
}
else if (i % 2 == 0&&j % 2 == 0){
map2[i*y+j] = 0;
}
else{
map2[i*y+j] = 8;
}
}
}
return map2;
}
void add(Wall *w,int p,int q,int direction){
Wall *w1 = w;
while (w->next != NULL){
w = w->next;
}
Wall *wall1 = new Wall;
wall1->x = p;
wall1->y = q;
wall1->direction = direction;
wall1->next = NULL;
w->next = wall1;
w1->count++;
}
//随机选一个墙
Wall *choose(Wall *K){
srand(time(NULL));
Wall *P = K;
int r;
r = rand()%K->count + 1;
for (int i = 0; i < r; i++) {
P = P->next;
}
return P;
}
void remove(Wall *T,Wall *B){
Wall *N = T;
while (N->next != B){
N = N->next;
}
N->next = B->next;
delete B;
T->count--;
}
void AllWallIn(Wall *w,int f1,int f2){
add(w,f1,f2+1,1);
add(w,f1-1,f2+1,2);
add(w,f1-1,f2,3);
add(w,f1-1,f2-1,4);
add(w,f1,f2-1,1);
add(w,f1+1,f2-1,2);
add(w,f1+1,f2,3);
add(w,f1+1,f2+1,4);
}
void CreatM(int *map3,int *mark1){
Wall *wall = new Wall;
Wall *J = NULL;
wall->next = NULL;
wall->count = 0;
AllWallIn(wall,2,2);
while (wall->count != 0){
J = choose(wall);
switch (J->direction) {
case 1:
if (mark1[J->x*y+J->y+1] == 1&&mark1[J->x*y+J->y-1] == 1){
remove(wall,J);
}
else if (mark1[J->x*y+J->y+1] == 0){
map3[J->x*y+J->y] = 1;
mark1[J->x*y+J->y+1] = 1;
AllWallIn(wall,J->x,J->y+1);
}
else{
map3[J->x*y+J->y] = 1;
mark1[J->x*y+J->y-1] = 1;
AllWallIn(wall,J->x,J->y-1);
}
break;
case 2:
if (mark1[(J->x-1)*y+J->y+1] == 1&&mark1[(J->x+1)*y+J->y-1] == 1){
remove(wall,J);
}
else if (mark1[(J->x-1)*y+J->y+1] == 0){
map3[J->x*y+J->y] = 1;
mark1[(J->x-1)*y+J->y+1] = 1;
AllWallIn(wall,J->x-1,J->y+1);
}
else{
map3[J->x*y+J->y] = 1;
mark1[(J->x+1)*y+J->y-1] = 1;
AllWallIn(wall,J->x+1,J->y-1);
}
break;
case 3:
if (mark1[(J->x-1)*y+J->y] == 1&&mark1[(J->x+1)*y+J->y] == 1){
remove(wall,J);
}
else if (mark1[(J->x-1)*y+J->y] == 0){
map3[J->x*y+J->y] = 1;
mark1[(J->x-1)*y+J->y] = 1;
AllWallIn(wall,J->x-1,J->y);
}
else{
map3[J->x*y+J->y] = 1;
mark1[(J->x+1)*y+J->y] = 1;
AllWallIn(wall,J->x+1,J->y);
}
break;
case 4:
if (mark1[(J->x-1)*y+J->y-1] == 1&&mark1[(J->x+1)*y+J->y+1] == 1){
remove(wall,J);
}
else if (mark1[(J->x-1)*y+J->y-1] == 0){
map3[J->x*y+J->y] = 1;
mark1[(J->x-1)*y+J->y-1] = 1;
AllWallIn(wall,J->x-1,J->y-1);
}
else{
map3[J->x*y+J->y] = 1;
mark1[(J->x+1)*y+J->y+1] = 1;
AllWallIn(wall,J->x+1,J->y+1);
}
break;
}
}
}
int *CreatMaze(int *map,int *mark){
int *map1;
map1 = (int *)malloc(sizeof(int)*(x-2)*(y-2));
CreatM(map,mark);
// Print(map);
for (int i2 = 1,i1 = 0; i2 <= x - 2&&i1 < x-2; ++i2,i1++) {
for (int j2 = 1,j1 = 0; j2 <= y - 2&&j1 < y-2; ++j2,j1++) {
if (i2==1&&j2!=0&&j2!=y-1||i2==x-2&&j2!=0&&j2!=y-1||j2==1&&i2!=0&&i2!=x-1||j2==y-2&&i2!=0&&i2!=x-1){
map[i2*y+j2] = 0;
}
map1[i1*y+j1] = map[i2*y+j2];
}
}
return map1;
}
//递归寻路
void copy(int *u){
for (int i = 0; i < x - 2; ++i) {
for (int j = 0; j < y - 2; ++j) {
M[i][j] = u[i*y+j];
}
}
}
void PrintM(){
FILE *fp = NULL;
fp = fopen("d:/migong.txt", "a");
fprintf(fp,"随机生成的可行迷宫为:\n");
for (int i = 0; i < x - 2; ++i) {
for (int j = 0; j < y-2; ++j) {
fprintf(fp,"%d",M[i][j]);
printf("%d",M[i][j]);
}
printf("\n");
fprintf(fp,"\n");
}
}
void PrintPath(){
printf("走过的路径为:\n");
for (int i = 1; i <= count[0]; ++i) {
printf("%d %d\n",path[0][i][0],path[0][i][1]);
}
}
int main() {
setbuf(stdout, NULL);
printf("请设置迷宫大小:\n");
scanf("%d,%d",&x,&y);
if(x % 2 == 0){//保证迷宫的行和列都为奇数
x++;
}
if (y % 2 == 0){
y++;
}
x+=4;
y+=4;
int *map;
int *map2;
map = (int *)malloc(sizeof(int)*x*y);
map = CreateMap(map,x,y);
//printf("#################\n");
int *mark = Initialize();
//Initialize();
//Print(mark);
// printf("#################\n");
map2 = CreatMaze(map,mark);
printf("#################\n");
//Print1(map2);
copy(map2);
//printf("#################\n");
//MiGong(0, 1, 1);
printf("生成的迷宫为:\n");
PrintM();
STACK n = MakeNull();
printf("路径为:\n");
setway2(1,1,n);
getShortcut();
//printf("#################\n");
// if(setWay(1,1)){
// printf("迷宫的一个路径为:\n");
// PrintM();
// printf("路径长度为%d\n",count[0]);
//PrintPath();
// }
return 0;
}