C++数据结构 迷宫问题



《C++数据结构 迷宫问题》由会员分享,可在线阅读,更多相关《C++数据结构 迷宫问题(23页珍藏版)》请在装配图网上搜索。
1、课程设计(论文)任务书 软件学院软件工程+电子商务2009专业2班 一、课程设计(论文)题目宫问题 二、课程设计(论文)工作自2010年12月27日起至2011年1月2日止 三、课程设计(论文)地点: 四、课程设计(论文)内容要求: 1本课程设计的目的 (1) 巩固和加深对数据结构基本知识的理解,提高综合运用课程知识的能力。 (2) 使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软—件设计的能力。 (3) 使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设「计的基本能力。 2•课程设计的任务及要求 1) 基本要求: (1) 对系统进行功能模块分
2、析、控制模块分析;- """(2)系统设计要能完成题目所要求的功能; (3) 编程简练,可用,尽可能的使系统的功能更加完善和全面; (4) 说明书、流程图要清楚; (5) 提高学生的论文写作能力;— (6) 特别要求自己独立完成; 2) 创新要求:— 在基本要求达到后,可进行创新设计,如改善算法性能、友好的人机界面。 3) 课程设计论文编写要求 ~~(1)要按照书稿的规格打印与写课程设计论文 """(2)论文包括目录、正文、小结、参考文献、附录等 """(3)课程设计论文装订按学校的统一要求完成 4)课程设计进度安却乍 内容 天数 地点 构思及收集资料 1
3、 图书馆 编码与调试 3 实验室 撰写论文 1 图书馆、实验室 学生签名: 20011年1月3日 课程设计(论文)评审意见 (1)基本算法 (20分): 优( )、良( )、中( )、一般( 、、差( ); (2)设计分析 (20分): 优( )、良( )、中( )、一般( 、、差( ); (3)调试分析 (20分): 优( )、良( )、中( )、一般( 、、差( ); (4)论文内容 (20分): 优( )、良( )、中( )、一般( 、、差( ); (5)答辩分析 (20分): 优( )、良(
4、 )、中( )、一般( 、、差( ); (6)格式规范性及考勤是否降等级:是()、否() 目录 一、需求分析1 二、概要设计2 三、详细设计5 四、调试分析及测试15 五、个人工作及创新18 六、小结19 参考文献20 数据结构课程设计 一、需求分析 1. 选题理由本次课设我选择了迷宫问题,迷宫求解是数据结构课程的一个经典问题,迷宫问题要求寻找一条从入口到出口的路径。通常用的是“穷举求解”的方法。为了保证在任何位置上都能原路退回,显然需要用一个后进先出的结构来保存从入口到当前位置的路径。因此,在求解迷宫通路的算法中要应用“栈”的思想。对于栈的内容在整个学期的
5、学习中我也有了一定的了解,所以选择了迷宫这一经典问题作为本次课设的内容。 2. 基本原理分析迷宫问题通常是用“穷举求解”方法解决,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前走;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。栈是一个后进先出的结构,可以用来保存从入口到当前位置的路径。 以二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。为处理方便起见,在迷宫的四周加一圈障碍。对于迷宫任何一个位置,均约定东、南、西、北四个方向可通。 3. 功能要求 (1)以
6、一个二维数组Maze[m+2][n+2]表示迷宫,其中:Maze[O]j]和Maze[m+1][j](0<=j<=n+1)及Maze[i][O]和Maze[i][n+1](0<=i<=m+1)为做外层的一圈障碍。数组中以0表示通路,1表示障碍,限定迷宫的大小为:m,n<=10。 (2)用户需用文件的形式输入迷宫的数据:文件中第一行的数据为迷宫的行数m和列数n;从第2行至第m+1行(每行n个数)为迷宫值,用0,1输入,同行中的两个数字之间用空白字符相隔。 (3)迷宫的入口位置和出口位置可由用户随时设定。 (4)若设定的迷宫存在通路,则以长方阵形式将迷宫及其通路输出到标准输出文件上,其中字符
7、“#”表示障碍,“*”表示路径,“@”表示曾途经该位置但不能到达出口,其余位置用空格符表示。若设定迷宫不存在通路则报告相应信息
(5)本程序只求出一条成功的通路。
(6)程序执行的命令为:1,创建迷宫;2,求解迷宫;3,输出迷宫的
解。
二、概要设计
1、数据结构及其抽象数据类型的定义。(1)栈的抽象数据类型
ADTStack{
数据对象:D={ai|ai^CharSet,i=l,2・・・n,n>=0}数据关系:R1={
8、件:栈S已存在。操作结果:销毁栈S。 ClearStack(&S)初始条件:栈S已存在。操作结果:将S清为空栈。 StackLength(S)初始条件:栈S已存在。操作结果:返回栈S的长度。 StackEmpty(S) 初始条件:栈S已存在。 操作结果:若S为空栈,则返回TRUE,否则返回FALSE。GetTop(S,&e)初始条件:栈S已存在。 操作结果:若栈S不空,则以e返回栈顶元素。 Push(&S,e)初始条件:栈S已存在。操作结果:在栈S的栈顶插入新的栈顶元素e。 Pop(&S,&e)初始条件:栈S已存在。操作结果:删除S的栈顶元素,并以e返回其值。 StackTr
9、averse(S,visit())初始条件:栈S已存在。 操作结果:从栈底到栈顶依次对S中的每个元素调用函数visit()。}ADTStack 2)迷宫的抽象数据类型 ADTmaze{ 数据对象:D={ai,j|ai,je{','#','@','*'},0<=i<=m+1,0<=j<=n+1,m,n<=10} 数据关系:R={ROW,COL} 基本操作: InitMaze(&M,a,row,col) 初始条件:二维数组a[row+2][col+2]已存在,其中自第1行至第row+1行,每行中自第1列至第col+1列的元素已有值,并且以值0表示通路,以值1表示障碍。 操作结果:
10、构成迷宫的字符型数组,以空白字符表示通路,以字符‘#'表示障碍,并在迷宫四周加上一圈障碍。 MazePath(&M) 初始条件:迷宫M已被赋值。 操作结果:若迷宫M中存在一条通路,则按以下规定改变迷宫M的状态:以字符'*'表示路径上的位置,字符‘@'表示“死胡同”,否则迷宫的状态不变。 PrintMaze(M) 初始条件:迷宫M已存在。操作结果:以字符形式输出迷宫。 }ADTmaze 2、整体框架本程序包含三个模块 (1)栈模块——实现栈抽象数据类型 (2)迷宫模块——实现迷宫抽象数据类型 (3)主程序模块:voidmian() {初始化; Do{ 接受命令;处理命令
11、;
}while(命令!二“退出”);
}
各模块之间的调用关系如图一:
主程序模快
迷宫權块
栈模块
图一:调用关系图
函数的调用关系图反映了程序的层次结构如图二:
RcaflCemmatidInterpret
MazcPiitlL
PrintMaE^
19
StackTraverse
lnitStackPishPop^tackEmpty
FflfttPrintMarkPrintPassNf*itPn>;Same
图二:函数的调用关系图
三、详细设计
源程序:
#include 12、h>
#include 13、
PosTypeseat;//当前的坐标位置intdi;//往下一坐标位置的方向}SElemType;
//结点类型
typedefstructNodeType{SElemTypedata;NodeType*next;
}NodeType,*LinkType;
//栈类型
typedefstruct{
LinkTypetop;intstacksize;
}SqStack;
PosTypestart;
PosTypeend;
MazeTypemaze;
boolfound;
//创建栈
StatusInitStack(SqStack&S)
{S.top=(LinkTy 14、pe)malloc(sizeof(NodeType));S.top->next=NULL;
S.stacksize=0;returnOK;
}
//进栈
StatusPush(SqStack&S,SElemType&e)
{
LinkTypep;p=(NodeType*)malloc(sizeof(NodeType));p->data=e;
p->next=S.top;
S.top=p;
S.stacksize++;returnOK;
}
//判断是否为栈空
StatusStackEmpty(SqStackS)
{
if(S.top->next==NULL)retu 15、rnOK;returnERROR;
}
//出栈
StatusPop(SqStack&S,SElemType&e){
LinkTypep;if(StackEmpty(S))returnERROR;
p=S.top;e=p->data;
S.top=S.top->next;
S.stacksize--;free(p);
returnOK;
}
//销毁栈
StatusDestroyStack(SqStack&S){
LinkTypep;while(S.top!=NULL)
{
p=S.top;S.top=S.top->next;
free(p);}//一个一个删除i 16、f(S.top==NULL)returnOK;elsereturnERROR;
}
//曾走过但不是通路标记并返回OK
StatusMarkPrint(MazeType&maze,PosTypecurpos){
maze.arr[curpos.r][curpos.c]='@';//"@"表示曾走过但不通returnOK;
}
//曾走过而且是通路标记并返回OK
StatusFootPrint(MazeType&maze,PosTypecurpos)
{maze.arr[curpos.r][curpos.c]二'*';//"*"表示可通returnOK;
}
//选择下一步的 17、方向
PosTypeNextPos(PosType&curpos,inti){
PosTypecpos;
cpos=curpos;
switch(i){//1.2.3.4分别表示东,南,西,北方向
case1:cpos.c+=1;
break;
case2:cpos.r+=1;
break;
case3:cpos.c-=1;
break;
case4:cpos.r-=1;
break;
}
returncpos;
}
//判断当前位置是否可通
StatusPass(MazeType&maze,PosTypecurpos)
{if(maze.arr[curpo 18、s.r][curpos.c]=='')returnTRUE;
elsereturnFALSE;
}
//创建迷宫
//按照用户输入的二维数组(0或1),设置迷宫maze的初值,包括加上边缘一圈的值
voidInitMaze(MazeType&maze,chara[MAXLEN][MAXLEN],introw,intcol)
{
maze.r=row;
maze.c=col;
for(inti=0;i<=col+1;i++){
a[0][i]='1';a[row+1][i]='1';
}
for(i=0;i<=row+1;i++){
a[i][0]='1';a[i][c 19、ol+1]='1';
}
for(i=0;i<=maze.r+2;i++){
for(intj=0;j 20、e;
InitStack(S);
curpos二start;//设定“当前位置"为“入口位置"
//curstep=1;//探索第一步
found=false;
do{
if(Pass(maze,curpos))
{
//当前位置可以通过,即是未曾走到过的通道块留下足迹
FootPrint(maze,curpos);//做可以通过的标识
//e.step=curstep;e.seat=curpos;
e.di=1;//为栈顶元素赋值
Push(S,e);//加入路径if(curpos.r二二end.r&&curpos.c二二end.c)found二true;//如口果到 21、达终点返回true
else{
curpos二NextPos(curpos,l);//下一位置是当前位置的东邻
}}
else//当前位置不能通过if(!StackEmpty(S)){
Pop(S,e);while(e.di==4&&!StackEmpty(S)){MarkPrint(maze,e.seat);//留下不能通
过的标记
Pop(S,e);
}
if(e.di<4){e.di++;//换下个方向Push(S,e);
//curpos=NextPos(e.seat,e.di);//进行
探索
}}
}while(!StackEmpty(S)&&!found 22、);DestroyStack(S);
returnfound;
}
//将标记路径信息的迷宫(字符型方阵)输出到终端(包括外墙)
voidPrintMaze(MazeType&maze)
{
for(inti=0;i<=maze.r+2;i++){
for(intj=0;j<=maze.c+2;j++){
printf(“%c",maze.arr[i][j]);//输出迷
宫
}printf("\n");
}
}
//系统初始化
voidInitialization()
{
system("cls");
printf("welcometothegame");
23、
printf("\n************************************************");printf("\n*创建迷宫一c执行迷宫一m输出迷宫--p退出一q*");printf("\n************************************************");printf("\n\n操作:-");
}
//读入操作命令符,显示提示信息
voidReadCommand(char&cmd)
{
do{
if(cmd=='c')
{printf("\n************************************* 24、*****");printf("\n*选择操作:执行迷宫--m*");
printf("\n*退出--:q*");
printf("\n******************************************");printf("\n\n操作:-");
}
elseif(cmd=='m'){printf("\n******************************************");printf("\n*选择操作:输出迷宫--p*");
printf("\n*退出--:q*");
printf("\n*************************** 25、***************");
printf("\n\n操作:-");
}
elseif(cmd=='p'){printf("\n******************************************");printf("\n*选择操作:执行迷宫--c*");
printf("\n*退出--:q*");
printf("\n******************************************");printf("\n\n操作:-");
}
cmd=getchar();
}while(!(cmd=='c'||cmd=='m'||cmd=='p' 26、||cmd=='q'));
}
//解释cmd--具体执行
voidInterpre(charcmd)
{
switch(cmd){
,,f
case'c':{
intrnum,cnum,i=0,m=1,n=1;
chara2[MAXLEN][MAXLEN];
charinput[1];
chardata[1000];
printf("\n请输入迷宫数据文件名!\n");scanf("%s",input);
FILE*fp;
fp=fopen(input,"r");
if(!fp)
{
printf("\n不能打开文件\n");
break;
}
whi 27、le(!feof(fp))
{
fscanf(fp,"%s",&data[i]);
if(i==0)
{
rnum=(int)data[i]-(int)'0';
}
if(i==1)
{cnum=(int)data[i]-(int)'0';
}
if(i>=2)
{if(n>cnum){m++;n=1;}a2[m][n]=data[i];
n++;
}
i++;
}fclose(fp);
InitMaze(maze,a2,rnum,cnum);
printf("\n迷宫建立完成!!\n");
break;
}
,,f
case'm':{
printf 28、("\n请输入迷宫入口的坐标,以空格为间隔:--");scanf("%d%d",&start.r,&start.c);
printf("\n请输入迷宫出口的坐标,以空格为间隔:--");scanf("%d%d",&end.r,&end.c);
MazePath(maze,start,end);
break;
}
,,f
case'p':{
if(found)
{
printf("\n求解迷宫的结果如下--\n");
PrintMaze(maze);
}
elseprintf("\n找不到路径!\n");
}
voidmain()
{
charcmd;Initia 29、lization();
do{
//读入一个操作符命令
//解释执行命令操作符
ReadCommand(cmd);
Interpre(cmd);
}while(cmd!='q');
}
调试分析及测试
1、调试分析:
(1) 本程序有一个核心算法,即求迷宫的路径,在调试的时候,出现了两个问题:没有想到要用'@'记号,导致迷宫走不出来;没有设置'found',不知何时跳出。
(2) 原本栈的元素e中除了di—往下一坐标位置的方向和seat—当前的坐标位置,还有一个step—当前位置在路径上的序号,后来发现step没什么用,就删掉了。
(3) 函数ReadCommand中, 30、cmd=getchar();的位置找不准,最后是试出来的。
(4) 调试的时候多次出现,没有错误,但是dos环境下就是执行不起来,所以采用了一些输出变量,判断到底是哪里出了问题。
(5) 本程序中三个主要的算法:InitMaze,MazePath和MarkPrint的时间复杂度均为O(m*n),本程序的空间复杂度也为O(m*n)(栈所占最大空间)
2、使用说明和运行结果:
(1)首先以文件形式输入迷宫数据,如图三:
[12-记事本丨回
文1中E探辑E13式卫)樂也耳和(HJ
EF
ULU1U
0C110
-LUL-
1)11C0
:1n1n
31、
[划F
J
图三
(2)进入演示程序后,会出现以下界面如图四:
图四
(3) 进入“创建迷宫”的命令后,即提示输入迷宫数据的文件名,结束符为“回车符”,该命令执行之后输出“迷宫建立完成”,且输出下面可执行的操作。如图五:
图五
(4) 进入“执行迷宫”的命令后,即提示输入迷宫入口,出口的坐标,结束符为“回车符”,该命令执行之后表示迷宫路径已寻找完成或未找到路径。请注意:若迷宫中存在路径,执行此命令后,迷宫状态已经改变,若要重复执行此命令,需重新输入迷宫数据。如图六:
图六
(5) 进入“输出迷宫”的命令后,即输出迷宫求出路径之后的状态。'#' 32、表示障碍,'@'表示曾走过但不通,'*'表示路径。如图七:
图七
(6) 进入“退出”的命令后,按任意键结束。如图八:
图八
3、缺点与改进:
(1) 在定义函数Mazepath的时候,开始的循环语句的结束条件不对,没有出路时,导致一直出现了不正确的结果,最后没有新位置入栈,则返回上一个位置,否则没有路径。
(2) 只是以文件形式输入迷宫,如果迷宫数据量大时,要先建好文件还是很浪费时间,如果以随机产生函数自动产生迷宫会更好。
五、个人工作及创新
为了准备这次课程设计我查找了很多的资料,对于迷宫问题的求解中迷宫的产生方式有很多的不同,有的是直接输入迷宫,有的是用文 33、件输入,有的是随机函数产生,我的课设是参考了用文件输入的方法,这样做相比直接输入迷宫操作要更简单。当然用随机函数产生迷宫比如用:
for(i=0;i 34、用了一番也使有了更加清楚的认识。
在求解迷宫的算法中,先设定当前位置的初值为入口位置,然后
Do{
若当前位置可通,
则{将当前位置插入栈顶;
若该位置是出口位置,则结束;否则切换当前位置的东邻方块为新的当前位置;
}
否则{
若栈不为空且栈顶位置尚有其它方向未被探索,则设定新的当前位置为延顺时针方向旋转找到的栈顶位置的下一相邻块;
若栈不空但栈顶位置四周均不通,
则{删去栈顶位置;
若栈不为空,则重新测试新的栈顶位置,
直至找到一个可通的相邻块或出栈至栈空;}
}
}
求解迷宫的算法大概就是这么个思路。
六、小结
要能很好的掌握编程,仅仅通过几个简单的程序的 35、编写是无法达成的,更需要的是大量的积累和深入研究才可能。在程序的编写中也不能一味的向已有的程序进行模仿,而要自己去探索,去寻找最好的解决方法,只有带着问题去反复实践,才能更熟练的掌握和运用,当然,对现有的程序也要多去接触,因为有些程序是我们在短时间内无法想出来的,我们也应该去参考别人的作品,这样可以节约时间获得更多的知识。最重要的是持之以恒,要经常性的复习原来接触到的程序,这样才能保证我们有足够的经验去面对程序问题。
参考文献
[1] .严蔚敏,吴伟民数据结构(C语言版)•清华大学出版社.2007
[2] .严蔚敏,数据结构题集(C语言版)•清华大学出版社.2007
[3] .谭浩强,C程序设计(第四版)•清华大学出版社.2007
- 温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。