数据结构迷宫问题课程设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构课程设计报告
设计题目:迷宫问题数据结构课程设计_
班级:计科152
学号:********
*名:***
南京农业大学计算机系
数据结构课程设计报告内容
一.课程设计题目
迷宫问题
以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
要求:首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出。
其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
二.算法设计思想
1.需求分析
(1)迷宫数据用一个二维数组int maze[row][col]来存储,在定义了迷宫的行列数后,用两个for循环来录入迷宫数据,并在迷宫周围加墙壁。
(2)迷宫的入口位置和出口位置可以由用户自己决定。
2.概要设计
(1)主程序模块:
void main()
{
int maze[row][col];
struct mark start,end; //出入口的坐标
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
//方向,依次是东西南北
built_maze(maze);
printf("请输入入口的横纵坐标:");
scanf("%d,%d",&start.a,&start.b);
printf("请输入出口的横纵坐标:");
scanf("%d,%d",&end.a,&end.b);
printf("0为东,1为南,2为西,3为北,-1为出路\n");
maze_path(maze,dir,start,end);
getchar();
}
(2)栈模块——实现栈抽象数据类型
(3)迷宫模块——实现迷宫抽象数据类型,建立迷宫,找出迷宫的一条通路
3.详细设计
(1)坐标位置类型
struct mark{
int a,b; //迷宫a行b列为位置
};
(2)迷宫类型
void built_maze(int maze[row][col])
//按照用户输入的row行和col列的二维数组(元素值为0和1)
//设置迷宫maze的初值,包括边上边缘一圈的值
void maze_path(int maze[row][col],int dir[4][2],struct mark start,struct mark end)
//求解迷宫maze中,从入口start到出口end的一条路径,
//若存在,则返回TRUE;否则返回FALSE
(3)栈类型
struct element{
int i,j,d; //坐标与方向
};
typedef struct Linkstack{
element elem;
struct Linkstack *next;
}*SLinkstack;
4.求迷宫路径为伪码算法
void maze_path(int maze[row][col],int dir[4][2],struct mark start,struct mark end)
{
int i,j,d;
int x,y;
element elem,E;
SLinkstack L1,L2;
initstack(L1);
initstack(L2);
maze[start.a][start.b]=2;
elem.i=start.a;
elem.j=start.b;
elem.d=-1; //d=-1表示无方向
push_stack(L1,elem);
while(!stack_empty(L1))
{
pop(L1,elem);
i=elem.i;
j=elem.j;
d=elem.d+1; //下一个方向
while(d<4) //探索东西南北各个方向
{
x=i+dir[d][0];
y=j+dir[d][1];
if(x==end.a&&y==end.b&&maze[x][y]==0) //这里表示已经到了出口
{
elem.i=i;
elem.j=j;
elem.d=d;
push_stack(L1,elem);
elem.i=x;
elem.j=y;
elem.d=-1;
push_stack(L1,elem);
while(L1) //逆置序列,输出迷宫路径
{
pop(L1,E);
push_stack(L2,E);
}
while(L2)
{
pop(L2,E);
printf("%3d%3d%3d\n",E.i,E.j,E.d);
}
return;
}
if(maze[x][y]==0)
{
maze[x][y]=2; //标记走过这个点
elem.i=i;
elem.j=j;
elem.d=d;
push_stack(L1,elem);
i=x;
j=y;
d=-1;
}
d++;
}
}
printf("此迷宫无出路");
}
5.主函数和其他函数的伪码算法
void main()
{
int maze[row][col];
struct mark start,end; //出入口的坐标
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
built_maze(maze); //方向,依次是东西南北
printf("请输入入口的横纵坐标:");
scanf("%d,%d",&start.a,&start.b);
printf("请输入出口的横纵坐标:");
scanf("%d,%d",&end.a,&end.b);
printf("0为东,1为南,2为西,3为北,-1为出路\n");
maze_path(maze,dir,start,end);
getchar();
}
三.程序结构
主程序
built_maze maze_path
initstack push_stack pop stack_empty
四.实验结果与分析
1.用户使用说明
(1)本程序的运行环境为debug运行环境,执行文件为:19215225.cpp;
(2)用VC++运行文件后出现以下窗口:
点击运行程序
(3)出现以下窗口后
输入迷宫的行列数,回车;再继续输入迷宫的数据,1表示障碍,0
表示通路;再输入入口坐标和出口坐标,回车。
就可以显示出迷宫路径。
2.测试结果
(1)输入行列数:5,5
输入迷宫数据为:0 0 0 1 1
1 1 0 1 1
0 0 0 1 0
0 1 1 0 0
0 0 0 0 0
出口位置:1,1
出口位置:5,5
(2)输入行列数:4,9
输入迷宫数据为:0 0 0 0 0 0 1 0 0
0 1 0 0 0 1 0 0 0
0 0 1 1 1 0 0 1 1
0 0 1 1 1 0 1 0 0
输入入口坐标:1,1
输入出口坐标:4,9
(3)输入行列数:9,8
输入迷宫数据为:0 0 1 0 0 0 1 0
0 0 1 0 0 0 1 0
0 0 0 0 1 1 0 1
0 1 1 1 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1
0 1 1 1 1 0 0 1
1 1 0 0 0 1 0 1 1 1 0 0 0 0 0 0 输入入口坐标:1,1
输入出口坐标:9,8
3.调试分析
(1)在刚开始写完代码后,运行发现程序只能运行简单的一条直线的迷宫,在运行复杂的迷宫时,不会碰到死路(周围没有可探索的道路)就删除坐标往回到前坐标换方向探索。
最后我和同寝室同学一起探讨才发现程序中探索过的坐标没有标记,后来我将maze[x][y]=2将它作为标记才解决问题。
(2)程序中主要的两个算法:initmaze和maze_path的时间复杂度为O(m*n),空间复杂度也为O(m*n)。
五.总结(收获与体会)
通过这段时间的课程设计,我对数据结构和C语言的理解更加深刻了。
在实践过程中我遇到了不少问题,但通过阅读相关书籍、求问老师同学,最终也解决了不少问题。
这些问题也给了我相当多的收获。
但通过这段时间的学习和解决的这么多问题,我觉得我对这些知识的掌握比以前好了许多。
求解迷宫问题用的是“穷举求解”的方法。
从入口出发,沿着某一方向探索(这里我选择优先探索的是东面),若无障碍,继续往前走,否则眼原路返回,换个方向继续探索,直到将所有可能的通道都探索完为止。
所以需要用栈来保存从入口到当前位置的路径。
但因为之前在学习栈这一节的时候没学扎实,现在有很多知识都忘了。
所以在编写求解迷宫路径的算法的时候我觉得有些困难,后来经过一步步分析和借鉴书上的穷举法才把算法写出来。
但我还是除了许多错误,其中大部分是语法错误,这些最后都还是一一解决了。
而且除了加深了栈的学习,我还复习了以前大一学的C语言中的二维数组和for,while循环。
这次课程设计不仅是让我们加深了解数据结构的理论知识,更重要的是培养我们解决实际问题的能力,能在不断地遇到问题,不断地解决问题的过程中培养自己的专业思维。
所以我相信通过这次课程设计我们能够提升自己的分析、设计程序和编写程序的能力。
六.源程序
#include<stdio.h>
#include<stdlib.h>
#define row 100
#define col 100
struct mark{
int a,b;
};
struct element{
int i,j,d; //坐标与方向
};
typedef struct Linkstack{
element elem;
struct Linkstack *next;
}*SLinkstack;
int initstack(SLinkstack &L)
{
L=NULL;
return 1;
}
int stack_empty(SLinkstack L)
{
if(L==NULL)
return 1;
else
return 0;
}
int push_stack(SLinkstack &L,element E)
{
SLinkstack P;
P=(SLinkstack)malloc(sizeof(Linkstack));
P->elem=E;
P->next=L;
L=P;
return 1;
}
int pop(SLinkstack &L,element &E)
{
SLinkstack P;
if(!stack_empty(L))
{
E=L->elem;
P=L;
L=L->next;
free(P);
return 1;
}
else
return 0;
}
void built_maze(int maze[row][col])//建立迷宫{
int x,y;
int m,n;
printf("请输入迷宫的行列数(用逗号隔开):");
scanf("%d,%d",&m,&n);
printf("请输入迷宫各行各列的数据(用空格隔开):\n");
for(x=0;x<m+2;x++)
{
for(y=0;y<n+2;y++)
{
if(x==0||x==m+1||y==0||y==n+1)//迷宫周围加墙壁
maze[x][y]=1;
else
scanf("%d",&maze[x][y]);
}
}
printf("迷宫生成中……\n");
printf("迷宫显示为:\n");
for(x=0;x<m+2;x++)
{
for(y=0;y<n+2;y++)
printf("%3d",maze[x][y]);
printf("\n");
}
}
void maze_path(int maze[row][col],int dir[4][2],struct mark start,struct mark end)
{
int i,j,d;
int x,y;
element elem,E;
SLinkstack L1,L2;
initstack(L1);
initstack(L2);
maze[start.a][start.b]=2; //标记起点坐标
elem.i=start.a;
elem.j=start.b;
elem.d=-1; //d=-1表示无方向
push_stack(L1,elem);
while(!stack_empty(L1))
{
pop(L1,elem);
i=elem.i;
j=elem.j;
d=elem.d+1; //下一个方向
while(d<4) //探索东西南北各个方向
{
x=i+dir[d][0];
y=j+dir[d][1];
if(x==end.a&&y==end.b&&maze[x][y]==0)
{//这里表示已经到了出口
elem.i=i;
elem.j=j;
elem.d=d;
push_stack(L1,elem);
elem.i=x;
elem.j=y;
elem.d=-1;
push_stack(L1,elem);
while(L1) //逆置序列,输出迷宫路径
{
pop(L1,E);
push_stack(L2,E);
}
while(L2)
{
pop(L2,E);
printf("(%d,%d,%d)\n",E.i,E.j,E.d);
}
return;
}
if(maze[x][y]==0)
{
maze[x][y]=2; //标记走过这个点
elem.i=i;
elem.j=j;
elem.d=d;
push_stack(L1,elem);
i=x;
j=y;
d=-1;
}
d++;
}
}
printf("此迷宫无出路");
}
void main()
{
int maze[row][col];
struct mark start,end; //出入口的坐标
int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}}; //方向,依次是东西南北
printf("************************************************** *********************************************\n");
printf("\t*************** 欢迎使用迷宫模拟程序***************\n");
printf("************************************************** *********************************************\n");
built_maze(maze);
printf("请输入入口的横纵坐标:");
scanf("%d,%d",&start.a,&start.b);
printf("请输入出口的横纵坐标:");
scanf("%d,%d",&end.a,&end.b);
printf("0为东,1为南,2为西,3为北,-1为出路\n");
maze_path(maze,dir,start,end);
printf("按任意键继续");
getchar();
}。