数据结构迷宫求解
数据结构课程设计迷宫问题求解

数据结构课程设计迷宫问题求解正文:一、引言在数据结构课程设计中,迷宫问题求解是一个经典且常见的问题。
迷宫问题求解是指通过编程实现在迷宫中找到一条从起点到终点的路径。
本文将详细介绍如何用数据结构来解决迷宫问题。
二、问题分析1.迷宫定义:迷宫是由多个格子组成的矩形区域,其中包括起点和终点。
迷宫中的格子可以是墙壁(无法通过)或者通道(可以通过)。
2.求解目标:在给定的迷宫中,找到从起点到终点的一条路径。
3.输入:迷宫的大小、起点坐标、终点坐标以及墙壁的位置。
4.输出:从起点到终点的路径,或者提示无解。
三、算法设计1.基础概念a) 迷宫的表示:可以使用二维数组来表示迷宫,数组的元素可以是墙壁、通道或者路径上的点。
b) 坐标系统:可以使用(x, y)来表示迷宫中各个点的坐标。
c) 方向定义:可以用上、下、左、右等四个方向来表示移动的方向。
2.深度优先搜索算法(DFS)a) 算法思想:从起点开始,沿着一个方向一直走到无法继续为止,然后回退到上一个点,再选择其他方向继续探索。
b) 算法步骤:i) 标记当前点为已访问。
ii) 判断当前点是否为终点,如果是则返回路径;否则继续。
iii) 遍历四个方向:1.如果该方向的下一个点是通道且未访问,则继续向该方向前进。
2.如果该方向的下一个点是墙壁或已访问,则尝试下一个方向。
iv) 如果四个方向都无法前进,则回退到上一个点,继续向其他方向探索。
3.广度优先搜索算法(BFS)a) 算法思想:从起点开始,逐层向外探索,直到找到终点或者所有点都被访问。
b) 算法步骤:i) 标记起点为已访问,加入队列。
ii) 循环以下步骤直到队列为空:1.取出队首元素。
2.判断当前点是否为终点,如果是则返回路径;否则继续。
3.遍历四个方向:a.如果该方向的下一个点是通道且未访问,则标记为已访问,加入队列。
iii) 如果队列为空仍未找到终点,则提示无解。
四、算法实现1.选择合适的编程语言和开发环境。
数据结构程序设计(迷宫问题)

数据结构程序设计(迷宫问题)数据结构程序设计(迷宫问题)一、引言迷宫问题是计算机科学中常见的问题之一,它涉及到了数据结构的设计和算法的实现。
本文将介绍迷宫问题的定义、常见的解决算法和程序设计思路。
二、问题定义迷宫问题可以描述为:给定一个迷宫,迷宫由若干个连通的格子组成,其中有些格子是墙壁,有些格子是路径。
任务是找到一条从迷宫的起点(通常是左上角)到终点(通常是右下角)的路径。
三、基本数据结构1.迷宫表示:迷宫可以使用二维数组来表示,数组中的每个元素代表一个格子,可以用0表示路径,用1表示墙壁。
2.坐标表示:可以使用二维坐标表示迷宫中的每一个格子,使用(x, y)的形式表示。
四、算法设计1.深度优先搜索算法:深度优先搜索算法可以用来解决迷宫问题。
算法从起点开始,尝试向四个方向中的一个方向前进,如果可以移动则继续向前,直到到达终点或无法继续移动。
如果无法继续移动,则回溯到上一个节点,选择另一个方向继续搜索,直到找到一条路径或者所有路径都已经探索完毕。
2.广度优先搜索算法:广度优先搜索算法也可以用来解决迷宫问题。
算法从起点开始,先将起点加入队列,然后不断从队列中取出节点,并尝试向四个方向中的一个方向移动,将新的节点加入队列。
直到找到终点或者队列为空,如果队列为空则表示无法找到路径。
五、程序设计思路1.深度优先搜索算法实现思路:a) 使用递归函数来实现深度优先搜索算法,参数为当前节点的坐标和迷宫数据结构。
b) 判断当前节点是否为终点,如果是则返回成功。
c) 判断当前节点是否为墙壁或已访问过的节点,如果是则返回失败。
d) 将当前节点标记为已访问。
e) 递归调用四个方向,如果存在一条路径则返回成功。
f) 如果四个方向都无法找到路径,则将当前节点重新标记为未访问,并返回失败。
2.广度优先搜索算法实现思路:a) 使用队列保存待访问的节点。
b) 将起点加入队列,并标记为已访问。
c) 不断从队列中取出节点,尝试向四个方向移动,如果新的节点未被访问过且不是墙壁,则将新的节点加入队列,并标记为已访问。
数据结构迷宫问题求解

学号专业计算机科学与技术姓名实验日期2017.6.20教师签字成绩实验报告【实验名称】迷宫问题的求解【实验目的】(1)通过本课程的学习,能熟练掌握几种基本数据结构的基本操作。
(2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。
(3)用递归和非递归两种方式完成迷宫问题的求解。
【实验原理】迷宫问题通常是用“穷举求解”方法解决,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前走;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。
假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。
栈是一个后进先出的结构,可以用来保存从入口到当前位置的路径。
【实验内容】1 需求分析1.基本要求:(1)首先实现一个以链表作存储结构的栈类型,然后编写一个求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出。
其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
如,对于教材第50页图3.4所示的迷宫,输出一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),…(2)编写递归形式的算法,求得迷宫中所有可能的通路。
(3)以方阵形式输出迷宫和其通路。
(4)按照题意要求独立进行设计,设计结束后按要求写出设计报告。
2.输入输出的要求:(i) 求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一个坐标的方向。
(ii)输出迷宫示意图3.程序所能达到的功能:(i) 实现一个以链表作存储结构的栈类型,以非递归算法求出通路(ii)以一个递归算法,对任意输入的迷宫矩阵求出所有通路。
2 概要设计1.①构建一个二维数组maze[M][N]用于存储迷宫矩阵②手动生成迷宫,即为二维数组maze[M][N]赋值③构建一个栈用于存储迷宫路径④建立迷宫节点用于存储迷宫中每个节点的访问情况;非递归本程序包含6个函数:(1)主函数 main()(2)生成迷宫 create_maze()(4)打印迷宫 print_maze()(5)搜索迷宫路径并用三元组输出路径 mgpath()(6)用图来输出路径print_tu();递归本程序包含3个函数:(1)主函数main();(2)打印迷宫printmaze();(3)搜索迷宫路径pass(int x,int y);3. 详细设计1.非递归起点和终点的结构类型 typedef struct{int h;int l;}T;栈节点类型 typedef struct cell{int row;int col;int dir;}TCell;1.生成迷宫void creat_maze(int a,int b){定义i,j为循环变量for(i<a)for(j<b)输入maze[i][j]的值}2.打印迷宫void print_maze(int m,int n){用i,j循环变量,将maze[i][j]输出}3.搜索迷宫路径void mazepath(int maze[][],T s,T e) //参数传递迷宫和起点与终点{TCell S[N1*N2];top=0; //建立栈S[top].row=s.h;S[top].col=s.l;S[top].dir=-1; //起点入栈while(top>=0) //判栈是否空{ i,j为当前访问点的位置if(i,j是终点坐标)用循环输出栈里的元素;else 将(i,j),即访问点入栈,然后向四周寻找是否有通路,若有通路,将原访问点标记(赋值-1),选一条通路作为新访问点,入栈。
数据结构迷宫求解

数据结构迷宫求解迷宫问题是一种常见的求解问题,通过在迷宫中找到从起点到终点的路径。
在计算机科学中,使用数据结构来解决迷宫问题非常方便。
本文将介绍迷宫问题的基本原理、常见的求解方法以及使用不同数据结构的优缺点。
首先,我们需要明确迷宫的基本定义。
迷宫可以看作是一个二维的网格,其中包含一些墙壁和通路。
起点是迷宫的入口,终点则是迷宫的出口。
我们的目标是找到从起点到终点的一条路径。
迷宫问题可以使用多种算法求解,包括深度优先(DFS)、广度优先(BFS)、最短路径算法等。
以下将详细介绍这些算法以及它们在迷宫问题中的应用。
同时,我们还会讨论不同数据结构在求解迷宫问题中的优缺点。
首先,深度优先(DFS)是一种常用的求解迷宫问题的算法。
该算法从起点开始,一直到终点,期间遇到墙壁或已经访问过的点则回溯到上一个节点。
DFS可以使用递归实现,也可以使用栈来保存需要回溯的节点。
DFS的优点是简单易懂,易于实现。
然而,它可能会陷入死循环或者找到一条较长的路径而不是最短路径。
另一种常见的算法是广度优先(BFS),它从起点开始,逐层扩展,直到找到终点为止。
BFS可以使用队列来保存每一层的节点。
与DFS相比,BFS能够找到最短路径,但它需要维护一个较大的队列,从而增加了空间复杂度。
除了DFS和BFS,还有一些其他算法可以应用于迷宫问题。
例如,迪杰斯特拉算法和A*算法可以找到最短路径。
这些算法使用了图的概念,将迷宫中的通道表示为图的边,将各个节点之间的距离表示为图的权重。
然后,通过计算最短路径的权重,找到从起点到终点的最短路径。
迪杰斯特拉算法和A*算法的优点是能够找到最短路径,但它们的实现较为复杂。
在使用这些算法求解迷宫问题时,我们需要选择适合的数据结构来存储迷宫和过程中的状态。
以下是几种常见的数据结构以及它们的优缺点:1.数组:数组是一种常见的数据结构,它可以用来表示迷宫。
可以使用二维数组来表示迷宫的网格,并使用特定的值表示墙壁和通路。
数据结构迷宫求解

#include<stdio.h>#include<stdlib.h>#include<malloc.h>#define TRUE 1#define FALSE 0#define OVERFLOW 0#define OK 1#define ERROR 0#define STACK_INIT_SIZE 300//存储空间初始化分配量#define STACK_INCREMENT 10//存储空间分配增量#define MaxSize 10typedef int Status;typedef struct{int r;int c;}PosType;//坐标位置(行标,列标)typedef struct// 定义路径向量{int ord; //通道块在路径上的序号PosType seat;//通道块在迷宫中的位置int di;//从此通道块走向下一通道块的方向}SElemType;typedef struct{SElemType *base;SElemType *top;//栈底指针int stacksize;}SqStack;typedef struct{int r;int c;char adr[MaxSize+2][MaxSize+2];}MazeType;//迷宫类型Status InitStack(SqStack *S);//初始化Status Push(SqStack *S,SElemType e);//向栈顶插入元素Status Pop(SqStack *S);//出栈Status StackEmpty(SqStack *S);Status InitMaze(MazeType *maze);//初始化迷宫Status Pass(MazeType *maze,PosType curpos);//判断当前位置可否通过Status FootPrint(MazeType *maze,PosType curpos);//走过的地方留下足迹PosType NextPos(PosType curpos,int i);//探索下一位置并返回下一位置的坐标Status MarkPrint(MazeType *maze,PosType curpos);//曾走过但不通留下标记并返回OK Status MazePath(MazeType *maze,PosType start,PosType end);//迷宫maze存在从入口start到end的通道则求得一条存放在栈中void PrintMaze(MazeType *maze);//输出迷宫#include <stdio.h>Status InitStack(SqStack *S){S->base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));if(!S->base) exit(OVERFLOW);S->top=S->base;S->stacksize=STACK_INIT_SIZE;return OK;}Status Push(SqStack *S,SElemType e){if(S->top-S->base>=S->stacksize){S->base=(SElemType*)realloc(S->base,(STACK_INIT_SIZE+STACK_INCREMENT)*sizeof(SElemType)) ;if(!S->base) exit(OVERFLOW);S->top=S->base+S->stacksize;S->stacksize+=STACK_INCREMENT;}*S->top++=e;return OK;}Status Pop(SqStack* S){SElemType e;if(S->top==S->base) return ERROR;e=*--S->top;return OK;}Status StackEmpty(SqStack *S){if(S->top==S->base)return TRUE;elsereturn FALSE;}Status InitMaze(MazeType *maze){int i,j;printf("请输入迷宫的行数\n");scanf("%d",&maze->r);printf("请输入迷宫的列数\n");scanf("%d",&maze->c); //迷宫行和列数if(maze->r>MaxSize||maze->c>MaxSize) return error;for(i=0;i<=maze->c+1;i++){ //迷宫行外墙maze->adr[0][i]='#';maze->adr[maze->r+1][i]='#';}for(i=0;i<=maze->r+1;i++){ //迷宫列外墙maze->adr[i][0]='#';maze->adr[i][maze->c+1]='#';}for(i=1;i<=maze->r;i++)for(j=1;j<=maze->c;j++)maze->adr[i][j]='0';//初始化迷宫printf("设置迷宫障碍方块行标+列标(0,0)表示结束\n");scanf("%d%d",&i,&j);while(i&&j){maze->adr[i][j]='1';scanf("%d%d",&i,&j);}//设定通道块上的不通的路块//maze->adr[1][3]='1';maze->adr[1][7]='1';//maze->adr[2][3]='1';maze->adr[2][7]='1';//maze->adr[3][5]='1';maze->adr[3][6]='1';maze->adr[3][8]='1';//maze->adr[4][2]='1';maze->adr[4][3]='1';maze->adr[4][4]='1';maze->adr[4][7]='1';//maze->adr[5][4]='1';//maze->adr[6][2]='1';maze->adr[6][6]='1';maze->adr[6][8]='1';//maze->adr[7][2]='1';maze->adr[7][3]='1';maze->adr[7][4]='1';maze->adr[7][5]='1';maze->adr[7][ 8]='1';//maze->adr[8][1]='1';maze->adr[8][2]='1';maze->adr[8][6]='1'; maze->adr[8][8]='1';//maze->adr[9][1]='1';maze->adr[9][2]='1';return OK;}Status Pass(MazeType *maze,PosType curpos)if(maze->adr[curpos.r][curpos.c]=='0')//可通return TRUE;elsereturn FALSE;}Status FootPrint(MazeType *maze,PosType curpos){maze->adr[curpos.r][curpos.c]='*';//"*"表示可通return OK;};PosType NextPos(PosType curpos,int i){PosType cpos;cpos=curpos;switch(i){ //1.2.3.4分别表示东,南,西,北方向case 1 : cpos.c+=1; break;case 2 : cpos.r+=1; break;case 3 : cpos.c-=1; break;case 4 : cpos.r-=1; break;default: exit(ERROR);}return cpos;};Status MarkPrint(MazeType *maze,PosType curpos){maze->adr[curpos.r][curpos.c]='@';//"@"表示曾走过但不通return OK;Status MazePath(MazeType *maze,PosType start,PosType end){SqStack S;PosType curpos;int curstep;//当前序号SElemType e;InitStack(&S);curpos=start; //设置"当前位置"为"入口位置"curstep=1; //探索第一步do{if(Pass(maze,curpos)){ //当前位置可以通过,当前位置上是0 FootPrint(maze,curpos);//留下足迹e.ord=curstep;e.seat=curpos;e.di=1;Push(&S,e); //加入路径if(curpos.r==end.r && curpos.c==end.c)return TRUE; //到达出口curpos=NextPos(curpos,1); //下一位置是当前位置的东邻curstep++; //探索下一步}else{ //当前位置不通if(!StackEmpty(&S)){Pop(&S);while(e.di==4 && !StackEmpty(&S)){MarkPrint(maze,e.seat); //留下不能通过的标记,并退一步Pop(&S); //注意pop操作指针的位置!!!!这是关键!e.di=S.top->di;e.seat=S.top->seat;e.ord=S.top->ord;}if(e.di< 4){e.di++;//换下一个方向探索Push(&S,e);curpos=NextPos(e.seat,e.di);//设定当前位置是该新方向上的相邻}}}}while(!StackEmpty(&S));return OK;}void PrintMaze(MazeType *maze){int i,j;printf("用心形代表迷宫的从入口到出口的一条路径\n");printf("用# ,1代表墙和不通的地方用@代表曾走过的通道块但不通\n");printf(" ");for(i=0;i<=maze->c+1;i++)//打印列数名printf("%4d",i);printf("\n\n");for(i=0;i<=maze->r+1;i++){printf("%2d",i);//打印行名for(j=0;j<=maze->c+1;j++)printf("%4c",maze->adr[i][j]);//输出迷宫//当前位置的标记printf("\n\n");}}int main(){ //主函数MazeType maze;PosType start,end;InitMaze(&maze);//初始化并创建迷宫printf("请输入起点坐标\n");scanf("%d%d",&start.r,&start.c); //输入起点printf("请输入终点\n");scanf("%d%d",&end.r,&end.c); //输入终点//start.r=1;start.c=1;//迷宫入口坐标//end.c=8;end.r=9; //迷宫出口坐标PrintMaze(&maze);MazePath(&maze,start,end);PrintMaze(&maze);//打印路径**/return 0;}。
数据结构 迷宫求解

数据结构迷宫求解数据结构迷宫求解一、引言数据结构是计算机科学中最基础、最重要的内容之一。
它能帮助我们存储和组织数据,并提供了各种算法来对这些数据进行处理和操作。
迷宫求解是其中一种经典的应用场景,通过使用适当的数据结构和算法,能够在迷宫中寻找到一条从起点到终点的路径。
本文将介绍一种常用的迷宫求解算法,并给出相应的数据结构实现。
二、问题描述1:迷宫定义:迷宫是一个由墙壁和路障组成的二维矩阵,其中墙壁表示不可通行的区域,路障表示可通行但需要绕过的区域。
迷宫通常具有一个起点和一个终点,我们需要找到一条从起点到终点的路径。
2:算法目标:实现一个算法,能够在给定的迷宫中找到一条从起点到终点的路径,并输出该路径。
三、数据结构设计1:迷宫的存储结构:为了方便表示迷宫,我们可以使用一个二维数组来表示迷宫的格子,其中每个格子表示一个迷宫的单元。
我们可以使用0表示可通行的空格,使用1表示墙壁,使用2表示路障。
同时,我们需要记录每个格子的状态,以标记是否已经被访问过。
2:路径的存储结构:为了记录找到的路径,我们可以使用一个栈来存储路径上的各个节点。
在访问迷宫时,我们将访问过的格子入栈,并在找到终点后,按照栈的顺序依次弹出格子,即可得到路径。
四、算法设计1:深度优先搜索算法:深度优先搜索是一种常用的图遍历算法,适用于解决迷宫问题。
其基本思想是从起点出发,沿着某一条路径一直向前,直到终点或者无法前进为止。
当无法前进时,回退到上一个节点,并尝试其他路径,直到找到终点或者所有路径都尝试完毕。
2:算法步骤:- 将起点入栈,并标记其为已访问;- 当栈不为空时,弹出栈顶元素,并尝试向上、下、左、右四个方向前进,如果某一方向可以前进且未被访问过,则将该方向上的格子入栈,并标记为已访问;- 当找到终点时,输出路径;- 当所有路径都尝试完毕时,结束算法。
五、算法实现1:迷宫的表示:我们可以使用一个二维数组来存储迷宫,如下所示: ```pythonmaze = [[0, 1, 0, 0, 0],[0, 1, 0, 1, 0],[0, 0, 0, 0, 0],[0, 1, 1, 1, 0],[0, 0, 0, 1, 0]]```2:深度优先搜索的实现:我们可以使用递归来实现深度优先搜索算法,如下所示:```pythondef dfs(maze, start, end, path):if start == end:return Truei, j = startmaze[i][j] = 2path:append(start)if i > 0 and maze[i - 1][j] == 0 anddfs(maze, (i - 1, j), end, path):return Trueif i < len(maze) - 1 and maze[i + 1][j] == 0 and dfs(maze, (i + 1, j), end, path):return Trueif j > 0 and maze[i][j - 1] == 0 anddfs(maze, (i, j - 1), end, path):return Trueif j < len(maze[0]) - 1 and maze[i][j + 1] == 0 and dfs(maze, (i, j + 1), end, path):return Truepath:pop()return Falsedef solve_maze(maze, start, end):path = []dfs(maze, start, end, path)return path```六、待解决的问题1:如何处理迷宫中存在的死胡同(即无法找到终点的路径)?2:如何处理迷宫中存在的多条路径(即多个路径都能到达终点)?附件:- 迷宫示例图片- 算法实现示例代码- 数据结构设计图法律名词及注释:1:数据结构:在计算机科学中,数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。
数据结构课程设计 迷宫求解

考虑使用一个二维数组表示迷宫.所有的通路用0表示,墙用1表示,出口用9表示,入口用6表示,已经过点用3表示.输出走出迷宫的过程.从这个问题的求解过程中可以简单总结出两个算法,一是探路过程,二是输出路线.1.探路过程探路过程算法可归纳为:[1]从入口位置开始,检查东西南北四个方向上的通路,如果发现出口则成功退出,否则将所有通路坐标压入栈;[2]从栈中取出一个坐标,将其标记为当前位置(标记数字3),再次判断通路情况;[3]如此进行,直到发现出口则成功退出,若栈空而且未发现出口,则失败退出.这里使用到的回溯过程可描述为: 每到达一点时,会将所有可能的通路坐标(标记数字0的节点)压入栈.所以当到达一点,而不存在可能的通路时,自然没有相应的坐标压入栈,而此时便从栈中取出上一个点所压入的可能的一个通路坐标,并继续作通路判断,这便是一个回溯的过程.2.输出某一较短路线将所有在探路过程中经过的点(标记数字3的节点)按实际探路路线存入队列,对头为入口,队尾为出口.这些点可能存在绕路的情况,所以可用下面的算法输出某一较短路线.[1]将队尾(出口)节点设置为当前判断节点;[2]从当前判断节点(x,y)的前驱节点开始,向前遍历队列,如果发现相邻节点(其坐标可以为(x+1,y),(x-1,y),(x,y+1),(x,y-1)之一),则删除该相临节点至当前判断节点的前驱节点之间的所有节点;[3]将该相临节点设置为当前判断节点,继续判断相临节点;[4]当当前判断节点为对头节点时退出.该算法所得到的路线不一定是最短路线,想得到最短路线,可考虑使用树结构将所有由出口至入口的路线保留为一子树,树高最短的子树即为最短路线.但此算法可保证所得路线不会存在绕路情况.3.表示节点坐标的类public class MazeCell {private int x, y;//表示x轴y轴坐标public MazeCell() {}public MazeCell(int i, int j) {x = i;y = j;}public boolean equals(Object o) {if (!(o instanceof MazeCell))return false;MazeCell cell = (MazeCell) o;return cell.x == x && cell.y == y;}public String toString() {return x + "," + y;}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public void setY(int y) {this.y = y;}}4.所使用的栈数据结构import java.util.LinkedList;public class Stack<T> {private LinkedList<T> storage = new LinkedList<T>(); /** 入栈*/public void push(T v) {storage.addFirst(v);}/** 出栈,但不删除*/public T peek() {return storage.getFirst();}/** 出栈*/public T pop() {return storage.removeFirst();}/** 栈是否为空*/public boolean empty() {return storage.isEmpty();}/** 打印栈元素*/public String toString() {return storage.toString();}}5.求解迷宫问题import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintStream;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.ListIterator;public class Maze {private int rows = 0, cols = 0;// 迷宫的行数与列数private char[][] store, path;// 迷宫矩阵private MazeCell currentCell, exitCell = new MazeCell(),entryCell = new MazeCell();// 当前节点,出口节点,入口节点private static final char EXIT = '9', ENTRY = '6', VISITED = '3';// 出口标记,入口标记,已经过节点标记private static final char PASS = '0', W ALL = '1';// 通路标记,墙标记private Stack<MazeCell> mazeStack = new Stack<MazeCell>();// 探路过程所使用栈private List<MazeCell> currentList = new LinkedList<MazeCell>();// 路经的路线队列public Maze() {// 构造迷宫int row = 0, col = 0;Stack<String> mazeRows = new Stack<String>();InputStreamReader isr = new InputStreamReader(System.in);BufferedReader buffer = new BufferedReader(isr);System.out.println("Enter a rectangular maze using the following" + " characters: \n6-entry\n9-exit\n1-wall\n0-passage\n"+ "Enter one line at a time; end with Ctrl-d;");try {String str = buffer.readLine();while (str != null) {row++;cols = str.length();str = "1" + str + "1";mazeRows.push(str);if (str.indexOf(EXIT) != -1) {exitCell.setX(row);exitCell.setY(str.indexOf(EXIT));}if (str.indexOf(ENTRY) != -1) {entryCell.setX(row);entryCell.setY(str.indexOf(ENTRY));}str = buffer.readLine();}} catch (IOException e) {e.printStackTrace();}rows = row;store = new char[rows + 2][];store[0] = new char[cols + 2];for (; !mazeRows.empty(); row--)store[row] = (mazeRows.pop()).toCharArray();store[rows + 1] = new char[cols + 2];for (col = 0; col <= cols + 1; col++) {store[0][col] = WALL;store[rows + 1][col] = WALL;}path = new char[rows + 2][];copyArray(store, path);}/** 二维数组复制*/private void copyArray(char[][] src, char[][] tar) {for (int i = 0; i < src.length; i++) {tar[i] = new char[cols + 2];for (int j = 0; j < src[i].length; j++)tar[i][j] = src[i][j];}}/** 二维数组输出*/private void display(PrintStream out, char[][] carray) {for (int row = 0; row <= rows + 1; row++)out.println(carray[row]);out.println();}/** 将未访问并可通路的节点压入栈*/private void pushUnvisited(int row, int col) {if (store[row][col] == PASS || store[row][col] == EXIT) mazeStack.push(new MazeCell(row, col));}/** 探路过程*/public void exitMaze(PrintStream out) {currentCell = entryCell;currentList.add(currentCell);out.println();while (!currentCell.equals(exitCell)) {int row = currentCell.getX();int col = currentCell.getY();display(System.out, store);if (!currentCell.equals(entryCell))store[row][col] = VISITED;pushUnvisited(row - 1, col);pushUnvisited(row + 1, col);pushUnvisited(row, col - 1);pushUnvisited(row, col + 1);if (mazeStack.empty()) {display(out, store);out.println("Failure");return;} else {currentCell = mazeStack.pop();currentList.add(currentCell);}}display(out, store);out.println("Success");}/** 得到某一输出路线*/private void getPath() {if (currentList.size() <= 0)return;MazeCell cell = currentList.get(currentList.size() - 1);while (cell != currentList.get(0)) {List<MazeCell> subList = currentList.subList(0, currentList.indexOf(cell));ListIterator<MazeCell> itr = subList.listIterator();while (itr.hasNext()) {MazeCell target = itr.next();if (adjoin(cell, target)) {removeElements(currentList.indexOf(target) + 1, currentList .indexOf(cell));cell = target;break;}}}}/** 删除队列中由from至to的连续元素*/private void removeElements(int from, int to) {int turn = to - from;while (turn > 0) {currentList.remove(from);turn--;}}/** 判断两个节点是否相邻*/private boolean adjoin(MazeCell current, MazeCell target) {if ((current.getX() == target.getX() + 1 || current.getX() == target.getX() - 1)&& (current.getY() == target.getY()))return true;if ((current.getY() == target.getY() + 1 || current.getY() == target.getY() - 1)&& (current.getX() == target.getX()))return true;return false;}/** 输出路线*/public void printPath(PrintStream out) {getPath();out.println("Path:");if (currentList.size() >= 2) {currentList.remove(currentList.size() - 1);currentList.remove(0);}Iterator<MazeCell> itr = currentList.iterator();while (itr.hasNext()) {MazeCell cell = itr.next();path[cell.getX()][cell.getY()] = VISITED;}display(System.out, path);}public static void main(String[] args) {Maze maze = new Maze();maze.exitMaze(System.out);maze.printPath(System.out);}}6.结果输出Enter a rectangular maze using the following characters: 6-entry9-exit1-wall0-passageEnter one line at a time; end with Ctrl-d;90000110110000000600//构造的迷宫如下111111119000011110111100000110060011111111//开始探路11111111900001111011110000011006001 11111111111111 1900001 1110111 1000001 1006301 11111111111111 1900001 1110111 1000001 1006331 1111111 1111111 1900001 1110111 1000031 1006331 11111111111111 1900001 1110111 1000331 1006331 1111111 1111111 1900001 1110111 1003331 1006331 11111111111111 1900001 1110111 1033331 1006331 1111111111111119000011110111133333110063311111111111111119000011110111133333113063311111111111111119000011110111133333113363311111111//下一步为回溯过程111111119000011110111133333113363311111111111111119000011113111133333113363311111111111111119030011113111133333113363311111111111111119033011113111133333113363311111111111111119033311113111133333113363311111111//下一步为回溯过程111111119333311113111133333113363311111111SuccessPath:111111119330011113111100300110060011111111。
数据结构 迷宫求解

实验二:迷宫1.需求分析[迷宫求解] 求迷宫中从入口到出口的所有路径;计算机接迷宫问题时,通常使用的是“穷举求解”的方法,即从入口出发,顺某一方向向前探索,若能走通,则继续往前走;否则,沿原路返回,换一个方向再继续探索,直至所有可能的通路都探索到为止。
因此,在求解迷宫通路问题的算法中可应用“栈”设计一个先进后出的结构来保存从入口到当前位置的路径。
在计算机中构造一个方块图表示迷宫,图中每个方块或为通道(即空白方块),或为墙(即阴影方块)。
所求路径必须为简单路径,即在求得的路径上不能重复出现同一通道块。
假设“当前位置”指的是“在搜索过程中某一时刻所在图中某个方块位置”,则求迷宫中一条路径的基本思想是:若当前位置“可通”,则纳入“当前路径”,并继续朝下一个“位置”探索,即切换“下一位置”为“当前位置”,如此重复直至到达出口;若当前位置“不可通,则应顺着“来向”退回到“迁移通道块”,然后朝着除了“来向”之外的其他方向继续探索;若该通道块的四周4个方块均“不可通”,则应该“从当前路径”删除该通道块。
所谓“下一位置”指的是“当前位置”四周4个方向(东西南北)上相邻的方块。
假设以栈S记录“当前路径”,则栈顶中存放的是“当前路径上最后一个通道块”。
由此,“纳入路径”的操作即为“当前位置入栈”;“从当前路径上删除前衣通道块”的操作即为“出栈”。
2.概要设计void EnQueue(int i,int j,int k); //入队一个节点void DeQueue(int *i,int *j,int *k); //获取当前节点的序号和对应的迷宫坐标,然后出列bool GetNextPos(int *i ,int *j,int count); //得到下一个邻接点的位置void ShortestPath_BFS(int i,int j); //广度优先遍历寻找最短路径void ShortestPath(); //输出最短路径void Print(); //输出迷宫形状int Map[10][10] = {{1,1,1,1,1,1,1,1,1,1},{1,0,0,1,0,0,0,1,0,1},{1,0,0,1,0,0,0,1,0,1},{1,0,0,0,0,1,1,0,0,1},{1,0,1,1,1,0,0,0,0,1},{1,0,0,0,1,0,0,0,0,1},{1,0,1,0,0,0,1,0,0,1},{1,0,1,1,1,0,1,1,0,1},{1,1,0,0,0,0,0,0,0,0},{1,1,1,1,1,1,1,1,1,1}};struct Node{int parent_id; //保存父节点的位置int node_id; //当前节点的序号,以便传递给子节点int x,y; //当前结点对应的坐标}Q[10*10]; //每个节点包含迷宫坐标、队列中的序号、父节点的序号,多个节点形成队列int front = 0,rear = 0; //队列头指针和尾指针void EnQueue(int i,int j,int k){Q[rear].x = i;Q[rear].y = j; //保存当前节点对应的坐标位置Q[rear].parent_id = k; //保存父节点的序号Q[rear].node_id = rear; //保存当前节点序号rear++;}void DeQueue(int *i,int *j,int *k){*i = Q[front].x;*j = Q[front].y;*k = Q[front].node_id;front++; //出列一个节点}bool GetNextPos(int *i ,int *j,int count){switch(count){case 1:(*j)++; return 1; //右(东)case 2:(*i)++; return 1; //下(南)case 3:(*j)--; return 1; //左(西)case 4:(*i)--; return 1; //上(北)default: return 0;}}void ShortestPath_BFS(int i ,int j){int count,m,n,k;EnQueue(i,j,-1); Map[1][1] = 1; //起点入队,标记起点已走过while(true){count = 1;DeQueue(&i,&j,&k);n = i,m = j; //保存当前位置while(GetNextPos(&i,&j,count)){count++;if(!Map[i][j]){EnQueue(i,j,k); Map[i][j] = 1;if(i == 8 && j == 9) return; //到达终点,(8,9)是默认终点,可以任意修改}i = n; j = m; //保证遍历当前坐标的所有相邻位置}}}3.详细设计主函数部分:#include"maze.h"#include<iostream>using namespace std;void main(){cout<<"程序说明:"<<'\n'<<"1.输出路径为最短路径;"<<'\n'<<"2.默认的出口在最右下角,如有需要可以调整。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
【完成题目3】迷宫求解【问题描述】以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
【基本要求】首先实现一个栈类型,然后编写一个求解迷宫的非递归程序。
求得的通路以三元组(i,j,d)的形式输出,其中(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。
【算法设计】本实验的目的是设计一个程序,实现手动或者自动生成一个n×m矩阵的迷宫,寻找一条从入口点到出口点的通路。
我们将其简化成具体实验内容如下:选择手动或者自动生成一个n×m的迷宫,将迷宫的左上角作入口,右下角作出口,设“0”为通路,“1”为障碍,即无法穿越。
假设从起点出发,目的为右下角终点,可向“上、下、左、右、左上、左下、右上、右下”8个方向行走。
如果迷宫可以走通,则用“■”代表“1”,用“□”代表“0”,用“→”代表行走迷宫的路径。
输出迷宫原型图、迷宫路线图以及迷宫行走路径。
如果迷宫为死迷宫,输出信息。
可以二维数组存储迷宫数据,用户指定入口下标和出口下标。
为处理方便起见,可在迷宫的四周加一圈障碍。
对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。
本程序包含三个模块1)主程序模块:void main(){初始化;do {接受命令;处理命令;} while (命令! = 退出);}2)栈模块——实现栈抽象数据类型;3)迷宫模块——实现迷宫抽象数据类型。
【源代码】#include<stdlib.h> //库中包含system("pause")和rand()函数#include<stdio.h> //c语言里的库#include<iostream>#include <malloc.h>#define OK 1#define ERROR 0#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define OVERFLOW -1#define M 49#define N 49using namespace std;int maze[M][N];typedef int Status;typedef struct{int m,n,direc;}MazeType,*LMazeType;typedef struct{LMazeType top;LMazeType base;int stacksize;int over;}Stack;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);}}}}void Init_automatic_Maze(int maze[M][N],int m,int n) //自动生成迷宫int i,j;cout<<"\n迷宫生成中……\n\n";system("pause");for(i=1;i<m+1;i++)for(j=1;j<n+1;j++)maze[i][j]=rand()%2; //随机生成0、1}void PrintMaze(int maze[M][N],int row,int col){int i,j;cout<<"迷宫如图所示."<<endl;for(i=1;i<row+1;i++){for(j=1;j<col+1;j++){if(maze[i][j]==1)cout<<"■";elsecout<<"□";}cout<<endl;}}Status InitStack(Stack &S){S.base=(LMazeType)malloc(STACK_INIT_SIZE * sizeof(MazeType));if(!S.base)exit(OVERFLOW);S.top=S.base;S.stacksize=STACK_INIT_SIZE;S.over=0;return OK;}Status Push(Stack &S,MazeType e){if(S.top-S.base>=S.stacksize){S.base=(LMazeType)realloc(S.base,(S.stacksize+STACKINCREMENT) * sizeof(MazeType)); if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top++=e;return OK;Status Pop(Stack &S,MazeType &e){if(S.top==S.base)return ERROR;e=*--S.top;return OK;}Status MazePath(Stack &S,MazeType &e,int maze[M][N],int m,int n) {do{if(maze[e.m][e.n]==0)//0可通,1不可通,2为已走过{Push(S,e);maze[e.m][e.n]=2;if(e.m==m&&e.n==n){S.over=1;//表示存满一条路径return OK;}else {e.n++;e.direc=0;//来这一点时的方向,0右1下2左3上MazePath(S,e,maze,m,n);}}else{if(S.top!=S.base&&S.over!=1){switch(e.direc) //回到上一位置并同时改变方向走下一步 {case 0:e.n--;e.m++;e.direc=1;break;case 1:e.m--;e.n--;e.direc=2;break;case 2:e.n++;e.direc=3;break;case 3:Pop(S,e);break;}}}}while(S.top!=S.base&&S.over!=1);return OK;}int PrintPath(Stack S,int maze[M][N],int row,int col){if(S.top==S.base){cout<<"\n===============================================\n"; cout<<"此迷宫无解\n\n";return ERROR;}MazeType e;while(S.top!=S.base){Pop(S,e);maze[e.m][e.n]=(e.direc+10);}cout<<"完成!"<<endl;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:break;case 10:cout<<"→";break;case 11:cout<<"↓";break;case 12:cout<<"←";break;case 13:cout<<"↑";break;}}cout<<endl;}cout<<"入口"<<endl;cout<<"完成!"<<endl;return OK;}int main(){int i,m,n,maze[M][N],cycle=0;while(cycle!=(-1)){cout<<"********************************************************************************\n"; cout<<" 欢迎进入迷宫求解系统\n";cout<<endl;cout<<"********************************************************************************\n"; cout<<" ☆ 1 手动生成迷宫☆\n";cout<<" ☆ 2 自动生成迷宫☆\n";cout<<" ☆ 3 退出☆\n\n";cout<<"********************************************************************************\n"; cout<<"\n";cout<<"请选择你的操作:\n";cin>>i;switch(i){case 1:cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;while((m<1||m>49)||(n<1||n>49)){cout<<"\n抱歉,你输入的行列数超出预设范围(1-49,1-49),请重新输入:\n\n";cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;}Init_hand_Maze(maze,m,n);PrintMaze(maze,m,n);MazeType start,end;cout<<"请输入起点m n:"<<endl;cin>>start.m>>start.n;start.direc=0;cout<<"请输入终点m n:"<<endl;cin>>end.m>>end.n;Stack S;cout<<"寻找路径..."<<endl;InitStack(S);MazePath(S,start,maze,end.m,end.n);PrintPath(S,maze,m,n);system("pause");cout<<"\n\nPress Enter Contiue!\n";getchar();while(getchar()!='\n'); //接受一个输入,当为回车时执行break跳出,否则一直执行接受数据break;case 2:cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;while((m<0||m>49)||(n<0||n>49)){cout<<"\n抱歉,你输入的行列数超出预设范围(0-49,0-49),请重新输入:\n\n";cout<<"\n请输入行数:";cin>>m;cout<<"\n";cout<<"请输入列数:";cin>>n;}Init_automatic_Maze(maze,m,n);PrintMaze(maze,m,n);cout<<"请输入起点m n:"<<endl;cin>>start.m>>start.n;start.direc=0;cout<<"请输入终点m n:"<<endl;cin>>end.m>>end.n;cout<<"寻找路径..."<<endl;InitStack(S);MazePath(S,start,maze,end.m,end.n); PrintPath(S,maze,m,n);system("pause");cout<<"\n\nPress Enter Contiue!\n";getchar();while(getchar()!='\n');break;case 3:cycle=(-1);break;default:cout<<"\n";cout<<"你的输入有误!\n"; cout<<"\nPress Enter Contiue!\n";getchar();while(getchar()!='\n');break;}}}【结果截图】迷宫无解的情况手动生成迷宫的情况11 /11自动生成迷宫的情况 【收获及体会】1. 本次实验核心算法明晰,思路明确,易于实现。