1、目 录第一章: 设计问题描述与分析.11.1. 课程设计内容11.2. 问题分析11.3功能实现.21.4运行环境.3第二章: 算法设计与流程图.42.1.主函数的流程图.42.2.概要设计.52.4 详细设计.62.4.1. 节点类型和指针类型.62.4.2. 迷宫的操作6(1)生成迷宫.6(2)打印迷宫矩阵与字符图形7(3)迷宫求解路由求解操作7(4)打印迷宫通路坐标8(5)输出迷宫通路的字符图形.82.4.3. 主函数9第三章:调试分析.10程序设计综合课程设计第四章:使用说明11第五章:测试结果12附录 1.19附录 2.19程序设计综合课程设计1第一章:设计问题描述与分析1.1.课程
2、设计内容:该系统是由 C 语言编写的生成一个 NM(N 行 M 列)的迷宫,完成迷宫的组织和存储,并实现迷宫路由算法。基本要求 1、 N 和 M 是用户可配置的,缺省值为 50和 50。2、迷宫的入口和出口分别在左上角和右下角。提示:(1)可以使用二维数组 mazeM+2N+2表示迷宫,其中 M,N 为迷宫的行、列数,当元素值为 0 时表示该点是通路,当元素值为 1 时表示该点是墙。老鼠在每一点都有 4 种方向可以走,可以用数组 move4来表示每一个方向上的横纵坐标的偏移量,可用另一个二维数组 markM+2N+2记录节点的访问情况。(2)可以选用深度优先算法或广度优先算法实行,迷宫可由自动
3、或手动生成。测试用例应该包含有解迷宫和无解迷宫。1.2. 问题分析本程序要求实现迷宫问题的相关操作,包括迷宫的组织和存储,并实现迷宫路由算法(即查找迷宫路径) 。程序所能达到的:具体包括迷宫的建立,迷宫的存储(迷宫由自动生成或手动生成) ,迷宫中路径的查找迷宫是一个矩形区域,迷宫存在一个入口和一个出口,其内部包含了不能穿越的墙或者障碍。迷宫的建立即是建立这样一个迷宫矩阵,用于存储迷宫信息,包括可穿越的路和不可穿越的墙或者障碍,分别用 0 表示通路,1 表示障碍。对于迷宫矩阵,用 mn 的矩阵来描述,m 和 n 分别代表迷宫的行数和列数。这样,则迷宫中的每个位置都可以用其行号和列号来指定。从入口
4、到出口的路径是由一组位置构成的。每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的上、下、左、右的邻居。为了描述迷宫中位置(i ,j)处有无障碍,规定,当位置(i ,j )处有一个障程序设计综合课程设计2碍时,其值为 1,否则为 0.这样迷宫就可以用 0、1 矩阵来描述,在构造矩阵时,为了操作方便会将矩阵四周置为 1(不通) 。对于查找迷宫路由问题首先,考察,迷宫的入口位置,如果该位置就是迷宫出口,则已经找到了一条路径,搜索工作结束。否则,考察其上、下、左、右位置上的邻居是否是障碍,若不是就移动到这个相邻位置上,然后对于这个位置开始搜索通往出口的路径。如果不成功,就选择另一个相邻的
5、位置,并从它开始搜索路径。为防止搜索出现重复,则将已搜索过的位置标记为 1。同时为保留过搜索的痕迹,在考察相邻位置之前,将当前位置保存在一个堆栈中,如果所有相邻的非障碍位置均被搜索过,且未能找到通往出口的路径,则表明不存在从入口到出口的路径。且对于此,实现的是深度优先遍历算法,如果查找到路径,则为从入口到出口的路径。下面实现如何利用堆栈实行深度优先遍历算法进行迷宫最短路径的查找。以矩阵 1 1 1 1 1 1 11 0 0 1 0 1 11 1 0 0 1 0 11 1 0 0 0 1 11 0 0 1 0 0 11 1 1 1 1 1 1首先,将位置(1,1)放入堆栈中,从它开始搜索,标记。
6、由于其只有一个非障碍位置,所以接下来移动到(1,2) ,防止稍后的搜索再经过这个位置。从(1,2)移动到(2,2) ,放入堆栈中, (2,2)存在(2,3) 、 (3,2)两个可移动位置。标记已被搜索过,对于每一个非障碍位置,它的相邻非障碍节点均入队列,实现了深度优先遍历算法。所以如果存在路径,则从出口处节点的位置,逆序则可程序设计综合课程设计3以找到其从出口到入口的通路。实现了查找路径。1.3功能实现:1、数据输入形式和输入值的范围:生成迷宫时可选择手动或者自动生成;手动输入迷宫矩阵时以 0 表示无障碍为通路,1 表示该点有障碍为墙。所有输入中,元素的值均为整数。2、结果的输出形式:当完成迷
7、宫生成后,会提示输入入口与出口,进入迷宫路由查找算法,如找到出口,则打印出路径矩阵坐标,并显示显示迷宫生成图形3、测试数据:a、进入界面,选择 2,自动生成b、输入入口与出口c、查看结果1.4运行环境:运行环境为 DOS程序设计综合课程设计4第二章:算法设计与流程图2.1.主函数的流程图:N判断入口是否为通路 循环结束,无通路程序设计综合课程设计5YNNYY YYNYNY将该位置入栈,并标记为 1栈不为空且栈顶非出口栈顶位置下面可通?栈顶位置上面可通?栈顶位置右面可通?栈顶为出口?找出通路,链栈内即为通路循环结束程序设计综合课程设计6NN图 1 迷宫算法流程图 2.2 概要设计 1、为了实现上
8、述功能,需要:构造一个二维数组 mazeM+2N+2用于存储迷宫矩阵,构造一个二维数组 backupM+2N+2用于备份迷宫矩阵;自动或手动生成迷宫,即为二维数组 mazeM+2N+2赋值并备份;将构造一个堆栈用于存储迷宫路由;建立迷宫节点 struct Mlink,用于存储迷宫中每个访问过的节点。实现迷宫路由算法,用深度优先遍历实现查找迷宫路径。如找到路径则显示路径,否则提示无通路。同时显示生成迷宫。在屏幕上显示操作菜单。2、本程序包含 6 个函数:( 1 )主函数 main( )( 2 )生成迷宫函数 create( )( 3 )打印迷宫矩阵与图形函数 prin( )栈顶位置左面可通?栈顶
9、出栈程序设计综合课程设计7( 4 )寻找迷宫路由 Mazepath( )( 5 )输出迷宫通路坐标 printonglu1( )( 6 )输出迷宫生成图形 printonglu2( )各函数之间的关系如下图(图 2)所示:函数关系图:create( ) prin( )main() Mazepath( )printonglu1( )printonglu2( )图 2 各函数间关系图程序设计综合课程设计82.3 详细设计实现概要设计中定义的所有数据类型,对各个操作给出伪代码算法。对于主程序和各个模块也给出相应的伪代码算法。1.节点类型和指针类型迷宫矩阵类型:Mlink *stack; 全局变量堆栈
10、,存储迷宫通路int abcM+2N+2 辅助数组int mazeM+2N+2; 迷宫矩阵int backupM+2N+2; 备份矩阵,便于操作,定义为全局变量 迷宫中节点类型及队列类型:struct Mlink int row ,col ; struct node * next; Mlink;2.迷宫的操作(1)生成迷宫void create(int mazeN+2)定义变量 i,j,flag;srand( (unsigned)time( NULL ) ) 以时间产生随机种子利用 for 初始化迷宫矩阵与备份矩阵,包括边界全置为 1利用 for 将迷宫置为 0选择迷宫生成方式 1 为手动生成
11、,2 为自动生成,输入值并赋给 flag程序设计综合课程设计9flag=1以 i , j 控制迷宫中行列数的循环输入以 0 表示通路,以 1 表示障碍,给 mazeij赋值,不包括边界。循环结束,完成迷宫生成flag=2定义变量 i1,j1 用以接收随机值以 i , j 控制迷宫中行列数的循环赋值操作以 0 表示通路,以 1 表示障碍用 for(c=1;cnext(5)输出迷宫通路的字符图形void printonglu2()此函数根据堆栈内栈顶与“次栈顶”的位置关系决定输出字符,或,其中 2=,3=,4=,5=所有的操作都是在备份矩阵 backup上。出口位置输出int i,z,j;Mlin
12、k *p=stack;p 不空if(p-rowp-next-row) backupp-next-rowp-next-col=5; 下一位置在下程序设计综合课程设计12else if(p-rownext-row) backupp-next-rowp-next-col=2;下一位置在上else if(p-colp-next-col) backupp-next-rowp-next-col=4;下一位置在右else ;下一位置在左利用 for 循环,i,j 为循环控制变量输出备份矩阵 backup为 0 是输出“”为 1 是输出“”为 2 是输出“”为 3 是输出“”为 4 是输出“”为 5 是输出“
13、”为 6 是输出“”另外在输出语句上,与矩阵输出相同,标明了行号与列号(该功能为王教授所要求而后加的) 3.主函数void menu()定义迷宫数组矩阵 mazeM+2N+2定义辅助数组 abcM+2N+2 以用来在可以在第一次产生迷宫中重复选择入口与出口程序设计综合课程设计13定义变量 k 以用来控制循环 定义整型变量 x1,y1 ,用于存储入口。定义整型变量 x2,y2 ,用于存储出口。定义整型变量 x 用于接收 mazepash 的返回值。输入入口与出口。如果 x=1 则条用函数printonglu1();printonglu2();否则提示无通路。界面开始会显示:1,手动建立2,自动建
14、立按提示操作,输入入口与出口,回车即会看到结果第三章:调试分析在调试过程中,开始用堆栈实现了路径的查找并调试成功,但输出的结果仅仅只是路径坐标,看起来不形象,于是想到了用字符来表示图形并标出通路,虽然不程序设计综合课程设计14是太完美,但比之之前好好多了在实现这一算法过程,注意将访问过的节点进行标记,并且在遍历过程中对矩阵数组是“破坏性”遍历,在算法完成后,矩阵已被破坏,堆栈中会存用路径,为了再原矩阵中用字符图形表示出通路,在建立矩阵后会迷宫矩阵备份一下,当然或许会有更好的处理方法。程序设计综合课程设计15第四章:使用说明程序名为迷宫.exe,运行环境为 DOS,程序执行后显示:建立迷宫矩阵(
15、选择 1 或者 2):1,手动建立2,自动建立进请输入您的选择:在输入选择后输入数字选择执行不同的迷宫建立。按要求输入入口与出口程序设计综合课程设计16第五章:测试结果程序设计综合课程设计171.主页面图 3 主页面程序设计综合课程设计182.选择自动建立图 4 迷宫自动生成中程序设计综合课程设计193,自动生成迷宫,上面为数组矩阵,其中 0 可通,1 障碍。下面为字符图形,其中白色可通,黑色障碍程序设计综合课程设计20图 5 打印出的迷宫矩阵与迷宫图形程序设计综合课程设计214,根据提示输入入口与出口图 6 输入入口与出口程序设计综合课程设计225,回车后输出路径程序设计综合课程设计23图
16、7 打印出的迷宫路径程序设计综合课程设计246,输入一个非“0”继续图 8 输入非“0”继续走该迷宫程序设计综合课程设计257,输入入口与出口,无通路程序设计综合课程设计26图 9 无通路程序设计综合课程设计27附录 1:附录 2:源代码:#include#include#include#include#define M 20#define N 20typedef struct node/堆栈结构int row; /行int col; /列struct node * next;Mlink;Mlink *stack;/定义一个栈int backupM+2N+2; /备份数组程序设计综合课程设计28/*建立迷宫矩阵*/void create(int mazeN+2)/建立迷宫int i,j,flag;srand( (unsigned)time( NULL ) ); /以时间产生随机种子for(i=0;i=M+1;i+)for(j=0;j=N+1;j+)mazeij=1;/将四周置为 1for(i=1;i=M;i+)for(j=1;j=N;j+)mazeij=0;/初始化矩阵backupij=0;/初始化备份矩阵printf(“建立迷宫矩阵(选择 1 或者 2):n1,手动建立n2,自动建立n请输入您的选择:n“);scanf(“%d“,if(flag=1)/手动建立迷宫