迷宫问题的CC++算法实现.docx
《迷宫问题的CC++算法实现.docx》由会员分享,可在线阅读,更多相关《迷宫问题的CC++算法实现.docx(16页珍藏版)》请在冰豆网上搜索。
迷宫问题的CC++算法实现
基于栈的C语言迷宫问题与实现
一.问题描述
多年以来,迷宫问题一直是令人感兴趣的题目。
实验心理学家训练老鼠在迷宫中寻找食物。
许多神秘主义小说家也曾经把英国乡村花园迷宫作为谋杀现场。
于是,老鼠过迷宫问题就此产生,这是一个很有趣的计算机问题,主要利用“栈”是老鼠通过尝试的办法从入口穿过迷宫走到出口。
迷宫只有两个门,一个叫做入口,另一个叫做出口。
把一只老鼠从一个无顶盖的大盒子的入口处赶进迷宫。
迷宫中设置很多隔壁,对前进方向形成了多处障碍,在迷宫的唯一出口处放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口。
求解迷宫问题,即找出从入口到出口的路径。
一个迷宫可用上图所示方阵[m,n]表示,0表示能通过,1表示不能通过。
现假设耗子从左上角[1,1]进入迷宫,编写算法,寻求一条从右下角[m,n]出去的路径。
下图是一个迷宫的示意图:
二.算法基本思想
迷宫求解问题是栈的一个典型应用。
基本算法思想是:
在某个点上,按照一定的顺序(在本程序中顺序为上、右、下、左)对周围的墙、路进行判断(在本程序中分别用1、0)代替,若周围某个位置为0,则移动到该点上,再进行下一次判断;若周围的位置都为1(即没有通路),则一步步原路返回并判断有无其他通路,然后再次进行相同的判断,直到走到终点为止,或者确认没有任何通路后终止程序。
要实现上述算法,需要用到栈的思想。
栈里面压的是走过的路径,若遇到死路,则将该位置(在栈的顶层)弹出,再进行下一次判断;若遇到通路,则将该位置压栈并进行下一次判断。
如此反复循环,直到程序结束。
此时,若迷宫有通路,则栈中存储的是迷宫通路坐标的倒序排列,再把所有坐标顺序打印后,即可得到正确的迷宫通路。
三.程序具体部分的说明
1.迷宫的生成
根据题目的要求,迷宫的大小是自定义输入的。
所以在程序中用malloc申请动态二维数组。
数组中的元素为随机生成的0、1。
数组周围一圈的元素全部定义为1,以表示边界。
2.栈的C语言实现
为了实现栈的功能,即清空、压栈、弹出、返回栈顶元素,在程序中编写了相应的函数。
MakeNULL清空栈
Push将横、纵坐标压栈
Topx返回栈顶存储的横坐标
Topy返回栈顶存储的纵坐标
Pop弹出栈顶元素
3.具体的判断算法
当位置坐标(程序中为XY)移到某一位置时,将这个位置的值赋值为1并压栈,以说明该点已经走过。
接着依次判断该点的上、右、下、左是否为0,若有一方为0,则移动到该位置上,进行下次判断;若为周围位置全部是1,则将该点压栈后不断弹出,每次弹出时判断栈顶元素(即走过的路)周围有无其他通路。
如果有的话,则选择该方向继续走下去;如果栈已经为空仍然没有找到出路,则迷宫没有出口程序结束。
当XY走到出口坐标时,程序判断部分结束。
栈里面存储的是每个走过的点的坐标,将这些横纵坐标分别存储在两个数组中,最后将数组中的坐标元素倒序输出,即得到了完整的路径。
四.程序源代码及注释
//Maze.cpp:
定义控制台应用程序的入口点。
//
#include"stdafx.h"
#include
#include
#include
#include
#include
typedefintElementtype;
structnode
{
Elementtypeval1;
Elementtypeval2;
node*next;
};//定义结构体
typedefnode*MAZE;
voidMakeNull(MAZE&S);
voidPush(Elementtypex,Elementtypey,MAZES);
voidPop(MAZES);
ElementtypeTopx(MAZES);
ElementtypeTopy(MAZES);//申明函数
int_tmain(intargc,_TCHAR*argv[])
{
int**p,*q,*x1,*y1,i,j,k,n1,n2,m1,m2,l,w,max;
intx,y;
inta,b,c,d;
printf("输入迷宫长度及宽度l和w\n");
scanf("%d%d",&l,&w);
getchar();
n1=w+2;
n2=l+2;//为迷宫加上边界
max=n1*n2;
p=(int**)malloc(n1*sizeof(int));
for(i=0;ip[i]=(int*)malloc(n2*sizeof(int));//生成二维动态数组
srand(time(NULL));
x1=(int*)malloc(max*sizeof(int));//生成动态数组用于存储路径
y1=(int*)malloc(max*sizeof(int));//生成动态数组用于存储路径
for(i=0;i{
x1[i]=0;
}
for(i=0;i{
y1[i]=0;
}//先将存储路径的数组元素全赋值为0
for(i=0;i{
for(j=0;j{
if(i==0||j==0)
{
p[i][j]=1;
}
elseif(i==n1-1||j==n2-1)
{
p[i][j]=1;
}
else
p[i][j]=rand()%2+0;
}
}//生成二维10随机数组
p[1][1]=0;
p[n1-2][n2-2]=0;//定义迷宫的入口及出口
printf("生成的迷宫如下(代表墙0代表路):
\n");
for(i=0;i{
{
for(j=0;jprintf("%2d",p[i][j]);
}
printf("\n");
}//打印迷宫
MAZES;
MakeNull(S);//清空栈
i=1;
j=1;
if(p[1][2]==1&&p[2][1]==1)
{
printf("Thereisnowayout");a
getchar();
return0;
}//判断入口是否就是死路
else
{
do
{
if(p[i-1][j]==0)
{
x=i;
y=j;
Push(x,y,S);
p[i][j]=1;
i=i-1;
}//判断能否向上走
elseif(p[i-1][j]==1&&p[i][j+1]==0)
{
x=i;
y=j;
Push(x,y,S);
p[i][j]=1;
j=j+1;
}//判断能否向右走
elseif(p[i-1][j]==1&&p[i][j+1]==1&&p[i+1][j]==0)
{
x=i;
y=j;
Push(x,y,S);
k=Topx(S);
p[i][j]=1;
i=i+1;
}//判断能否向下走
elseif(p[i-1][j]==1&&p[i][j+1]==1&&p[i+1][j]==1&&p[i][j-1]==0)
{
x=i;
y=j;
Push(x,y,S);
p[i][j]=1;
j=j-1;
}//判断能否向左走
elseif(p[i-1][j]==1&&p[i][j+1]==1&&p[i+1][j]==1&&p[i][j-1]==1)//判断如果为死路
{
p[i][j]=1;
x=i;
y=j;
Push(x,y,S);
for(;;)
{
Pop(S);//弹出栈顶元素
x=Topx(S);
y=Topy(S);//返回栈顶元素横纵坐标
if(p[x-1][y]==0)
{
i=x-1;
j=y;
p[i][j]=1;
x=i;
y=j;
Push(x,y,S);
break;
}
elseif(p[x-1][y]==1&&p[x][y+1]==0)
{
i=x;
j=y+1;
p[i][j]=1;
x=i;
y=j;
Push(x,y,S);
break;
}
elseif(p[x-1][y]==1&&p[x][y+1]==1&&p[x+1][y]==0)
{
i=x+1;
j=y;
p[i][j]=1;
x=i;
y=j;
Push(x,y,S);
break;
}
elseif(p[x-1][y]==1&&p[x][y+1]==1&&p[x+1][y]==1&&p[x][y-1]==0)
{
i=x;
j=y-1;
p[i][j]=1;
x=i;
y=j;
Push(x,y,S);
break;
}//判断弹出后栈顶元素周围有无通路
elseif(x==1&&y==1)
{
printf("Thereisnowayout");
getchar();
return0;
}//如果栈顶元素为入口则迷宫无出路
}
}
}while(i!
=n1-2||j!
=n2-2);//循环截止条件
}
printf("Success!
\nTherouteis:
\n");
for(i=0;;i++)
{
a=Topx(S);
b=Topy(S);
Pop(S);
x1[i]=a;
y1[i]=b;//将栈顶元素坐标存储在数组中
if(a==1&&b==1)
{
getchar();
break;
}
}
for(i=max-1;i>=0;)
{
if(x1[i]!
=0&&(x1[i]!
=x1[i-1]||y1[i]!
=y1[i-1]))
{
printf("<%d,%d>",x1[i],y1[i]);
i--;
}
elseif(x1[i]!
=0&&(x1[i]==x1[i-1]&&y1[i]==y1[i-1]))
{
printf("<%d,%d>",x1[i],y1[i]);
i=i-2;
}
else
i--;
}//倒序打印数组得到顺序出路坐标
printf("<%d,%d>",n1-2,n2-2);//打印出口坐标
getchar();
return0;
}
voidMakeNull(MAZE&S)//清空栈的函数
{
S=newnode;
S->next=NULL;
}
voidPush(Elementtypex,Elementtypey,MAZES)//压栈函数
{
MAZEstk;
stk=newnode;
stk->val1=x;
stk->val2=y;
stk->next=S->next;
S->next=stk;
}
voidPop(MAZES)//弹出函数
{
MAZEstk;
if(S->next)
{
stk=S->next;
S->next=stk->next;
deletestk;
}
}
ElementtypeTopx(MAZES)//返回横坐标函数
{
if(S->next)
return(S->next->val1);
else
returnNULL;
}
ElementtypeTopy(MAZES)//返回纵坐标函数
{
if(S->next)
return(S->next->val2);
else
returnNULL;
}
另一种方法实现的迷宫代码
#ifndefMMIGONG_H
#defineMMIGONG_H
#defineMAX_SIZE100
#include
usingnamespacestd;
structNode
{
intx;
inty;
intdi;
};
classStack
{
private:
intrrow;
intccolm;
inttop;
intcount;
intminlenght;
Nodestack[MAX_SIZE];
Nodesstack[MAX_SIZE];
public:
Stack();//初始化
//int**InsortMiGong();//输入迷宫(即一个二维数组)
voidFindPath(intab[][10]);//找出迷宫的出路
};
Stack:
:
Stack()//初始化
{
rrow=0;
ccolm=0;
top=-1;
count=1;
minlenght=MAX_SIZE;
}
/*int**Stack:
:
InsortMiGong()//输入迷宫(即一个二维数组)
{
introw=1,colm=1;
while(true)
{
cout<<"请输入迷宫的行数和列数:
";
cin>>row>>colm;
if(row<=0||colm<=0)
{
cout<<"输入错误!
请重新输入:
"<rrow=row;
ccolm=colm;
continue;
}
else
{
rrow=row;
ccolm=colm;
break;
}
}
int*mg[];
cout<<"请输入迷宫矩阵(只有0和1两个数构成):
";
for(inti=0;ifor(intj=0;jcin>>mg[i][j];
returnmg;
}*/
voidStack:
:
FindPath(intab[][10])//找出迷宫的出路
{
inta,b,di,find,k;
top++;stack[top].x=1;
stack[top].y=1;
stack[top].di=-1;
ab[1][1]=-1;
while(top>-1)
{
a=stack[top].x;
b=stack[top].y;
di=stack[top].di;
if(a==8&&b==8)
{
cout<"<for(intk=0;k<=top;k++)
{
cout<<"("<if(!
((k+1)%15))
cout<}
cout<if(top+1{
for(k=0;k<=top;k++)
sstack[k]=stack[k];
minlenght=top+1;
}
ab[stack[top].x][stack[top].y]=0;
top--;
a=stack[top].x;
b=stack[top].y;
di=stack[top].di;
}
find=0;
while(di<8&&!
find)
{
di++;
switch(di)
{
case0:
a=stack[top].x-1;b=stack[top].y;break;
case1:
a=stack[top].x;b=stack[top].y+1;break;
case2:
a=stack[top].x+1;b=stack[top].y;break;
case3:
a=stack[top].x;b=stack[top].y-1;break;
}
if(ab[a][b]==0)
find=1;
}
if(find==1)
{
stack[top].di=di;
top++;
stack[top].x=a;
stack[top].y=b;
stack[top].di=-1;
ab[a][b]=-1;
}
else
{
ab[stack[top].x][stack[top].y]=0;
top--;
}
}
cout<cout<<"走出迷宫最短的路径是:
"<cout<<"其长度为:
"<cout<<"路径是:
"<for(k=0;k{
cout<<"("<if(kcout<<"->";
if(!
((k+1)%10))
cout<}
cout<}
#endif
#include"MMIGONG.H"
voidmain()
{
Stackstack;
intab[10][10]=
{
{1,1,1,1,1,1,1,1,1,1,},
{1,0,0,1,0,0,0,1,0,1,},
{1,0,0,1,0,0,0,1,0,1,},
{1,0,0,0,0,1,1,0,0,1,},
{1,0,1,1,1,0,0,0,0,1,},
{1,0,0,0,1,0,0,0,0,1,},
{1,0,1,0,0,0,1,0,0,1,},
{1,0,1,1,1,0,1,1,0,1,},
{1,1,0,0,0,0,0,0,0,1,},
{1,1,1,1,1,1,1,1,1,1,},
};
cout<<"所有可以走出迷宫的路径有:
"<stack.FindPath(ab);
}
|