迷宫课程设计报告.docx
- 文档编号:25365931
- 上传时间:2023-06-07
- 格式:DOCX
- 页数:27
- 大小:307.08KB
迷宫课程设计报告.docx
《迷宫课程设计报告.docx》由会员分享,可在线阅读,更多相关《迷宫课程设计报告.docx(27页珍藏版)》请在冰豆网上搜索。
迷宫课程设计报告
迷宫课程设计报告
西安郵電大學
数据结构课程设计报告
题目:
迷宫问题
院系名称:
计算机学院
专业名称:
软件工程
班级:
1101
学生姓名:
武妍娜
学号(8位):
04113027
指导教师:
李培
设计起止时间:
2012年12月3日~2012年12月14日
一.设计目的
1.熟悉C语言程序的编辑、编译链接和运行的过程,能够熟练地编辑、编译及调试程序。
2.掌握文件和文件指针的概念以及文件的定义方法,学会熟练使用文件打开、关闭、读、写等基本操作。
3.熟练掌握结构体、链表、指针的使用,及函数间的调用。
4.能够熟练运用所学栈的相关知识及操作,顺利完成题目的要求。
二.设计内容
迷宫是实验心理学中一个古典问题。
用计算机解迷宫路径的程序,就是仿照人走迷宫。
计算机解迷宫时,通常用的是"穷举求解"的方法,即从入口出发,顺某一方向向前探索,若能走通,则继续往前走;否则沿原路退回,换一个方向再继续探索,直至所有可能的通路都探索到为止。
1.功能与数据需求
迷宫求解问题描述:
以一个M×N的矩阵表示迷宫,0和1分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
1.1题目要求的功能
(1)基本要求:
首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。
求得的通路以二元组(i,j)的形式输出,其中:
(i,j)指迷宫中对应的坐标。
(2)测试数据:
①左上角(1,1)为入口,右下角(9,8)为出口。
②左上角(1,1)为入口,右上角(1,8)为出口。
(3)如下图所示:
(4)
1.2扩展功能
(1)编写非递归形式的算法,求得迷宫中所有可能的通路;
(2)以方阵形式输出迷宫及其通路
2.界面需求
(1)在菜单中选择要执行的操作
(2)输出方阵迷宫
(3)用户自己输入迷宫起始位置
(4)输出所走的迷宫路径
(5)输出方阵路径,并保存到文件中
3.开发环境与运行需求
MicrosoftVisualC++6.0
Ubuntu
三.概要设计
1.功能模块图;
本程序包含三个模块
(1)主程序模块:
voidmain()
{
初始化;
do{
接受命令;
处理命令;
}while(命令!
=“退出”);
}
(2)栈模块——实现栈抽象数据类型
(3)迷宫模块——实现迷宫抽象数据类型
2.各个模块详细的功能描述。
(1)菜单:
从菜单中选择要执行的操作
(2)文件模块:
实现文件的各项基本操作
a)打开文件b)关闭文件
c)从文件读信息d)向文件中写入内容
(3)栈模块:
实现栈的各项基本操作
a)初始化栈b)入栈
c)出栈d)取栈顶元素
(4)迷宫模块:
求解迷宫问题
a)显示迷宫b)获取迷宫路径
c)判断当前路径是否走过d)获得下一个可走的位置
e)获得东面,南面,西面,北面相邻的位置
四.详细设计
1.功能函数的调用关系图
2.各功能函数的数据流程图
(1)获得迷宫路径函数
dowhile(cur.x!
=chukou[0]||cur.y!
=chukou[1])
是否
elseif
if
(2)
获得下一个可通行的位置
ifelseif
elseifelseif
3.重点设计及编码
获得迷宫路径的函数:
intGetMazePath()
{
MStackElemstart,cur;
start.x=rukou[0];
start.y=rukou[1];
start.val=Maze[rukou[0]][rukou[1]];
cur=start;
do
{
if(UnPass(path,cur))
{
Push(&realPath,cur);
Push(&path,cur);
cur=GetNext(cur);
if(cur.x==chukou[0]&&cur.y==chukou[1])
{
Push(&realPath,cur);
Push(&path,cur);
return1;
}
elseif(cur.val==-1)
{
Pop(&realPath);
cur=GetTop(&realPath);
}
}
else
{
cur=GetNext(cur);
if(cur.val==-1)
{
Pop(&realPath);
cur=GetTop(&realPath);
}
}
}while(cur.x!
=chukou[0]||cur.y!
=chukou[1]);
return0;
}
五.测试数据及运行结果
1.正常测试数据和运行结果
2.异常测试数据及运行结果
六.调试情况,设计技巧及体会
1.改进方案
在迷宫问题中,由于走的方向顺序不同,存在着多条路径的结果。
因此就出现了一个最大的问题,哪条路径最短,即求最短路径。
由于时间有限和难度问题,我没能及时解决这个问题,这也是在这次的迷宫课程设计中,我唯一的不足之处。
不过我并没有放弃,课程设计结束后,我还会继续努力,解决掉这个问题。
在以后的生活中,我也会不断督促自己,提高编程能力。
2.体会
刚开始,头脑里没有任何思路,不知道如何下手,经过仔细研读课本和上网查资料后,终于有了思绪。
先将整个程序划分为三个大模块:
主模块,栈模块和迷宫模块。
然后再依次实现每个大模块中的小操作。
最后将所有的程序拼接起来,进行调试。
我觉得所有模块中最难编的就是查找迷宫路径函数,经过苦思冥想,再加上老师和同学的帮助,总算做出来了,但是非常复杂。
在编译的过程中总会出现五花八门的错误,比如:
从文件里读不出信息,又或者是存不进去文件,或者是乱码等。
后来才发现原来是源文件中存的信息类型和程序中定义的类型不匹配,经过改正之后果然正确了。
改正完后,当把所有的小块连接在一起时,虽然没有错误,但是总有许多警告语句,运行的结果也不尽人意。
通过上网查资料后,发现这都是一些格式问题。
看来编程格式很重要啊!
经过两个星期的上机实践学习,我才发现我的C语言上机实践能力还有待加强,有待进步。
以后不但要重视课本与习题,更要重视上机实践。
七.参考文献
1.耿国华主编,《数据结构——C语言描述》,高等教育出版社,2005年
2.陈锐,《数据结构(C语言版)》,清华大学出版社2012年
八.附录
#include
#include
#include
#defineM11//迷宫行数
#defineN10//迷宫列数
#defineSTACK_INIT_SIZE100
#defineSTACKINCREMENT10
charMaze[M][N]={0};//迷宫
chars[M][N]={0};//迷宫路线图
intrukou[2],chukou[2];
//定义栈元素类型
typedefstruct
{
intx;//x坐标
inty;//y坐标
charval;//Maze[x][y]的值
}MStackElem;
//定义栈
typedefstruct
{
MStackElem*base;
MStackElem*top;
intStackSize;
}MStack;
//初始化栈
InitStack(MStack*S)
{
S->base=(MStackElem*)malloc(STACK_INIT_SIZE*sizeof(MStackElem));
if(!
S->base)
{
printf("初始化栈失败!
\n");
exit(-1);//存储分配失败
}
S->top=S->base;
S->StackSize=STACK_INIT_SIZE;
}
//入栈
Push(MStack*S,MStackEleme)
{
//向栈中添加元素前先判断栈是否还有空间容纳新元素
if(S->top-S->base>=S->StackSize)//栈满,追加元素
{
S->base=(MStackElem*)realloc(S->base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(MStackElem));
if(!
S->base)
{
printf("空间不足,入栈失败!
\n");
exit(-1);//存储分配失败
}
S->top=S->base+S->StackSize;//因为是重新分配了空间,所以base的值其实已经改变,所以top的值也就相应的改变,才能指向新的迷宫栈
S->StackSize+=STACKINCREMENT;
}
*(S->top++)=e;//将新元素加到栈顶
}
//获得栈顶元素
MStackElemGetTop(MStack*S)
{
if(S->top==S->base)
{
printf("\n对不起,没有出路!
\n\n");
exit(0);
}
else
return*(S->top-1);
}
//出栈
Pop(MStack*S)
{
//若栈不为空,则删除s的栈顶元素
if(S->top==S->base)
{
printf("栈为空,出栈失败!
\n");
exit(0);
}
else
--(S->top);
}
MStackrealPath,path;//构造两个栈,一个用来保存探索中的全部路径,一个用来保存有效路径
//判断当前位置是否走过
intUnPass(MStackpath,MStackElemcur)//这里不能传path的地址,否则在遍历过程中它的top值就被改了
{
intflag=1;//未走过
while(path.top!
=path.base)
{
MStackEleme=*(path.top-1);
if(e.x==cur.x&&e.y==cur.y)
flag=0;//曾走过
(path.top)--;//每循环一次令头指针下移一个位置
}
returnflag;
}
//获得东面(即右边)相邻的位置
MStackElemGetEast(MStackElemcur)
{
if(cur.y!
=N-2)//当y==N-2时已到了迷宫右边界,不能再向东(右)行了
{
cur.y+=1;
cur.val=Maze[cur.x][cur.y];
}
returncur;//当y==N-2时返回的是它本身
}
//获得南面(即下边)相邻的位置
MStackElemGetSouth(MStackElemcur)
{
if(cur.x!
=M-2)//当x==M-2时已到了迷宫下边界,不能再向南(下)行了
{
cur.x+=1;
cur.val=Maze[cur.x][cur.y];
}
returncur;//当x==M-2时返回的是它本身
}
//获得西面(即左边)相邻的位置
MStackElemGetWest(MStackElemcur)
{
if(cur.y!
=1)//当y==1时已到了迷宫左边界,不能再向西(左)行了
{
cur.y-=1;
cur.val=Maze[cur.x][cur.y];
}
returncur;//当y==1时返回的是它本身
}
//获得北面(即上边)相邻的位置
MStackElemGetNorth(MStackElemcur)
{
if(cur.x!
=1)//当cur.x==1时表示在迷宫的上边界,不能再向北(上)行了
{
cur.x-=1;
cur.val=Maze[cur.x][cur.y];
}
returncur;//当cur.x==1时返回的还是它本身
}
//获得下一个可通行的位置,按东南西北(即顺时针)的方向试探
MStackElemGetNext(MStackElemcur)
{
MStackElemnext;
next.x=next.y=next.val=-1;
if(GetEast(cur).val==''&&UnPass(path,GetEast(cur)))
next=GetEast(cur);
elseif(GetSouth(cur).val==''&&UnPass(path,GetSouth(cur)))
next=GetSouth(cur);
elseif(GetWest(cur).val==''&&UnPass(path,GetWest(cur)))
next=GetWest(cur);
elseif(GetNorth(cur).val==''&&UnPass(path,GetNorth(cur)))
next=GetNorth(cur);
returnnext;//如果当前位置的四面或为墙或已走过,则返回的next的val值为-1
}
//获得迷宫路径的函数
intGetMazePath()
{
MStackElemstart,cur;
start.x=rukou[0];
start.y=rukou[1];
start.val=Maze[rukou[0]][rukou[1]];//入口坐标的值
cur=start;//设定当前位置为"入口位置"
do
{
if(UnPass(path,cur))//如果当前位置未曾走到过
{
Push(&realPath,cur);
Push(&path,cur);
cur=GetNext(cur);
if(cur.x==chukou[0]&&cur.y==chukou[1])//到达出口
{
Push(&realPath,cur);//把出口结点放入路径中
Push(&path,cur);
return1;
}
elseif(cur.val==-1)//当前位置的四面都为墙
{
Pop(&realPath);//删除真实路径的栈顶元素
cur=GetTop(&realPath);//令cur指向栈顶元素
}
}
else//如果当前位置已经走过,说明原来测试的方向不对,现在尝试其它方向
{
cur=GetNext(cur);
if(cur.val==-1)
{
Pop(&realPath);//仍不通,删除真实路径的栈顶元素
cur=GetTop(&realPath);//令cur指向栈顶元素
}
}
}while(cur.x!
=chukou[0]||cur.y!
=chukou[1]);
return0;
}
//输出迷宫路径
PrintMazePath(MStack*S)//为了安全,这里不传MStack的地址,以防在遍历的过程中把它们的top或base的值也修改了
{
MStackEleme;
inti,j;
for(i=0;i for(j=0;j s[i][j]=Maze[i][j]; while(S->base<(S->top-1)) { e=*(S->base);//先指向栈底元素,以后依次向上增1 s[e.x][e.y]='.'; printf("(%d,%d)----->",e.x,e.y); (S->base)++; } //最后一个结点没有后继,所以不再输出"------>" e=*(S->base); s[e.x][e.y]='.'; printf("(%d,%d)",e.x,e.y); } //打开文件,获取迷宫 OpenFile() { FILE*fp; inti,j,c; system("cls"); if((fp=fopen("in.txt","rt"))==NULL)//打开迷宫文件in.txt { printf("打开文件失败! \n"); exit (1); } for(i=0;i {for(j=0;j fscanf(fp,"%c",&Maze[i][j]); fscanf(fp,"%c",&c);//换行 } fclose(fp); } //保存迷宫路线图 SaveFile() { FILE*fp; inti,j; charstr[M][N+1]; for(i=0;i { for(j=0;j str[i][j]=s[i][j]; str[i][j]='\n'; } str[M-1][N]='\0';//结束符 if((fp=fopen("out.txt","wt"))==NULL) { printf("存储文件失败! \n"); exit (1); } fputs(str,fp);//保存文件 printf("\n迷宫文件保存成功,文件名为: out.txt。 \n\n"); system("pause"); fclose(fp); } //输出迷宫 Print1() { intm,n; printf("\n迷宫('#'代表墙即不通,''代表通路即可通过)\n\n"); for(m=0;m { printf("\t\t"); for(n=0;n printf("%c",Maze[m][n]); printf("\n"); } } //输出迷宫路线图 Print2() { intm,n; printf("\n迷宫路线如下: \n'#'代表不通即墙,''代表通路即可通过,'.'代表行走路线,'>'代表入口,'<'代表出口.\n\n"); s[rukou[0]][rukou[1]]='>';//入口标志 s[chukou[0]][chukou[1]]='<';//出口标志 for(m=0;m { printf("\t\t"); for(n=0;n printf("%c",s[m][n]); printf("\n"); } } //菜单函数 Menu() { printf("\t\t******************************************\n"); printf("\t\t***欢迎进入课程设计***\n"); printf("\t\t***迷宫求解程序***\n"); printf("\t\t******\n"); printf("\t\t***1.显示迷宫***\n"); printf("\t\t***2.进入迷宫***\n"); printf("\t\t***3.打印迷宫***\n"); printf("\t\t***0.退出迷宫***\n"); printf("\t\t******************************************\n"); } Flower() { printf("\t{@}\n"); printf("\t{@}*{@}\n"); printf("\t{@}*{@}*{@}\n"); printf("\t{@}*{@}*{@}*{@}\n"); printf("\t\\{@}*{@}*{@}\/\n"); printf("\t\\\\\\l\/\/\/\n"); printf("\t\\\\\\Y\/\/\/\n"); printf("\t\\\\l\/\/\n"); printf("\t\\\\Y\/\/\n"); printf("\t>=<\n"); printf("\t\/\/*\\\\\n\n"); } //主函数 intmain() { intchoice;//x[]用来输入迷宫入口坐标,y[]用来输入迷宫出口坐标 OpenFile();//打开迷宫文件 do { system("cls");//清屏 Menu();//调用菜单函数 printf("\n请输入您的选择: "); scanf("%d",&choice); switch(choice) { case1: system("cls"); Print1();//显示迷宫 printf("\n"); system("pause"); break; case2: //进入迷宫 system("cls"); printf("\n请输入入口坐标: "); scanf("%d%d",&rukou[0],&rukou[1]);//迷宫入口坐标 printf("\n请输入出口坐标: "); scanf("%d%d",&chukou[0],&chukou[1]);//迷宫出口坐标 if(rukou[0]>M-2||rukou[1]>N-2||chukou[0]>M-2||chukou[1]>N-2||rukou[0]<0||rukou[1]<0||chukou[0]<0||chukou[1]<0) printf("输入的入口或出口坐标错误! \n");//判断输入坐标是否正确
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 课程设计 报告