迷宫设计实验报告.docx
- 文档编号:26137571
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:24
- 大小:144.20KB
迷宫设计实验报告.docx
《迷宫设计实验报告.docx》由会员分享,可在线阅读,更多相关《迷宫设计实验报告.docx(24页珍藏版)》请在冰豆网上搜索。
迷宫设计实验报告
天津商业大学
《数据结构》课程设计报告
题目:
迷宫问题
学院:
信息工程学院
专业:
计算机科学与技术
班级:
13-01班
姓名:
王
同组人员:
谭
指导教师:
黄
2014
年
12
月
26
日
1.课程设计的容
【问题描述】
以一个m×n的长方阵表示迷宫,0和1表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条入口到出口的通路,或得出没有通路的结论。
【基本要求】
首先实现一个栈类型,然后编写一个求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出,其中:
(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
如:
对于下列数据的迷宫,输出的一条通路为:
(1,1,1),(1,2,2),(2,2,2)(3,2,3),(3,1,2)……
2.需求分析
(1)以二维数组maze[M+2][N+2]表示迷宫,其中maze[i][0]和maze[i][N+1](0=
数组中元素0表示障碍1表示可通过,迷宫的大小可不限;
(2)迷宫中的数据均由用户自由输入;
(3)迷宫的出口和入口可由用户自由设定;
(4)本程序只求出一条成功的通路;
(5)程序执行的命令为:
①创建迷宫②求解迷宫③输出迷宫的解
3.概要设计
3.1抽象数据类型定义
(1)设定栈的抽象数据类型定义:
ADTStack{
数据对象:
D={ai|ai∈CharSet,i=1,2,…,n,n>=0}
数据关系:
基本操作:
InitStack(&S)
操作结果:
构造一个空栈S。
DestroyStack(&S)
初始结果:
栈S已存在。
操作结果:
销毁栈S。
ClearStack(&S)
初始结果:
栈S已存在。
操作结果:
将S清为空栈。
StackLength(S)
初始结果:
栈S已存在。
操作结果:
返回栈S的长度
StackEmpty(S)
初始条件:
栈S已存在。
操作结果:
若S为空栈,则返回TRUE,否则返回FALSE
GetTop(S,&e)
初始条件:
栈S已存在。
操作结果:
若栈S不空,则以e返回栈顶元素e。
Push(&S,e)
初始条件:
栈S已存在。
操作结果:
在栈S的栈顶插入新的栈顶元素。
Pop(&S,&e)
初始条件:
栈S已存在。
操作结果:
删除S的栈顶元素,并以e返回其值。
StackTraverse(S,visit())
初始条件:
栈S已存在。
操作结果:
从栈底到栈顶依次对S中的每个元素调用visit()
}ADTStack
(2)设定迷宫的抽象数据类型为:
ADTmaze{
数据对象:
D={a(i,j)|a(i,j)∈{0,1},0=
数据关系:
R={M,N}
M={|a(i-1,j),a(i,j)∈D,i=1,2,…,m+1,j=0,1,…n+1}
N={|a(i,j-1),a(i,j)∈D,I=0,1,…m+1,j=1,2,…n+1}
基本操作:
InitMaze(&M,maze,m,n)
初始条件:
二维数组maze[m+1][n+1]已存在,其中自第一行至第m+1行、每行中自第一列至第n+1列的元素已有值,并且以值0表示通路,以值1表示障碍。
操作结果:
构成迷宫的字符型数组,以字符0表示通路,以字符1障碍,并在迷宫四周加上一圈障碍。
MazePath(&M)
初始条件:
迷宫M已被赋值。
操作结果:
若迷宫M中存在一条通路,则按如下规定改变迷宫M的状态:
以数字0代表可通过,数字1代表不可通过。
3.1模块划分
(1)主程序模块:
voidmain()
{
intsto[M][N];
structmarkstart,end;//start,end入口和出口的坐标
intadd[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//行增量和列增量方向依次为东西南北
initmaze(sto);//建立迷宫
printf("输入入口的横坐标,纵坐标[逗号隔开]\n");
scanf("%d,%d",&start.x,&start.y);
printf("输入出口的横坐标,纵坐标[逗号隔开]\n");
scanf("%d,%d",&end.x,&end.y);
MazePath(start,end,sto,add);//findpath
system("PAUSE");
}
(2)栈模块——实现栈抽象数据类型;
(3)迷宫模块——实现迷宫抽象数据类型,建立迷宫,求解迷宫的一条路径。
4.详细设计
4.1数据类型的定义
(1)坐标位置,类型:
structmark//定义迷宫点的坐标类型
{
intx;
inty;
};
(2)迷宫类型
voidinitmaze(intmaze[M][N])
//按照用户输入的M行和N列的二维数组(元素值为0或1)
//设置迷宫maze的初值,包括加上边缘一圈的值
voidMazePath(structmarkstart,structmarkend,intmaze[M][N],intdiradd[4][2])
//求解迷宫maze中从入口Start到出口end的一条路径
//若存在,则返回TRUE,否则返回FALSE
(3)栈类型
structElement
{
intx,y;//x行,y列
intd;//d下一步的方向
};
typedefstructLStack//链栈
{
Elementelem;
structLStack*next;
}*PLStack;
4.2主要模块的算法描述
(1)求迷宫路径的伪码算法
voidMazePath(structmarkstart,structmarkend,intmaze[M][N],intdiradd[4][2])
{
inti,j,d;inta,b;
Elementelem,e;
PLStackS1,S2;
InitStack(S1);
InitStack(S2);
maze[start.x][start.y]=2;//入口点作上标记
elem.x=start.x;
elem.y=start.y;
elem.d=-1;//开始为-1
Push(S1,elem);
while(!
StackEmpty(S1))//栈不为空有路径可走
{
Pop(S1,elem);
i=elem.x;
j=elem.y;
d=elem.d+1;//下一个方向
while(d<4)//试探东南西北各个方向
{
a=i+diradd[d][0];
b=j+diradd[d][1];
if(a==end.x&&b==end.y&&maze[a][b]==0)//如果到了出口
{
elem.x=i;
elem.y=j;
elem.d=d;
Push(S1,elem);
elem.x=a;
elem.y=b;
elem.d=886;//方向输出为-1判断是否到了出口
Push(S1,elem);
printf("\n0=东1=南2=西3=北886为则走出迷宫\n\n通路为:
(行坐标,列坐标,方向)\n");
while(S1)//逆置序列并输出迷宫路径序列
{
Pop(S1,e);
Push(S2,e);
}
while(S2)
{
Pop(S2,e);
printf("-->(%d,%d,%d)",e.x,e.y,e.d);
}
return;//跳出两层循环,本来用break,但发现出错,exit又会结束程序,选用return还是不错滴o(∩_∩)o...
}
if(maze[a][b]==0)//找到可以前进的非出口的点
{
maze[a][b]=2;//标记走过此点
elem.x=i;
elem.y=j;
elem.d=d;
Push(S1,elem);//当前位置入栈
i=a;//下一点转化为当前点
j=b;
d=-1;
}
d++;
}
}
printf("没有找到可以走出此迷宫的路径\n");
}
(2)建立迷宫的伪码算法
voidinitmaze(intmaze[M][N])
{
inti,j;
intm,n;//迷宫行,列
printf("请输入迷宫的行数m=");
scanf("%d",&m);
printf("请输入迷宫的列数n=");
scanf("%d",&n);
printf("\n请输入迷宫的各行各列:
\n用空格隔开,0代表路,1代表墙\n",m,n);
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
maze[i][j]=(int)(rand()%2);
//scanf("%d",&maze[i][j]);
printf("你建立的迷宫为o(∩_∩)o...\n");
for(i=0;i<=m+1;i++)//加一圈围墙
{
maze[i][0]=1;
maze[i][n+1]=1;
}
for(j=0;j<=n+1;j++)
{
maze[0][j]=1;
maze[m+1][j]=1;
}
for(i=0;i<=m+1;i++)//输出迷宫
{
for(j=0;j<=n+1;j++)
printf("%d",maze[i][j]);
printf("\n");
}
}
(3)主函数的伪码算法:
voidmain()
{
intsto[M][N];
structmarkstart,end;//start,end入口和出口的坐标
intadd[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//行增量和列增量方向依次为东西南北
initmaze(sto);//建立迷宫
printf("输入入口的横坐标,纵坐标[逗号隔开]\n");
scanf("%d,%d",&start.x,&start.y);
printf("输入出口的横坐标,纵坐标[逗号隔开]\n");
scanf("%d,%d",&end.x,&end.y);
MazePath(start,end,sto,add);//findpath
system("PAUSE");
}
(4)栈的初始化、判空、进栈、和出栈等的伪码算法:
intInitStack(PLStack&S)//构造空栈
{
S=NULL;
return1;
}
intStackEmpty(PLStackS)//判断栈是否为空
{
if(S==NULL)
return1;
else
return0;
}
intPush(PLStack&S,Elemente)//压入新数据元素
{
PLStackp;
p=(PLStack)malloc(sizeof(LStack));
p->elem=e;
p->next=S;
S=p;
return1;
}
intPop(PLStack&S,Element&e)//栈顶元素出栈
{
PLStackp;
if(!
StackEmpty(S))
{
e=S->elem;
p=S;
S=S->next;
free(p);
return1;
}
else
return0;
}
4.3函数之间的调用关系
5.程序运行说明与测试
5.1用户手册
(1)本程序的运行环境为C语言的运行环境,新建文件的后缀名:
.cpp
(2)进入演示程序后,即显示以下的用户界面:
①、点击组建进行“编译”;
②、点击
运行程序;
(3)执行程序出现界面后,按照提示先迷宫的行数和列数回车,进一步输入迷宫的数据‘1’代表墙,‘0’代表路径回车;输入迷宫的“入口”和“出口”
回车即可现实路径,或者显示没有路径可走。
5.2测试数据
(1)输入行数:
3;输入列数:
2
输入迷宫数据为:
00
00
00
入口位置:
11
出口位置:
32
(2)输入行数:
3;输入列数:
4
输入迷宫数据:
0000
0011
0000
入口位置:
11
出口位置:
34
(3)输入行数:
4;输入列数:
9
输入迷宫数据:
000000100
010001000
001110011
001110100
入口位置:
11
出口位置:
49
(4)输入行数:
8;输入列数:
9
输入迷宫数据:
00100010
00100010
00001101
01110010
00010000
01000101
01111001
11000101
11000000
入口位置:
11
出口位置:
89
5.3测试结果及分析
(1)
(2)
(3)
(4)
6.实验总结
(1)本次算法涉及迷宫的求解路径和迷宫的建立函数;建立迷宫函数时可自由确定迷宫的行数和列数,及迷宫的数据也可自由输入;但在建立迷宫数据时一开始使用的是随机函数,但是用此方法生成的迷宫行数列数一致时迷宫也是一致,且找不着路径;
(2)本题中的主要算法:
MazePath和initmaze的时间复杂度为O(m*n),本题的空间复杂度异为O(m*n)(栈所占的最大空间)
附:
源程序清单
#include
#include
#defineM15
#defineN15
structmark//定义迷宫点的坐标类型
{
intx;
inty;
};
structElement//"恋"栈元素,嘿嘿。
。
{
intx,y;//x行,y列
intd;//d下一步的方向
};
typedefstructLStack//链栈
{
Elementelem;
structLStack*next;
}*PLStack;
/*************栈函数****************/
intInitStack(PLStack&S)//构造空栈
{
S=NULL;
return1;
}
intStackEmpty(PLStackS)//判断栈是否为空
{
if(S==NULL)
return1;
else
return0;
}
intPush(PLStack&S,Elemente)//压入新数据元素
{
PLStackp;
p=(PLStack)malloc(sizeof(LStack));
p->elem=e;
p->next=S;
S=p;
return1;
}
intPop(PLStack&S,Element&e)//栈顶元素出栈
{
PLStackp;
if(!
StackEmpty(S))
{
e=S->elem;
p=S;
S=S->next;
free(p);
return1;
}
else
return0;
}
/***************求迷宫路径函数***********************/
voidMazePath(structmarkstart,structmarkend,intmaze[M][N],intdiradd[4][2])
{
inti,j,d;inta,b;
Elementelem,e;
PLStackS1,S2;
InitStack(S1);
InitStack(S2);
maze[start.x][start.y]=2;//入口点作上标记
elem.x=start.x;
elem.y=start.y;
elem.d=-1;//开始为-1
Push(S1,elem);
while(!
StackEmpty(S1))//栈不为空有路径可走
{
Pop(S1,elem);
i=elem.x;
j=elem.y;
d=elem.d+1;//下一个方向
while(d<4)//试探东南西北各个方向
{
a=i+diradd[d][0];
b=j+diradd[d][1];
if(a==end.x&&b==end.y&&maze[a][b]==0)//如果到了出口
{
elem.x=i;
elem.y=j;
elem.d=d;
Push(S1,elem);
elem.x=a;
elem.y=b;
elem.d=886;//方向输出为-1判断是否到了出口
Push(S1,elem);
printf("\n0=东1=南2=西3=北886为则走出迷宫\n\n通路为:
(行坐标,列坐标,方向)\n");
while(S1)//逆置序列并输出迷宫路径序列
{
Pop(S1,e);
Push(S2,e);
}
while(S2)
{
Pop(S2,e);
printf("-->(%d,%d,%d)",e.x,e.y,e.d);
}
return;//跳出两层循环,本来用break,但发现出错,exit又会结束程序,选用return还是不错滴o(∩_∩)o...
}
if(maze[a][b]==0)//找到可以前进的非出口的点
{
maze[a][b]=2;//标记走过此点
elem.x=i;
elem.y=j;
elem.d=d;
Push(S1,elem);//当前位置入栈
i=a;//下一点转化为当前点
j=b;
d=-1;
}
d++;
}
}
printf("没有找到可以走出此迷宫的路径\n");
}
/*************建立迷宫*******************/
voidinitmaze(intmaze[M][N])
{
inti,j;
intm,n;//迷宫行,列
printf("请输入迷宫的行数m=");
scanf("%d",&m);
printf("请输入迷宫的列数n=");
scanf("%d",&n);
printf("\n请输入迷宫的各行各列:
\n用空格隔开,0代表路,1代表墙\n",m,n);
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
//maze[i][j]=(int)(rand()%2);
scanf("%d",&maze[i][j]);
printf("你建立的迷宫为o(∩_∩)o...\n");
for(i=0;i<=m+1;i++)//加一圈围墙
{
maze[i][0]=1;
maze[i][n+1]=1;
}
for(j=0;j<=n+1;j++)
{
maze[0][j]=1;
maze[m+1][j]=1;
}
for(i=0;i<=m+1;i++)//输出迷宫
{
for(j=0;j<=n+1;j++)
printf("%d",maze[i][j]);
printf("\n");
}
}
voidmain()
{
intsto[M][N];
structmarkstart,end;//start,end入口和出口的坐标
intadd[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//行增量和列增量方向依次为东西南北
initmaze(sto);//建立迷宫
printf("输入入口的横坐标,纵坐标[逗号隔开]\n");
scanf("%d,%d",&start.x,&start.y);
printf("输入出口的横坐标,纵坐标[逗号隔开]\n");
scanf("%d,%d",&end.x,&end.y);
MazePath(start,end,sto,add);//findpath
system("PAUSE");
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 设计 实验 报告