迷宫问题.docx
- 文档编号:5992202
- 上传时间:2023-01-02
- 格式:DOCX
- 页数:18
- 大小:122.18KB
迷宫问题.docx
《迷宫问题.docx》由会员分享,可在线阅读,更多相关《迷宫问题.docx(18页珍藏版)》请在冰豆网上搜索。
迷宫问题
《数据结构》实验报告三
题目:
迷宫问题
班级:
电子0802
学号:
14号
姓名:
日期:
2011.04.11
程序名:
一、上机实验的问题和要求:
迷宫问题(书P503.2.4和《数据结构题集》P1052.9):
以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
利用链栈结构,然后编写一个求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出,其中:
(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
如:
对于下列数据的迷宫,输出的一条通路为:
(1,1,1),(1,2,2),(2,2,2),(3,2,3),….。
测试数据:
0
0
1
0
0
0
1
0
0
0
1
0
0
0
1
0
0
0
0
0
1
1
0
1
0
1
1
1
0
0
1
0
0
0
0
1
0
0
0
0
0
1
0
0
0
1
0
1
0
1
1
1
1
0
0
1
1
1
0
0
0
1
0
1
1
1
0
0
0
0
0
0
二、程序设计的基本思想,原理和算法描述:
迷宫求解问题主要运用了堆栈的性质
求迷宫中一条从入口到出口的路径的算法描述:
do
{
若当前位置可通
则{
将当前位置插入栈顶;
若该位置时出口位置,则结束;
否则切换当前位置为东邻方块为新的当前位置;
}
否则
{
若栈不空且栈顶位置尚有其他方向未经探索,
则设定新的当前位置为沿顺时针方向旋转的栈顶位置的下一相邻模块
若栈不空但栈顶位置的四周均不可通
则{
删去栈顶位置;
若栈不空,则重新测试新的栈顶位置
直至找到一个可通的相邻模块或出栈至栈空;
}
}
}while(栈不空)
实现的函数为
/**************************************************************
若迷宫maze中从入口start到出口end的通道,则求得一条存放在栈中
**************************************************************/
StatusMazePath(intmaze[12][12],SqStack&S,PosTypestart,PosTypeend)
{
PosTypecurpos;
intcurstep;
SElemTypee;
InitStack(S);
curpos=start;//设定"当前位置"为"入口位置
curstep=1;//探索第一步
do
{
if(Pass(maze,curpos))//当前位置可通过,即是未曾走到过的通道块
{
Markfoot(maze,curpos);//留下足迹
e.di=1;
e.ord=curstep;
e.seat=curpos;
Push(S,e);//加入路径
if(curpos.row==end.row&&curpos.line==end.line)
returnOK;//到达终点(出口)
curpos=NextPos(curpos,1);//下一位置是当前位置的东邻
curstep++;//探索下一步
}
else//当前位置不能通过
{
if(!
StackEmpty(S))
{
Pop(S,e);
while(e.di==4&&!
StackEmpty(S))
{
Markfoot(maze,e.seat);//留下不能通过的标记,并退回一步
Pop(S,e);
}
if(e.di<4)
{
e.di++;//换下一个方向探索
Push(S,e);
curpos=NextPos(e.seat,e.di);//当前位置设为新方向的
//相邻块
}
}
}
}while(!
StackEmpty(S));
returnERROR;
}
围绕这个函数需要定义一些相关的函数操作,由以下函数实现
/**************************************************************
函数原型说明
**************************************************************/
StatusInitStack(SqStack&S);//创建一个空栈S
StatusPush(SqStack&S,SElemType&a);//插入新元素a
StatusPop(SqStack&S,SElemType&a);//删除栈顶元素,a返回其值
StatusStackEmpty(SqStackS);//检查是否空栈
StatusMazePath(intmaze[12][12],SqStack&S,PosTypestart,PosTypeend);
//找通路
voidInitmaze(intmaze[12][12],intsize);//初始化迷宫
voidprintmaze(intmaze[12][12],intsize);//显示迷宫
StatusPass(intmaze[12][12],PosTypeCurPos);//判断当前位置是否可通
voidMarkfoot(intmaze[12][12],PosTypeCurPos);//标记当前位置不可通
PosTypeNextPos(PosTypeCurPos,intDir);//进入下一位置
voidprintpath(intmaze[12][12],SqStackS,intsize);//显示通路
算法中我用正方形迷宫,即行数等于列数。
迷宫的存储我用了一个整形二维数组表示,
intsize;//正方形迷宫尺寸
intmaze[12][12];//存储迷宫内路径可通情况
二维数组存储的数字表示对应迷宫位置处可通与否,0表示可通,1表示不可通。
尺寸大小size可以设置,但是不能超过10,因为二维数组第一行,最后一行,第一列,最后一列一定要是不可通的,这是算法中用到的一个技巧。
迷宫内通道块位置变量类型定义为PosType
typedefstruct
{
introw;//row表示“行”号
intline;//line表示“列”号
}PosType;//位置的元素类型
这样判断其可通与否的语句为
if(maze[CurPos.row][CurPos.line]==0)
1.迷宫的初始化
voidInitmaze(intmaze[12][12],intsize);//初始化迷宫
迷宫的初始化有两种方法,一是随即生成,一是手动设置,由用户选择。
随即生成的方法是程序生成随机数,除以2取余
maze[i][j]=rand()%2;
手动设置是用户输入0,1由程序读取
scanf("%d",&maze[i][j]);
程序见第三部分。
2.显示迷宫
voidprintmaze(intmaze[12][12],intsize);//显示迷宫
只需要整齐打印出0,1即可,可以看到很好的效果
程序见第三部分。
3.显示通路
voidprintpath(intmaze[12][12],SqStackS,intsize);//显示通路
用到了一个技巧,只要是纳入堆栈的位置元素即为通路上的路径,将其迷宫对应位置
值变为2,
while(p!
=S.top)
{
maze[p->seat.row][p->seat.line]=2;//标记为路径中的点
p++;
}
然后显示通路时只要等于2的地方就打印一个0,否则打印空格。
if(maze[i][j]==2)printf("%c",'0');
elseprintf("");
程序见第三部分。
4.进入下一位置
PosTypeNextPos(PosTypeCurPos,intDir);//进入下一位置时按顺时针方向
//向下一位置探索
程序见第三部分。
5.堆栈操作,包括创建,入栈,出栈,判空。
StatusInitStack(SqStack&S);//创建一个空栈S
StatusPush(SqStack&S,SElemType&a);//插入新元素a
StatusPop(SqStack&S,SElemType&a);//删除栈顶元素,a返回其值
StatusStackEmpty(SqStackS);//检查是否空栈
程序见第三部分。
三、源程序及注释:
#include
#include
/**************************************************************
数据定义
**************************************************************/
typedefenum{ERROR,OK}Status;
typedefstruct
{
introw;//row表示“行”号
intline;//line表示“列”号
}PosType;//位置的元素类型
typedefstruct
{
intord;//该通道在路径上的“序号”
PosTypeseat;//通道块在迷宫中的“坐标位置”
intdi;//从此通道走向下以通道块的“方向”
}SElemType;//栈的元素类型
typedefstruct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
/**************************************************************
函数原型说明
**************************************************************/
StatusInitStack(SqStack&S);//创建一个空栈S
StatusPush(SqStack&S,SElemType&a);//插入新元素a
StatusPop(SqStack&S,SElemType&a);//删除栈顶元素,a返回其值
StatusStackEmpty(SqStackS);//检查是否空栈
StatusMazePath(intmaze[12][12],SqStack&S,PosTypestart,PosTypeend);//找通路
voidInitmaze(intmaze[12][12],intsize);//初始化迷宫
voidprintmaze(intmaze[12][12],intsize);//显示迷宫
StatusPass(intmaze[12][12],PosTypeCurPos);//判断当前位置是否可通
voidMarkfoot(intmaze[12][12],PosTypeCurPos);//标记当前位置不可通
PosTypeNextPos(PosTypeCurPos,intDir);//进入下一位置
voidprintpath(intmaze[12][12],SqStackS,intsize);//显示通路
/**************************************************************
主函数
**************************************************************/
voidmain(void)
{
SqStackS;
intsize;//正方形迷宫尺寸
intmaze[12][12];//存储迷宫内路径可通情况
for(intn=0;n<10;n++)
{
printf("创建一个正方形迷宫,请输入迷宫尺寸(注意不要大于10):
\n");//设置迷宫大小
scanf("%d",&size);if(size<1||size>10){printf("输入错误!
");return;}
Initmaze(maze,size);//初始化迷宫
printmaze(maze,size);//显示所创建的迷宫
PosTypestart,end;//设置入口和出口
printf("输入入口行坐标和列坐标:
");scanf("%d",&start.row);scanf("%d",&start.line);
printf("输入出口行坐标和列坐标:
");scanf("%d",&end.row);scanf("%d",&end.line);
if(MazePath(maze,S,start,end))//若有通路,显示通路
printpath(maze,S,size);
elseprintf("找不到通路!
\n\n");
}
}
/**************************************************************
若迷宫maze中从入口start到出口end的通道,则求得一条存放在栈中
**************************************************************/
StatusMazePath(intmaze[12][12],SqStack&S,PosTypestart,PosTypeend)
{
PosTypecurpos;
intcurstep;
SElemTypee;
InitStack(S);
curpos=start;//设定"当前位置"为"入口位置
curstep=1;//探索第一步
do
{
if(Pass(maze,curpos))//当前位置可通过,即是未曾走到过的通道块
{
Markfoot(maze,curpos);//留下足迹
e.di=1;
e.ord=curstep;
e.seat=curpos;
Push(S,e);//加入路径
if(curpos.row==end.row&&curpos.line==end.line)
returnOK;//到达终点(出口)
curpos=NextPos(curpos,1);//下一位置是当前位置的东邻
curstep++;//探索下一步
}
else//当前位置不能通过
{
if(!
StackEmpty(S))
{
Pop(S,e);
while(e.di==4&&!
StackEmpty(S))
{
Markfoot(maze,e.seat);//留下不能通过的标记,并退回一步
Pop(S,e);
}
if(e.di<4)
{
e.di++;//换下一个方向探索
Push(S,e);
curpos=NextPos(e.seat,e.di);//当前位置设为新方向的相邻块
}
}
}
}while(!
StackEmpty(S));
returnERROR;
}
/**************************************************************
初始化迷宫
**************************************************************/
voidInitmaze(intmaze[12][12],intsize)
{
charselect;
printf("选择创建方式A:
自动生成B:
手动创建\n");
label:
scanf("%c",&select);
if(select=='a'||select=='A')//自动生成
{
for(inti=0;i for(i=1;i { maze[i][0]=1; for(intj=1;j maze[i][j]=rand()%2; maze[i][size+1]=1; } for(i=0;i } elseif(select=='b'||select=='B')//手动设置 { printf("按行输入%d*%d数据,0代表可通,1代表不可通(每行以Enter结束): \n",size,size); for(inti=0;i for(i=1;i { maze[i][0]=1; for(intj=1;j scanf("%d",&maze[i][j]); maze[i][size+1]=1; } for(i=0;i } elseif(select=='\n')gotolabel;//排除Enter键的影响 elseprintf("输入错误! "); } /************************************************************** 显示迷宫 **************************************************************/ voidprintmaze(intmaze[12][12],intsize) { printf("\n\n"); printf("显示所建的迷宫(#表示外面的墙): \n"); for(inti=0;i for(i=1;i { printf("%c",'#'); for(intj=1;j { printf("%d",maze[i][j]); } printf("%c",'#'); printf("\n"); } for(i=0;i } /************************************************************** 输出路径 **************************************************************/ voidprintpath(intmaze[12][12],SqStackS,intsize) { printf("\n\n通路路径为: \n"); SElemType*p=S.base; while(p! =S.top) { maze[p->seat.row][p->seat.line]=2;//标记为路径中的点 p++; } for(inti=0;i for(i=1;i { printf("%c",'#'); for(intj=1;j { if(maze[i][j]==2)printf("%c",'0'); elseprintf(""); } printf("%c",'#'); printf("\n"); } for(i=0;i } /************************************************************** 判断当前位置是否可通 **************************************************************/ StatusPass(intmaze[12][12],PosTypeCurPos) { if(maze[CurPos.row][CurPos.line]==0) returnOK;//如果当前位置是可以通过,返回1 elsereturnERROR;//其它情况返回0 } /************************************************************** 标记当前位置不可通 **************************************************************/ voidMarkfoot(intmaze[12][12],PosTypeCurPos) { maze[CurPos.row][CurPos.line]=1; } /************************************************************** 进入下一位置 **************************************************************/ PosTypeNextPos(PosTypeCurPos,intDir) { PosTypeReturnPos; switch(Dir) { case1: //下一模块为东临模块 ReturnPos.row=CurPos.row; ReturnPos.line=CurPos.line+1; break; case2: //下一模块为南临模块 ReturnPos.row=CurPos.row+1
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 问题
![提示](https://static.bdocx.com/images/bang_tan.gif)