迷宫问题.docx
- 文档编号:30467285
- 上传时间:2023-08-15
- 格式:DOCX
- 页数:24
- 大小:143.25KB
迷宫问题.docx
《迷宫问题.docx》由会员分享,可在线阅读,更多相关《迷宫问题.docx(24页珍藏版)》请在冰豆网上搜索。
迷宫问题
西安郵電大學
数据结构课程设计报告
题目:
迷宫问题
院系名称:
专业名称:
班级:
学生姓名:
学号(8位):
指导教师:
设计起止时间:
1.设计目的
本次课程设计的主要目的是综合运用所学的数据结构知识,使用一种自己擅长的语言,解决问题,侧重对栈、哈夫曼树等相关内容的综合应用,使同学们能进一步熟悉掌握使用各种数据结构的实现,进一步提升自己分析问题的能力、培养编程能力、锻炼编程思维,进而不断提高同学们解决问题的能力,并为以后解决实际问题打下良好的基础。
二.设计内容
1.程序设计的环境为VisualC++,使用的语言为C语言。
2.设计了几种结构体:
迷宫(包括大小、出入口的坐标);点信息(包括点坐标、方向标记);链栈(包括点信息、下一点信息)。
3.使用的数据结构类型是链栈。
主要部分为非递归形式。
4.采用界面选择的方式使用程序。
5.创建用户自定义的迷宫:
用户在系统的限制和提示下进行迷宫的创建。
6.读取已有的迷宫信息:
与程序存放在同一目录下的in1.txt(有解)in2.txt(无解)。
7.写文件:
将用户创建好的迷宫信息放入文件in.txt中;将程序运行所得到的迷宫的解法信息存放在文件out.txt中。
8.求迷宫出路:
根据当前点的点信息方向标记的值,判断下一步的走向。
9.栈的基本操作:
栈的初始化、判空、出栈、入栈、取栈顶。
10.显示迷宫:
显示创建的迷宫或迷宫的出路。
11.为使界面美观,还使用了清屏函数。
三.概要设计
1.功能模块图;
对系统进行分析,给出系统结构图。
整个系统除了主函数外,另外还有12个函数,实现七项功能:
栈的初始化、判空、出栈、入栈、取栈顶等功能,创建迷宫功能,读取文件功能,找迷宫出路功能,写文件功能,显示功能,菜单界面。
其基本功能模块如下图所示:
2.各个模块详细的功能描述。
(1).主函数main()
调用开始界面函数,通过主菜单的选项进入创建或读取迷宫功能;
进入找迷宫出路函数;
进入退出界面。
(2).开始界面Menu()
选择下列功能:
创建迷宫、直接读取已有的迷宫、退出。
(3).创建迷宫CreeateMaze()
依次让用户输入迷宫的大小、各行的状态(0表示可走,1表示障碍)、入口的坐标、出口的坐标。
根据该信息生成迷宫。
并显示,存入文件in.txt中。
(4).读取文件ReadFile()
将文件中的迷宫信息以int类型读取
(5).找出路FindWay()
根据点信息中的方向标记的值来判断下一步:
a.当flag=0时,尝试向当前坐标的右边走;
b.当flag=1时,尝试向当前坐标的下边走;
c.当flag=2时,尝试向当前坐标的左边走;
d.当flag=3时,尝试向当前坐标的上边走;
e.当flag=4时,说明当前点四面不通,出栈;
(6).栈的初始化InitStack()
(7).栈的判空IsEmpty()
(8).取栈顶GetTop()
(9).出栈Pop()
出栈的同时,让当前点所对应的迷宫点的状态回归为“可走”。
(10).入栈Push()
入栈的同时,让当前点所对应的迷宫点的状态变成“路径”。
(11).写文件WriteFile()
按照迷宫的形式(矩形)来存储个点信息,存储类型为int。
(12).退出界面Quit()
四.详细设计
1.功能函数的调用关系图
2.各功能函数的数据流程图
找迷宫出路函数:
创建迷宫函数:
3.重点设计及编码
/*查找迷宫的出路*/
voidFindWay(MAZE*G)
{
STACK*stack;
POINTp;
stack=InitStack();
p.x=G->in_x;//将入口坐标入栈
p.y=G->in_y;
p.flag=0;
G=Push(stack,p,G);
do
{
switch(p.flag)
{
case0:
if(p.y+1>=0&&p.y+1
{
stack->next->road.flag++;
p.y=p.y+1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的右边走
break;
}
else
stack->next->road.flag++;
case1:
if(p.x+1>=0&&p.x+1
{
stack->next->road.flag++;
p.x=p.x+1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的下边走
break;
}
else
stack->next->road.flag++;
case2:
if(p.y-1>=0&&p.y-1
{
stack->next->road.flag++;
p.y=p.y-1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的左边走
break;
}
else
stack->next->road.flag++;
case3:
if(p.x-1>=0&&p.x-1
{
stack->next->road.flag++;
p.x=p.x-1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的上边走
break;
}
else
stack->next->road.flag++;
default:
G=Pop(stack,G);//当前坐标四方不通,出栈
if(!
IsEmpty(stack))
p=GetTop(*stack);
else
{
printf("\n该迷宫无解!
\n\n");
Quit();
}
}
if(p.x==G->out_x&&p.y==G->out_y)//判断是否找到出口
{
G=Push(stack,p,G);
break;
}
}while(!
IsEmpty(stack));
printf("\n迷宫的解法如下:
\n");
Show(G);
WriteFile(G,"out.txt");
free(stack);//销毁栈
}
五.测试数据及运行结果
1.正常测试数据和运行结果
创建迷宫及对其找路的结果:
提供的数据1(有解的迷宫)
提供的数据2(无解的迷宫)
2.异常测试数据及运行结果
开始界面输入错误选项,输入错误的文件名:
创建迷宫时出入口坐标有误:
六.调试情况,设计技巧及体会
1.改进方案
对自己设计进行评价,指出合理和不足之处,提出改进的方案。
通过第一周的编程,我完成了迷宫问题。
程序总体设计结构较合理,功能基本完善,界面友好清晰。
优点:
熟练的应用链栈这个数据结构的基本操作。
使程序可以更高效的运行,实现对迷宫的创建、读取、找路、写文件等基本功能。
也加深了自己对数据结构的认识。
缺点:
在某些方面存在着不足,比如,应考虑在迷宫存在多条通路的情况下,采取最优路径并显示出来的情况。
应考虑更多出错的情况,并给出更详细的、直观的错误提示。
再者,显示迷宫的方法可以转变为动态的,或更多的形式。
改进的方法:
增加结构体,使问题更具体详细。
增加出错语句的提示,使程序更人性化。
多使用环境下已有的函数,使程序更为简单。
2.体会
在为期两周的程序设计实习中,我受益颇多。
更进一步的了解和掌握了各种数据结构的操作。
熟练的使用数据结构以解决实际问题。
从中,我可以将书本知识应用于实践,为以后的计算机语言的学习打下了坚实的基础;同时,我分析问题的能力也在不断的提高,编程的能力也有显著的进步。
但在本次程序设计中,我学会的更多是坚持的精神和持之以恒的心态,哪怕报错的信息多到显示不完,也要静下心,认认真真一点一点地寻找错误的原因。
另外,我也学会了利用调试来查找出错点的方法,以及一些从未用过但是却功能特殊的函数。
同时真正意识到编写一个程序的不容易,以及多得考虑不完的问题,更是突显出团队合作的重要性。
七.参考文献
[1]耿国华.2008.《数据结构——C语言描述》.北京:
高等教育出版社
[2]王曙燕.2005.《C语言程序设计》.北京:
科学出版社
八.附录:
(可不要,不要打印源程序,只交电子版)
#include
#include
#include
#defineMAX_SIZE10//迷宫的最大规模
#defineTRUE1
#defineFALSE0
#definePASS0//通路
#defineWALL1//障碍
#defineIN2//入口
#defineOUT3//出口
#defineWAY4//路径
typedefstructPOINT
{
intx,y;//该点的坐标
intflag;//方向标记位
}POINT;
typedefstructMAZE
{
intmaze[MAX_SIZE][MAX_SIZE];//迷宫的各点的状态
intx,y;//迷宫的行、列数
intin_x,in_y;//迷宫入口坐标
intout_x,out_y;//迷宫出口坐标
}MAZE;
typedefstructSTACK
{
POINTroad;//存放路径信息
structSTACK*next;//下一个路径
}STACK;//链栈形式
intMeun(void);
MAZE*CreateMaze(void);
voidShow(MAZE*);
voidWriteFile(MAZE*,char*);
MAZE*ReadFile(char*);
voidQuit(void);
voidFindWay(MAZE*);
STACK*InitStack(void);
MAZE*Push(STACK*,POINT,MAZE*);
MAZE*Pop(STACK*,MAZE*);
intIsEmpty(STACK*);
POINTGetTop(STACK);
main()
{
MAZE*G;
intchoose;
charfname[10];
choose=Meun();
system("cls");
switch(choose)
{
case1:
G=CreateMaze();
break;
case2:
printf("\n请输入文件名:
");
scanf("%s",fname);
G=ReadFile(fname);
printf("文件中的迷宫如下:
\n");
Show(G);
printf("入口为:
(%d,%d)\n出口为:
(%d,%d)\n",G->in_x,G->in_y,G->out_x,G->out_y);
break;
case3:
Quit();
default:
printf("\n输入的选项有误!
\n");
exit(0);
}
printf("\n按任意键继续");
getch();
system("cls");
FindWay(G);
free(G);
printf("\n按任意键继续");
getch();
system("cls");
Quit();
}
//取栈顶
POINTGetTop(STACKs)
{
POINTq;
q.x=q.y=-1;
q.flag=0;
q=s.next->road;
returnq;
}
//判空
intIsEmpty(STACK*s)
{
if(s->next==NULL)
returnTRUE;
returnFALSE;
}
//出栈操作
MAZE*Pop(STACK*s,MAZE*G)
{
STACK*t;
t=s->next;//在出栈的同时让该点的状态回归PASS
s->next=t->next;
G->maze[t->road.x][t->road.y]=PASS;
free(t);
returnG;
}
//入栈操作
MAZE*Push(STACK*s,POINTp,MAZE*G)
{
STACK*t;
t=(STACK*)malloc(sizeof(STACK));
t->road=p;
t->next=s->next;//在入栈的同时让该点的状态变为WAY
s->next=t;
G->maze[p.x][p.y]=WAY;
returnG;
}
//栈的初始化
STACK*InitStack(void)
{
STACK*s;
s=(STACK*)malloc(sizeof(STACK));
s->next=NULL;
returns;
}
//找出路
voidFindWay(MAZE*G)
{
STACK*stack;
POINTp;
stack=InitStack();
p.x=G->in_x;//将入口坐标入栈
p.y=G->in_y;
p.flag=0;
G=Push(stack,p,G);
do
{
switch(p.flag)
{
case0:
if(p.y+1>=0&&p.y+1
{
stack->next->road.flag++;
p.y=p.y+1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的右边走
break;
}
else
stack->next->road.flag++;
case1:
if(p.x+1>=0&&p.x+1
{
stack->next->road.flag++;
p.x=p.x+1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的下边走
break;
}
else
stack->next->road.flag++;
case2:
if(p.y-1>=0&&p.y-1
{
stack->next->road.flag++;
p.y=p.y-1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的左边走
break;
}
else
stack->next->road.flag++;
case3:
if(p.x-1>=0&&p.x-1
{
stack->next->road.flag++;
p.x=p.x-1;
p.flag=0;
G=Push(stack,p,G);//尝试向当前坐标的上边走
break;
}
else
stack->next->road.flag++;
default:
G=Pop(stack,G);//当前坐标四方不通,出栈
if(!
IsEmpty(stack))
p=GetTop(*stack);
else
{
printf("\n该迷宫无解!
\n\n");
Quit();
}
}
if(p.x==G->out_x&&p.y==G->out_y)//判断是否找到出口
{
G=Push(stack,p,G);
break;
}
}while(!
IsEmpty(stack));
printf("\n迷宫的解法如下:
\n");
Show(G);
WriteFile(G,"out.txt");
free(stack);//销毁栈
}
voidQuit(void)
{
printf("\n\t---------------------------谢谢使用!
-------------------------------\n\n");
exit(0);
}
//读文件
MAZE*ReadFile(char*fname)
{
FILE*fp;
MAZE*G;
inti,j;
if((fp=fopen(fname,"rt"))==NULL)
{
printf("\n\n打开文件出错!
可能不存在这个文件!
\n\n");
exit(0);
}
G=(MAZE*)malloc(sizeof(MAZE));
G->x=9;//默认的迷宫大小
G->y=8;
for(i=0;i
for(j=0;j
{
fscanf(fp,"%d",&(G->maze[i][j]));
if(G->maze[i][j]==IN)
{
G->in_x=i;
G->in_y=j;
G->maze[G->in_x][G->in_y]=PASS;
}
if(G->maze[i][j]==OUT)
{
G->out_x=i;
G->out_y=j;
G->maze[G->out_x][G->out_y]=PASS;
}
}
fclose(fp);
printf("\n读取文件%s成功!
\n",fname);
returnG;
}
//写文件
voidWriteFile(MAZE*G,char*fname)
{
FILE*fp;
inti,j;
fp=fopen(fname,"wt");//写成迷宫形式
for(i=0;i
{
for(j=0;j
fprintf(fp,"%d",G->maze[i][j]);
fprintf(fp,"\n",G->maze[i][j]);
}
fclose(fp);
printf("\n数据已存入文件%s中。
\n\n",fname);
}
//显示迷宫
voidShow(MAZE*G)
{
inti,j;
for(i=0;i
{
printf("\t\t");
for(j=0;j
{
if(G->maze[i][j]==WAY)
printf("·");
elseif(G->maze[i][j]==WALL)
printf("■");
else
printf("□");
}
printf("\n");
}
printf("\n");
}
//创建新迷宫
MAZE*CreateMaze(void)
{
MAZE*G;
inti1,j1,i2,j2;
intgo=1;
G=(MAZE*)malloc(sizeof(MAZE));
printf("请输入迷宫的长度和宽度(不超过%d):
",MAX_SIZE);
scanf("%d%d",&(G->x),&(G->y));
printf("\n请输入迷宫的信息(0表示通路,1表示障碍,用空格隔开):
\n");
for(i1=0;i1
{
printf("第%d行:
\n",i1);
for(j1=0;j1
scanf("%d",&G->maze[i1][j1]);
}
printf("\n创建的迷宫如下:
\n");
Show(G);
while(go)
{
printf("\n请输入入口坐标(从0开始):
");
scanf("%d%d",&i1,&j1);
G->in_x=i1;
G->in_y=j1;
printf("请输入出口坐标(从0开始):
");
scanf("%d%d",&i2,&j2);
G->out_x=i2;
G->out_y=j2;
if(i1>=G->x||j1>=G->y||i2>=G->x||j2>=G->y)
printf("\n设置的出入口坐标有误!
请重新输入!
\n");
else
go=0;
}
WriteFile(G,"in.txt");
returnG;
}
intMeun(void)
{
intchoose;
printf("\n\t**********************************************************
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 迷宫 问题