目录第一章:设计问题描述与分析 (1)1.1.课程设计内容 (1)1.2. 问题分析 (1)1.3.功能实现 (2)1.4.运行环境 (3)第二章:算法设计与流程图 (4)2.1.主函数的流程图 (4)2.2.概要设计 (5)2.4详细设计 (6)2.4.1. 节点类型和指针类型 (6)2.4.2.迷宫的操作 (6)(1)生成迷宫 (6)(2)打印迷宫矩阵与字符图形 (7)(3)迷宫求解路由求解操作 (7)(4)打印迷宫通路坐标 (8)(5)输出迷宫通路的字符图形 (8)2.4.3. 主函数 (9)第三章:调试分析 (10)第四章:使用说明 (11)第五章:测试结果 (12)附录1 (19)附录2 (19)第一章:设计问题描述与分析1.1.课程设计内容:该系统是由C 语言编写的生成一个N×M(N行M列)的迷宫,完成迷宫的组织和存储,并实现迷宫路由算法。
基本要求1、 N和M是用户可配置的,缺省值为50和50。
2、迷宫的入口和出口分别在左上角和右下角。
提示:(1)可以使用二维数组maze[M+2][N+2]表示迷宫,其中M,N为迷宫的行、列数,当元素值为0时表示该点是通路,当元素值为1时表示该点是墙。
老鼠在每一点都有4种方向可以走,可以用数组move[4]来表示每一个方向上的横纵坐标的偏移量,可用另一个二维数组mark[M+2][N+2]记录节点的访问情况。
(2)可以选用深度优先算法或广度优先算法实行,迷宫可由自动或手动生成。
测试用例应该包含有解迷宫和无解迷宫。
1.2. 问题分析本程序要求实现迷宫问题的相关操作,包括迷宫的组织和存储,并实现迷宫路由算法(即查找迷宫路径)。
程序所能达到的:具体包括迷宫的建立,迷宫的存储(迷宫由自动生成或手动生成),迷宫中路径的查找迷宫是一个矩形区域,迷宫存在一个入口和一个出口,其内部包含了不能穿越的墙或者障碍。
迷宫的建立即是建立这样一个迷宫矩阵,用于存储迷宫信息,包括可穿越的路和不可穿越的墙或者障碍,分别用0表示通路,1表示障碍。
对于迷宫矩阵,用m×n的矩阵来描述,m和n分别代表迷宫的行数和列数。
这样,则迷宫中的每个位置都可以用其行号和列号来指定。
从入口到出口的路径是由一组位置构成的。
每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的上、下、左、右的邻居。
为了描述迷宫中位置(i ,j)处有无障碍,规定,当位置(i ,j)处有一个障碍时,其值为1,否则为0.这样迷宫就可以用0、1矩阵来描述,在构造矩阵时,为了操作方便会将矩阵四周置为1(不通)。
对于查找迷宫路由问题首先,考察,迷宫的入口位置,如果该位置就是迷宫出口,则已经找到了一条路径,搜索工作结束。
否则,考察其上、下、左、右位置上的邻居是否是障碍,若不是就移动到这个相邻位置上,然后对于这个位置开始搜索通往出口的路径。
如果不成功,就选择另一个相邻的位置,并从它开始搜索路径。
为防止搜索出现重复,则将已搜索过的位置标记为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)放入堆栈中,从它开始搜索,标记。
由于其只有一个非障碍位置,所以接下来移动到(1,2),防止稍后的搜索再经过这个位置。
从(1,2)移动到(2,2),放入堆栈中,(2,2)存在(2,3)、(3,2)两个可移动位置。
标记已被搜索过,对于每一个非障碍位置,它的相邻非障碍节点均入队列,实现了深度优先遍历算法。
所以如果存在路径,则从出口处节点的位置,逆序则可以找到其从出口到入口的通路。
实现了查找路径。
1.3.功能实现:1、数据输入形式和输入值的范围:生成迷宫时可选择手动或者自动生成;手动输入迷宫矩阵时以0 表示无障碍为通路,1 表示该点有障碍为墙。
所有输入中,元素的值均为整数。
2、结果的输出形式:当完成迷宫生成后,会提示输入入口与出口,进入迷宫路由查找算法,如找到出口,则打印出路径矩阵坐标,并显示显示迷宫生成图形3、测试数据:a 、进入界面,选择2,自动生成b 、输入入口与出口c 、查看结果1.4.运行环境:运行环境为DOS第二章:算法设计与流程图2.1.主函数的流程图:N判断入口是否为通路 循环结束,无通路Y Y Y YN YNYNN 图1迷宫算法流程图2.2概要设计1、为了实现上述功能,需要:①构造一个二维数组maze[M+2][N+2]用于存储迷宫矩阵,构造一个二维数组backup[M+2][N+2]用于备份迷宫矩阵;②自动或手动生成迷宫,即为二维数组maze[M+2][N+2]赋值并备份;③将构造一个堆栈用于存储迷宫路由;④建立迷宫节点struct Mlink ,用于存储迷宫中每个访问过的节点。
⑤实现迷宫路由算法,用深度优先遍历实现查找迷宫路径。
如找到路径则显示路径,否则提示无通路。
同时显示生成迷宫。
⑥在屏幕上显示操作菜单。
2、本程序包含6 个函数:( 1 )主函数 main( )栈顶位置下面可通? 栈顶位置上面可通? 栈顶位置右面可通? 栈顶位置左面可通? 找出通路,链栈内即为通路 循环结束 栈顶出栈( 2 )生成迷宫函数create( )( 3 )打印迷宫矩阵与图形函数prin( )( 4 )寻找迷宫路由Mazepath( )( 5 )输出迷宫通路坐标printonglu1( )( 6 )输出迷宫生成图形printonglu2( )各函数之间的关系如下图(图2)所示:函数关系图:create( )prin( )main() Mazepath( )printonglu1( )printonglu2( )图2各函数间关系图2.3详细设计实现概要设计中定义的所有数据类型,对各个操作给出伪代码算法。
对于主程序和各个模块也给出相应的伪代码算法。
1.节点类型和指针类型迷宫矩阵类型:Mlink *stack; 全局变量堆栈,存储迷宫通路int abc[M+2][N+2] 辅助数组int maze[M+2][N+2]; 迷宫矩阵int backup[M+2][N+2]; 备份矩阵,便于操作,定义为全局变量迷宫中节点类型及队列类型:struct Mlink { int row ,col ;struct node * next;} Mlink;2.迷宫的操作(1)生成迷宫void create(int maze[][N+2]){定义变量i,j,flag;srand( (unsigned)time( NULL ) ) 以时间产生随机种子利用for初始化迷宫矩阵与备份矩阵,包括边界全置为1利用for将迷宫置为0选择迷宫生成方式1为手动生成,2为自动生成,输入值并赋给flagflag=1{以i , j 控制迷宫中行列数的循环输入以0 表示通路,以1 表示障碍,给maze[i][j]赋值,不包括边界。
循环结束,完成迷宫生成}flag=2{定义变量i1,j1用以接收随机值以i , j 控制迷宫中行列数的循环赋值操作以0 表示通路,以1 表示障碍用for(c=1;c<=M*N;c++){i1=(int)(rand()%M)+1;j1=(int)(rand()%N)+1;maze[i1][j1]=int(rand()%2);}随机定位矩阵一点,给maze[i1][j1]赋一个随机值,这样可以增加迷宫通路的概率,循环结束,完成迷宫生成}以i , j 控制迷宫中行列数的循环赋值操作,将maze[][]备份到backup[][];}(2)打印迷宫矩阵与字符图形void prin(int maze[][N+2]){此函数主要用于将迷宫矩阵显示出来定义变量i,j,z;for(z=1;z<=N;z++){if(z<10)printf("%d ",z);elseprintf("%d",z);} 此语句用来标明列号用 for 控制循环在第一重循环里,使用语句{printf("\n");if(i<10) printf("%d ",i);else printf("%d",i);}以此用来标明行号以 i, j 控制迷宫中行列数的循环操作,将maze[i][j]显示出来并用字符□,■分别代表可通与不可通}(3)迷宫求解路由求解操作{Mlink *p;用以操作堆栈①入口若不通,return(0)否则下一步②将其入栈③未找到出口并且堆栈不空{1)栈顶位置以下是否可通,可通则返回②,否则2),2)栈顶位置以上是否可通,可通则返回②,否则3),3)栈顶位置以右是否可通,可通则返回②,否则4),4)栈顶位置以左是否可通,可通则返回②,否则出栈并返回,} ④如果栈顶为出口,return (1);否则return (0);}(4)打印迷宫通路坐标void printonglu1(){Mlink *q;用以操作堆栈q=stackq不空{输出q指向的坐标q=q->next}}(5)输出迷宫通路的字符图形void printonglu2(){此函数根据堆栈内栈顶与“次栈顶”的位置关系决定输出字符↑,←,→或↓,其中2=↑,3=←,4=→,5=↓所有的操作都是在备份矩阵backup[][]上。
出口位置输出㊣int i,z,j;Mlink *p=stack;p不空{if(p->row>p->next->row) backup[p->next->row][p->next->col]=5;下一位置在下else if(p->row<p->next->row) backup[p->next->row][p->next->col]=2;下一位置在上else if(p->col>p->next->col) backup[p->next->row][p->next->col]=4;下一位置在右else ;下一位置在左}利用for循环,i,j为循环控制变量输出备份矩阵backup[][]{为0是输出“□”为1是输出“■”为2是输出“↑”为3是输出“←”为4是输出“→”为5是输出“↓”为6是输出“㊣”}另外在输出语句上,与矩阵输出相同,标明了行号与列号(该功能为王教授所要求而后加的) }3.主函数void menu(){定义迷宫数组矩阵maze[M+2][N+2]定义辅助数组abc[M+2][N+2] 以用来在可以在第一次产生迷宫中重复选择入口与出口定义变量k以用来控制循环定义整型变量 x1,y1 ,用于存储入口。