数据结构课程设计 迷宫问题.docx
- 文档编号:12378241
- 上传时间:2023-04-18
- 格式:DOCX
- 页数:26
- 大小:225.05KB
数据结构课程设计 迷宫问题.docx
《数据结构课程设计 迷宫问题.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计 迷宫问题.docx(26页珍藏版)》请在冰豆网上搜索。
数据结构课程设计迷宫问题
课程设计(论文)任务书
软件学院软件工程+电子商务2009专业2班
一、课程设计(论文)题目迷宫问题
二、课程设计(论文)工作自2010年12月27日起至2011年1月2日止
三、课程设计(论文)地点:
创新大楼实训中心
四、课程设计(论文)内容要求:
1.本课程设计的目的
(1)巩固和加深对数据结构基本知识的理解,提高综合运用课程知识的能力。
(2)使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软
件设计的能力。
(3)使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设
计的基本能力。
2.课程设计的任务及要求
1)基本要求:
(1)对系统进行功能模块分析、控制模块分析;
(2)系统设计要能完成题目所要求的功能;
(3)编程简练,可用,尽可能的使系统的功能更加完善和全面;
(4)说明书、流程图要清楚;
(5)提高学生的论文写作能力;
(6)特别要求自己独立完成;
2)创新要求:
在基本要求达到后,可进行创新设计,如改善算法性能、友好的人机界面。
3)课程设计论文编写要求
(1)要按照书稿的规格打印与写课程设计论文
(2)论文包括目录、正文、小结、参考文献、附录等
(3)课程设计论文装订按学校的统一要求完成
4)课程设计进度安排
内容天数地点
构思及收集资料1图书馆
编码与调试3实验室
撰写论文1图书馆、实验室
学生签名:
20011年1月3日
课程设计(论文)评审意见
(1)基本算法(20分):
优( )、良( )、中( )、一般( )、差( );
(2)设计分析 (20分):
优( )、良( )、中( )、一般( )、差( );
(3)调试分析 (20分):
优( )、良( )、中( )、一般( )、差( );
(4)论文内容 (20分):
优( )、良( )、中( )、一般( )、差( );
(5)答辩分析 (20分):
优( )、良( )、中( )、一般( )、差( );
(6)格式规范性及考勤是否降等级:
是()、否( )
评阅人:
职称:
讲师
2011年1月4日
目录
一、需求分析1
二、概要设计2
三、详细设计5
四、调试分析及测试15
五、个人工作及创新18
六、小结19
参考文献20
一、需求分析
1.选题理由
本次课设我选择了迷宫问题,迷宫求解是数据结构课程的一个经典问题,
迷宫问题要求寻找一条从入口到出口的路径。
通常用的是“穷举求解”的方法。
为了保证在任何位置上都能原路退回,显然需要用一个后进先出的结构来保存从入口到当前位置的路径。
因此,在求解迷宫通路的算法中要应用“栈”的思想。
对于栈的内容在整个学期的学习中我也有了一定的了解,所以选择了迷宫这一经典问题作为本次课设的内容。
2.基本原理分析
迷宫问题通常是用“穷举求解”方法解决,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前走;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。
假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。
栈是一个后进先出的结构,可以用来保存从入口到当前位置的路径。
以二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。
为处理方便起见,在迷宫的四周加一圈障碍。
对于迷宫任何一个位置,均约定东、南、西、北四个方向可通。
3.功能要求
(1)以一个二维数组Maze[m+2][n+2]表示迷宫,其中:
Maze[0][j]和Maze[m+1][j](0<=j<=n+1)及Maze[i][0]和Maze[i][n+1](0<=i<=m+1)为做外层的一圈障碍。
数组中以0表示通路,1表示障碍,限定迷宫的大小为:
m,n<=10。
(2)用户需用文件的形式输入迷宫的数据:
文件中第一行的数据为迷宫的行数m和列数n;从第2行至第m+1行(每行n个数)为迷宫值,用0,1输入,同行中的两个数字之间用空白字符相隔。
(3)迷宫的入口位置和出口位置可由用户随时设定。
(4)若设定的迷宫存在通路,则以长方阵形式将迷宫及其通路输出到标准输出文件上,其中字符“#”表示障碍,“*”表示路径,“@”表示曾途经该位置但不能到达出口,其余位置用空格符表示。
若设定迷宫不存在通路则报告相应信息
(5)本程序只求出一条成功的通路。
(6)程序执行的命令为:
1,创建迷宫;2,求解迷宫;3,输出迷宫的解。
二、概要设计
1、数据结构及其抽象数据类型的定义。
(1)栈的抽象数据类型
ADTStack{
数据对象:
D={ai|ai∈CharSet,i=1,2…n,n>=0}
数据关系:
R1={
基本操作:
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返回栈顶元素。
Push(&S,e)
初始条件:
栈S已存在。
操作结果:
在栈S的栈顶插入新的栈顶元素e。
Pop(&S,&e)
初始条件:
栈S已存在。
操作结果:
删除S的栈顶元素,并以e返回其值。
StackTraverse(S,visit())
初始条件:
栈S已存在。
操作结果:
从栈底到栈顶依次对S中的每个元素调用函数visit()。
}ADTStack
(2)迷宫的抽象数据类型
ADTmaze{
数据对象:
D={ai,j|ai,j∈{'','#','@','*'},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表示障碍。
操作结果:
构成迷宫的字符型数组,以空白字符表示通路,以字符‘#’表示障碍,并在迷宫四周加上一圈障碍。
MazePath(&M)
初始条件:
迷宫M已被赋值。
操作结果:
若迷宫M中存在一条通路,则按以下规定改变迷宫M的状态:
以字符’*’表示路径上的位置,字符‘@’表示“死胡同”,否则迷宫的状态不变。
PrintMaze(M)
初始条件:
迷宫M已存在。
操作结果:
以字符形式输出迷宫。
}ADTmaze
2、整体框架
本程序包含三个模块
(1)栈模块——实现栈抽象数据类型
(2)迷宫模块——实现迷宫抽象数据类型
(3)主程序模块:
voidmian()
{
初始化;
Do{
接受命令;
处理命令;
}while(命令!
=“退出”);
}
各模块之间的调用关系如图一:
图一:
调用关系图
函数的调用关系图反映了程序的层次结构如图二:
图二:
函数的调用关系图
三、详细设计
源程序:
#include
#include
#include
#defineMAXLEN10//迷宫包括外墙最大行列数目
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
typedefintStatus;
//坐标位置类型
typedefstruct{
intr,c;
}PosType;//迷宫中r行c列的位置
//迷宫类型
typedefstruct{
intr;
intc;
chararr[MAXLEN][MAXLEN];//可取'','*','@','#'
}MazeType;
typedefstruct{
//intstep;//当前位置在路径上的“序号”
PosTypeseat;//当前的坐标位置
intdi;//往下一坐标位置的方向
}SElemType;
//结点类型
typedefstructNodeType{
SElemTypedata;
NodeType*next;
}NodeType,*LinkType;
//栈类型
typedefstruct{
LinkTypetop;
intstacksize;
}SqStack;
PosTypestart;
PosTypeend;
MazeTypemaze;
boolfound;
//创建栈
StatusInitStack(SqStack&S)
{
S.top=(LinkType)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)returnOK;
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);
}//一个一个删除
if(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;
}
//选择下一步的方向
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[curpos.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][col+1]='1';
}
for(i=0;i<=maze.r+2;i++){
for(intj=0;j if(a[i][j]=='1')maze.arr[i][j]='#'; elsemaze.arr[i][j]=''; } } } //求迷宫路径的伪码算法: StatusMazePath(MazeType&maze,PosTypestart,PosTypeend) { //求解迷宫maze中,从入口start到出口end的一条路径,若存在,返回TRUE,否则返回FALSE PosTypecurpos; SqStackS; SElemTypee; 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;//如果到达终点返回true else{ curpos=NextPos(curpos,1);//下一位置是当前位置的东邻 } } 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); 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! ! ! "); printf("\n************************************************"); printf("\n*创建迷宫--c执行迷宫--m 输出迷宫--p 退出--q*"); printf("\n************************************************"); printf("\n\n 操作: -"); } //读入操作命令符,显示提示信息 voidReadCommand(char&cmd) { do{ if(cmd=='c') { printf("\n******************************************"); printf("\n*选择操作: 执行迷宫--m *"); printf("\n*退出--: q *"); printf("\n******************************************"); printf("\n\n 操作: -"); } elseif(cmd=='m'){ printf("\n******************************************"); printf("\n*选择操作: 输出迷宫--p *"); printf("\n* 退出--: q *"); printf("\n******************************************"); 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'||cmd=='q')); } //解释cmd--具体执行 voidInterpre(charcmd) { switch(cmd){ 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; } while(! 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; } case'm': { printf("\n请输入迷宫入口的坐标,以空格为间隔: --"); scanf("%d%d",&start.r,&start.c); printf("\n请输入迷宫出口的坐标,以空格为间隔: --"); scanf("%d%d",&end.r,&end.c); MazePath(maze,start,end); break; } case'p': { if(found) { printf("\n求解迷宫的结果如下--\n"); PrintMaze(maze); } elseprintf("\n找不到路径! \n"); } } } voidmain() { charcmd; Initialization(); do{ ReadCommand(cmd); //读入一个操作符命令 Interpre(cmd); //解释执行命令操作符 }while(cmd! ='q'); } 四、调试分析及测试 1、调试分析: (1)本程序有一个核心算法,即求迷宫的路径,在调试的时候,出现了两个问题: 没有想到要用‘@’记号,导致迷宫走不出来;没有设置‘found’,不知何时跳出。 (2)原本栈的元素e中除了di—往下一坐标位置的方向和seat—当前的坐标位置,还有一个step—当前位置在路径上的序号,后来发现step没什么用
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构课程设计 迷宫问题 数据结构 课程设计 迷宫 问题