|
|
|
|
# 迷宫生成器
|
|
|
|
|
|
|
|
|
|
张桐桐,李玉璇,孟婷玉,周羽凡
|
|
|
|
|
|
|
|
|
|
**摘要**:设计一个程序随机生成指定大小的迷宫。一个迷宫是由 $M \times N$ 个方格组成的矩形区域,每个方格的四周可能存在墙,相邻的两个方格之间如果没有墙的阻隔则可以通行,否则无法通行。要求系统运行正常、功能完整;数据结构使用得当,算法有较高的效率;代码规范、可读性高,结构清晰;具备一定的健壮性、可靠性和可维护性。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
任务分工及完成情况。
|
|
|
|
|
每个成员的工作量(百分比):
|
|
|
|
|
|
|
|
|
|
| 张桐桐 | 李玉璇 | 周羽凡 |孟婷玉|
|
|
|
|
|
| ---- | ---- | ---- |----|
|
|
|
|
|
| 30 | 30 | 20 | 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 1. 系统分析
|
|
|
|
|
|
|
|
|
|
## 1.1 问题描述
|
|
|
|
|
|
|
|
|
|
综合运用线性表、栈和队列、图、查找和排序等数据结构知识,设计一个程
|
|
|
|
|
序能够随机构造指定大小的迷宫,掌握和提高分析、设计、实现及测试程序
|
|
|
|
|
的综合能力。
|
|
|
|
|
要求
|
|
|
|
|
设计一个程序随机生成指定大小的迷宫。一个迷宫是由 m*n 个方格组
|
|
|
|
|
成的矩形区域,每个方格的四周可能存在墙,相邻的两个方格之间如果没有
|
|
|
|
|
墙的阻隔则可以通行,否则无法通行。
|
|
|
|
|
(1)指定迷宫的大小为 m 行 n 列,随机生成迷宫。
|
|
|
|
|
(2)任意两个方格之间都存在通路。
|
|
|
|
|
(3)在不重复通过的情况下,任意两个方格之间有且只有一条通路。
|
|
|
|
|
(4)用文本文件保存迷宫,包括迷宫的大小和每一个被敲掉的墙。
|
|
|
|
|
(5)尝试以图形窗口或文本方式显示迷宫。
|
|
|
|
|
要求系统运行正常、功能完整;数据结构使用得当,算法有较高的效率;代
|
|
|
|
|
码规范、可读性高,结构清晰;具备一定的健壮性、可靠性和可维护性。
|
|
|
|
|
|
|
|
|
|
## 1.2 可行性分析
|
|
|
|
|
|
|
|
|
|
如果让所有存在通路的单元格组成一个集合,则构造迷宫可以看作是不断打破不同集合之间的墙,直至合并成一个集合的过程。迷宫的初始状态包含所
|
|
|
|
|
有的墙,每个单元格属于一个独立的集合。随机敲掉两个集合之间的一个墙使两者相通,同时令两个集合合并成一个集合。不断重复,直到所有单元格
|
|
|
|
|
都属于一个联通单元格的集合
|
|
|
|
|
对于迷宫,我们一般是用一个二元的数组来存储迷宫中的单元,不同符号表示墙和可以通过的路径。我们的目的是在这个迷宫中找到一条从起点到终点的全部是可通过路径的单元组。
|
|
|
|
|
从起点出发,向其四周探索,如果是可通过单元且没有访问过,则将其入栈并标记为已访问单元,并继续探索其它方向,如果其四周没有未访问的可通过单元,则说明该点为死点,我们就将其出栈。如果碰到终点,则停止探索,同时回溯栈中的点,把栈中的路径中的单元标记出来。
|
|
|
|
|
|
|
|
|
|
## 1.3 需求分析
|
|
|
|
|
|
|
|
|
|
(1)输入一个任意大小的迷宫数据,用非递归的方法求出一条走出迷宫的路径,并将路径输出;
|
|
|
|
|
输入行和列的长度,来设置迷宫的大小;
|
|
|
|
|
(2)对迷宫,用栈来进行处理,栈是后进先出的线性数据结构,当每走一格时,就对上一格的坐标和向下一格要走的方向进行记录并规定每当遇到死路,即四个方向的“通路成立判断”都不成立时,从栈中取出栈顶元素,就这样到当前坐标值等于终点坐标值时,及循环停止时,栈中的所有元素自下而上就是对路径的全部描述。
|
|
|
|
|
(3)读取输入的迷宫长度(m*n),对迷宫进行搜索路径,找到最短的路径
|
|
|
|
|
(4)迷宫地图的大小和迷宫的入口位置
|
|
|
|
|
(5)合并功能,能够使用户更方便的查看搜索结果,将多个数据合并成一个能够进行更高效的操作。
|
|
|
|
|
(6)递归功能,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
|
|
|
|
|
|
|
|
|
|
# 2. 系统设计
|
|
|
|
|
|
|
|
|
|
## 2.1 概要设计
|
|
|
|
|
|
|
|
|
|
系统划分为几个模块,可以画模块图。
|
|
|
|
|
|
|
|
|
|
逐个说明每个模块的功能(输入、输出、做什么,这里不写怎么做)。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.2 数据结构设计
|
|
|
|
|
|
|
|
|
|
首先,分析对比几种可选的数据结构设计方案。如图可以采用邻接矩阵,也可以采用邻接表,表示集合可以用普通的查找表,还可以用不相交集。给出每一种设计方案的特点(优势、不足等)。然后,综合考虑各种因素(空间、时间、乃至团队成员的水平等),给出你的选择。
|
|
|
|
|
|
|
|
|
|
### (1)xxx结构
|
|
|
|
|
|
|
|
|
|
给出核心数据结构的设计,包括文字描述和示意图。讲清楚数据是如何组织的。多个数据结构,逐一列出。
|
|
|
|
|
|
|
|
|
|
### (2)xxx结构
|
|
|
|
|
|
|
|
|
|
给出核心数据结构的设计,包括文字描述和示意图。讲清楚数据是如何组织的。
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
|
|
## 2.3 算法设计
|
|
|
|
|
|
|
|
|
|
首先,分析对比几种可选的算法设计方案。如是否排序,广度优先或深度优先搜索等。给出每一种设计方案的特点(优势、不足)。然后,综合考虑各种因素(空间、时间、乃至团队成员的水平等),给出你的选择。
|
|
|
|
|
|
|
|
|
|
### (1)XXX算法
|
|
|
|
|
|
|
|
|
|
给出核心算法的设计,包括伪代码或流程图。多个核心算法,逐一列出。只列举解决问题的核心算法,重点讲清楚是如何解决问题的。
|
|
|
|
|
|
|
|
|
|
### (2)XXX算法
|
|
|
|
|
|
|
|
|
|
给出核心算法的设计,包括伪代码或流程图。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 3. 系统实现
|
|
|
|
|
|
|
|
|
|
说明所使用的语言、开发工具等。
|
|
|
|
|
|
|
|
|
|
介绍项目的文件结构,以及主要函数的功能。
|
|
|
|
|
|
|
|
|
|
## 3.1 核心数据结构的实现
|
|
|
|
|
|
|
|
|
|
描述数据结构的实现方法。
|
|
|
|
|
|
|
|
|
|
可以配合程序代码加以说明。如:
|
|
|
|
|
|
|
|
|
|
int maze[M][N],row,col;
|
|
|
|
|
typedef struct 栈操作函数
|
|
|
|
|
void Init_hand_Maze(int maze[M][N],int m,int n)
|
|
|
|
|
{int i,j;
|
|
|
|
|
for(i=1;i<=m+1;i++)
|
|
|
|
|
for(j=1;j<=n+1;j++)
|
|
|
|
|
{maze[i][j]=1;
|
|
|
|
|
}
|
|
|
|
|
cout<<" 请按行输入迷宫, 0表示通路, 1 表示障碍:"<<endl; for(i=1;i<m+1;i++)
|
|
|
|
|
for(j=1.j<n+1;j++)
|
|
|
|
|
cin>>maze[i][j];
|
|
|
|
|
for(i=1;i<m+1;i++){
|
|
|
|
|
for(j=1:j<n+1;j++)
|
|
|
|
|
{
|
|
|
|
|
if(maze[i][j]!=0&&maze[i][j]!=1)(
|
|
|
|
|
cout<<” 您输入有误,请重新输入";
|
|
|
|
|
Init_hand_Maze(maze,m,n);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
时间复杂度 O(m*n)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Init_automatic_Maze(int maze[M][N],int m,int n) 求解迷宫
|
|
|
|
|
Status MazePath(Stack &S,MazeType &e,int maze[M][N], int m, int n)
|
|
|
|
|
{
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if(maze[][]==0) 打印路径
|
|
|
|
|
int PrintPath(Stack S,int maze[M][N],int row,int col)
|
|
|
|
|
{
|
|
|
|
|
if==
|
|
|
|
|
cout<<"\n===============================================\n";
|
|
|
|
|
cout<<" 此迷宫无解 \n\n";
|
|
|
|
|
return ERROR;
|
|
|
|
|
}
|
|
|
|
|
MazeType e; while!=
|
|
|
|
|
{Pop(S,e); maze[][]=+10);}
|
|
|
|
|
cout<<"\n===============================================\n";
|
|
|
|
|
cout<<" 路径为 :"<<endl;
|
|
|
|
|
int i,j:
|
|
|
|
|
for(i=1;i<row+1;i++)
|
|
|
|
|
{
|
|
|
|
|
for(j=1;j<col+1:j++)
|
|
|
|
|
{
|
|
|
|
|
switch(maze[i][j])
|
|
|
|
|
{
|
|
|
|
|
case 0:
|
|
|
|
|
cout<<" 口";
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
cout<<" ■";
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
cout<<"※”;
|
|
|
|
|
break;
|
|
|
|
|
case 10:
|
|
|
|
|
cout<<" →";
|
|
|
|
|
break;
|
|
|
|
|
case 11:
|
|
|
|
|
cout<<" ↓";
|
|
|
|
|
break;
|
|
|
|
|
case 12:
|
|
|
|
|
cout<<" ←";
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
cout<<" ↑";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cout<<endl;
|
|
|
|
|
}
|
|
|
|
|
cout<<" 完成!"<<endl;
|
|
|
|
|
return OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 3.2 核心算法的实现
|
|
|
|
|
|
|
|
|
|
描述算法的实现方法。
|
|
|
|
|
|
|
|
|
|
可以配合程序代码加以说明。如:
|
|
|
|
|
|
|
|
|
|
主函数
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
switch(i)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
Init_hand_Maze(maze,m,n);
|
|
|
|
|
PrintMaze(maze,m,n);
|
|
|
|
|
InitStack(S);
|
|
|
|
|
MazePath(S,start,maze,,;
|
|
|
|
|
PrintPath(S,maze,m,n);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
Init_automatic_Maze(maze,m,n);
|
|
|
|
|
PrintMaze(maze,m,n);
|
|
|
|
|
initStack(S):
|
|
|
|
|
MazePath(S,start,maze,,;
|
|
|
|
|
PrintPath(S,maze,m,n);
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
cycle=(-1);break;
|
|
|
|
|
default:
|
|
|
|
|
cout<<"\n";cout<<" 你的输入有误!\n”;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对该算法的时间和空间复杂度进行分析。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 4. 系统测试
|
|
|
|
|
|
|
|
|
|
描述测试的思路和方法。比如,先用小数据量进行测试,再用真实数据进行测试。
|
|
|
|
|
|
|
|
|
|
测试应考虑到输入数据的特殊情况。
|
|
|
|
|
输入 1 1 构不成迷宫
|
|
|
|
|
输入 1000 1000 构不成迷宫
|
|
|
|
|
|
|
|
|
|
给出若干测试用例,包括输入、预期结果、运行结果或是否通过测试。运行结果和预期结果一致,为通过测试。
|
|
|
|
|
测试 输入 10 8
|
|
|
|
|
100 10
|
|
|
|
|
150 15
|
|
|
|
|
均成功构成迷宫
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 5. 总结
|
|
|
|
|
|
|
|
|
|
概况项目和完成情况。
|
|
|
|
|
|
|
|
|
|
遇到的问题和解决方法。
|
|
|
|
|
|
|
|
|
|
个人小结:
|
|
|
|
|
|
|
|
|
|
张桐桐:完成迷宫这个项目,首先需要了解输入和输出,目标明确才可以进行下一步,其中运用到不相交集的知识,需要去自己学习,给我触发很大,计算机行业发展迅速,就算将来进行工作也离不开学习新的知识,所以在大学培养自我学习是非常重要的。没有什么是可以不劳而获的,只有贫穷可以。任务分为代码和文档两个部分,如何合理的分工,让每个人都有自己的任务,是非常重要的事情。这次的项目和之前的项目有所不同,没有可以参考的,只有自己去思考去尝试,将所学的知识合理的应用在恰当的部分。学以致用,才符合项目的目的。
|
|
|
|
|
|
|
|
|
|
成员2:
|
|
|
|
|
|
|
|
|
|
成员3:
|
|
|
|
|
|
|
|
|
|
成员4:
|
|
|
|
|
|
|
|
|
|
成员5:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 参考文献
|
|
|
|
|
|
|
|
|
|
列出参考的文献资料,根据情况自行添加。
|
|
|
|
|
|
|
|
|
|
[1] 严蔚敏, 吴伟民. 数据结构(C语言版). 北京: 清华大学出版社, 2007.
|
|
|
|
|
|