设计报告 题目04 迷宫求解Word文件下载.docx
《设计报告 题目04 迷宫求解Word文件下载.docx》由会员分享,可在线阅读,更多相关《设计报告 题目04 迷宫求解Word文件下载.docx(35页珍藏版)》请在冰豆网上搜索。
2.第一行的数据为迷宫的行数m和列数n;
从第2行到第m+1为迷宫值,同一行两个数字之间用空格表示。
3.实现一个以链表作存储结构的栈类型。
4.编写一个求解迷宫的非递归程序。
5.迷宫的入口位置和出口位置可由用户自己设定
6.本程序只求出一条成功的通路求得的通路以三元组(i,j,d)的形式输出,其中:
(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
7.测试数据:
迷宫的测试数据如下:
左上角(1,1)为入口,右下角(9,8)为出口
1
8.程序执行的命令为:
1)创建迷宫;
2)求解迷宫;
3)输出迷宫的解。
2.2过程论述
程序运行后,主界面会显示主菜单,然后选择1创建迷宫,然后会提示输入行数和列数,接下来便可以任意创建迷宫,其中用1表示障碍0表示通路,创建完迷宫后自己任意输入出口和入口的坐标系统便会显示每一步的方向和最终的路线。
至此便完成了迷宫的创建和走出迷宫的过程。
三、程序及功能说明
3.1三个模块
1)主程序模块:
voidmain()
{
初始化;
do{
接受命令;
处理命令;
}while(命令!
=”退出”);
}
2)栈模块------实现栈的抽象数据类型
3)迷宫模块----实现迷宫抽象数据类型
各个模块之间的调用关系如下:
主程序模块->
迷宫模块
->
栈模块
3.2各功能函数
3.2.1位坐标置类型
typedefstructposition//定义坐标
intx;
//当前横坐标
inty;
//当前纵坐标
}position;
3.2.2迷宫类型
1.初始化迷宫
voidInitMaze(intMaze[N][N],intm,intn)//初始化迷宫
inti,j;
print
(2);
printf("
请输入迷宫:
|\n"
);
//按照用户要求输入一二维数组来表示迷宫
print(4);
for(i=0;
i<
m;
i++)
{
print
(2);
for(j=0;
j<
n;
j++)
{
scanf("
%d"
&
Maze[i][j]);
if(Maze[i][j]!
=0&
&
Maze[i][j]!
=1)
{
i=-1;
break;
}
}
if(i==-1)break;
if(i==-1)
print
(1);
printf("
请输入0或1!
fflush(stdin);
//清空缓存
InitMaze(Maze,m,n);
elseprint
(1);
2.标记此处不通
intmarkThree(positioncurpos,intmaze[N][N])//标记此处不通
maze[curpos.x][curpos.y]=3;
return1;
}
3.检查当前通道块是否可通
intjudgePass(positionseat,intmaze[N][N],intx,inty)//检查当前通道块是否可通
{
if(maze[seat.x][seat.y]==0&
seat.x<
x&
seat.x>
=0&
seat.y<
y&
seat.y>
=0)//若当前坐标的值为0且坐标位置合法
return1;
return0;
4.标记此处可通
intmarkTwo(positioncurpos,intmaze[N][N])
maze[curpos.x][curpos.y]=2;
5.转换至下一个位置
voidNextPos(position*curpos,inti)//转换至下一个位置
if(i==1)
curpos->
y++;
elseif(i==2)
x++;
elseif(i==3)
y--;
elseif(i==4)
x--;
6.输出迷宫
voidPrintMaze(intmaze[N][N],intm,intn)//输出迷宫
printf("
%d"
maze[i][j]);
print(3);
for(;
j>
0;
j--)
\b\b"
printf("
|\n"
7.输出迷宫
voidPrintMaze2(intmaze[N][N],intm,intn,LinkStack*stack)//输出迷宫
Node*p;
{
p=stack->
pData;
while(p->
next!
=NULL)p=p->
next;
if((i==stack->
pData->
ele.seat.x&
j==stack->
ele.seat.y)||(i==p->
j==p->
ele.seat.y))
printf("
%c"
20);
else
if(maze[i][j]==0)
1);
if(maze[i][j]==1)
{
2);
}
if(maze[i][j]==2)
p=stack->
while(p->
=NULL&
(p->
ele.seat.x!
=i||p->
ele.seat.y!
=j))
{
p=p->
}
if(p->
ele.direction==1)
printf("
26);
ele.direction==2)
25);
ele.direction==3)
27);
ele.direction==4)
24);
if(maze[i][j]==3)
4);
}
}
8.求解迷宫的一条路径
intMazePath(intmaze[N][N],positionstart,positionend,LinkStack*stack,intn1,intn2)//求解迷宫maze中,从入口Start到出口end的一条路径
DataTypee;
intcurstep;
position*curpos;
curpos=(position*)malloc(sizeof(position));
initStack(stack);
//初始化stack
curpos->
x=start.x;
y=start.y;
curstep=1;
//探索第一步
if(judgePass(*curpos,maze,n1,n2)==0)
起始位置不可通过!
markThree(*curpos,maze);
return0;
if(judgePass(*curpos,maze,n1,n2)==1)//当前位置可通
markTwo(*curpos,maze);
//标记该点可通过
e.number=curstep;
e.seat.x=curpos->
x;
e.seat.y=curpos->
y;
e.direction=1;
Push(stack,e);
//加入路径,入栈
if(curpos->
x==end.x&
y==end.y)//到达出口位置
return1;
NextPos(curpos,1);
//探索下一步
curstep++;
else//若当前位置不能通过
if(IsEmpty(stack))
e=Pop(stack);
while(e.direction==4)
markThree(e.seat,maze);
//留下不能通过的标记,并退回一步
e=Pop(stack);
if(e.direction<
4)//换下一个方向探索
e.direction++;
Push(stack,e);
NextPos(&
e.seat,e.direction);
//设当前位置是该新方向上的相邻块,1代表向右,2代表向下,3代表向左,4代表向上。
x=e.seat.x;
curpos->
y=e.seat.y;
}while(IsEmpty(stack));
四、结果分析
4.1进入演示程序后,显示用户界面为:
4.2选择1创建迷宫后界面显示:
4.3输入迷宫后显示
4.7显示每一步的坐标和方向
五、总结
此次课程设计极大地提高了我们的实际操作能力,同时也让我们对算法的意义有了更深刻的理解,一个好的算法能够极大地提高程序的工作效率,同时也能够更快更好地达到预期目的。
在程序中,我们运用了链栈和深度优先搜索的知识,这也帮助我们对数据结构的知识进行了复习。
本程序的核心算法是求解迷宫路径的算法,在调试的过程总,通过对该算法的完善,我们也学到了很多,特别是对漏洞的查找和修补,这是整个工作中最难的部分,需要细致的调试和耐心的纠错。
由于使用了链栈,对我们对指针的运用能力也造成了极大的考验。
为了使程序尽量简洁,我们参照课本上的链栈模块进行修改,同时为了减少程序的运算次数,我们尽量的是程序可视化界面简洁化,减少花哨的成分。
本程序借鉴了一个C++程序的一些思想,在借鉴的过程中,我们也了解到一些C++与C这两种语言的区别,比如C语言与C++相比,结构体不能直接互相赋值,元素的定义必须写在赋值、判断、循环语句之前等。
虽然过程并不轻松,但在我们的团结协作下,我们完成了这次课程设计,我们不只学到了,也培养了合作意识,这也是一大收获!
通过这次课程设计,我在多方面有所提高。
1、编译工具VisualC++
很多程序在结构上是独立的,但是本次设计的程序功能不是零散的,我所应用的调试工具是VisualC++,可以充分利用Windows的支持剪切板和英文的特点。
2、巩固和温习了C语言
在界面设置中使用函数调用while。
其中文本显示颜色和背景颜色都可以任意按照自己的喜好,任意改变,同时在制作显示菜单的窗口,大小根据菜单条数设计。
最后采用printf输出程序设计界面。
这次的程序软件基本上运行成功,可以简单的建立链式循环链表,并进行输出,及循环语句的运用和选择语句的控制
六、课程设计心得体会
通过此次课程设计,使我更加扎实的掌握了有关栈方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。
实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。
过而能改,善莫大焉。
在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。
最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。
这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。
在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!
课程设计诚然是一门专业课,给我很多专业知识以及专业技能上的提升,同时又是一门讲道课,一门辩思课,给了我许多道,给了我很多思,给了我莫大的空间。
同时,设计让我感触很深。
使我对抽象的理论有了具体的认识。
通过这次课程设计,我掌握了栈的结构特点及有关概念;
理解了顺序栈的存储结构;
初步掌握了顺序栈的基本操作算法。
我认为,在这学期的实验中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。
更重要的是,在实验课上,我们学会了很多学习的方法。
而这是日后最实用的,真的是受益匪浅。
要面对社会的挑战,只有不断的学习、实践,再学习、再实践。
这对于我们的将来也有很大的帮助。
以后,不管有多苦,我想我们都能变苦为乐,找寻有趣的事情,发现其中珍贵的事情。
就像中国提倡的艰苦奋斗一样,我们都可以在实验结束之后变的更加成熟,会面对需要面对的事情。
回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
在设计的过程中遇到问题,可以说得是困难重重,但可喜的是最终都得到了解决。
实验过程中,也对团队精神的进行了考察,让我们在合作起来更加默契,在成功后一起体会喜悦的心情。
果然是团结就是力量,只有互相之间默契融洽的配合才能换来最终完美的结果。
参考文献
[1]曲朝阳,郭晓利,王晓慧,孙鸿飞.数据结构.中国电力出版社,2007
源程序
#include<
stdio.h>
stdlib.h>
windows.h>
conio.h>
#defineN100
#defineOK0
intMAX_SIZE=100;
//宏定义,使程序更直观
intMaze[N][N];
//迷宫存放在一个数字型数组中
typedefstructDataType
intnumber;
//通道块在路径上的序号
positionseat;
//通道块在迷宫中坐标位置
intdirection;
//从此通道块走向下一通道块的方向
}DataType;
//栈数据元素的类型
typedefstructNode//定义结构体变量表示顺序栈
DataTypeele;
//ele为结构体类型的元素
structNode*next;
}Node;
typedefstructLinkStack
Node*pData;
//指向栈的指针
inttop;
//记录栈的结点个数
}LinkStack;
voidprint(intx)
if(x==0)
|~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~|\n"
if(x==1)
|-----------------------------------------------------------------------|\n"
if(x==2)
|"
if(x==3)
"
if(x==4)
||\n"
voidinitStack(LinkStack*L)//链栈的初始化
L->
pData=NULL;
top=-1;
intIsEmpty(LinkStack*L)//判断是否为空函数,0为空,1为非空
if(!
L->
pData)
returnL->
top>
voiddestroyStack(LinkStack*L)//链栈的销毁:
销毁之后L->
ele=NULL,而L则没有变化
Node*p,*q;
//输入必须保证L是可用的链栈,否则应做相应的判断
IsEmpty(L))
return;
q=L->
//判断栈是否存在
while(q!
=NULL)
p=q;
q=q->
free(p);
//释放顺序栈占用的空间
L=NULL;
//返回值表示操作成功
free(L);
intcountStack(LinkStack*L)//求栈中元素个数
top;
voidPush(LinkStack*L,DataTypedata)//入栈操作
Node*m=(Node*)malloc(sizeof(Node));
//通过malloc函数分配空间
if(NULL==m)
空间分配失败!
m->
ele.number=data.number;
//将data中的数据复制
ele.seat.x=data.seat.x;
ele.seat.y=data.seat.y;
ele.direction=data.direction;
next=NULL;
if(NULL==L->
pData)//如果刚开始栈为空执行以下语句
L->
pData=m;
top++;
else
{
m->
next=L->
//注意此处如果栈为空,L->
top自加两次
DataTypePop(LinkStack*L)//出栈操作函数
DataTypem;
//定义结构体类型的指针m
//定义结构体类型的指针p
桟是空的!
m.number=L->
ele.number;
m.seat.x=L->
ele.seat.x;
m.seat.y=L->
ele.seat.y;
m.direction=L->
ele.direction;
p=L->
pData=L->
free(p);
//释放p所指的空间
top--;
returnm;
Node*StackTraverse(Node*pData)//用递归输出栈中的每个元素
if(pData->
next==NULL)
<
第%d步:
坐标为(%d,%d),方向为%d>
pData->
ele.number,pData->
ele.seat.x+1,pData->
ele.seat.y+1,pData->
ele.d