迷宫问题课程设计报告.docx

上传人:b****6 文档编号:8222036 上传时间:2023-01-29 格式:DOCX 页数:26 大小:214.04KB
下载 相关 举报
迷宫问题课程设计报告.docx_第1页
第1页 / 共26页
迷宫问题课程设计报告.docx_第2页
第2页 / 共26页
迷宫问题课程设计报告.docx_第3页
第3页 / 共26页
迷宫问题课程设计报告.docx_第4页
第4页 / 共26页
迷宫问题课程设计报告.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

迷宫问题课程设计报告.docx

《迷宫问题课程设计报告.docx》由会员分享,可在线阅读,更多相关《迷宫问题课程设计报告.docx(26页珍藏版)》请在冰豆网上搜索。

迷宫问题课程设计报告.docx

迷宫问题课程设计报告

一、课程设计名称及内容

名称:

迷宫问题

内容:

生成一个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)可以选用深度优先算法或广度优先算法实行,迷宫可由自动或手动生成。

测试用例应该包含有解迷宫和无解迷宫。

二、问题分析

本程序要求实现迷宫问题的相关操作,包括迷宫的组织和存储,并实现迷宫路由算法(即查找迷宫路径)。

程序所能达到的:

具体包括迷宫的建立,迷宫的存储(迷宫由自动生成或手动生成),迷宫中路径的查找

迷宫是一个矩形区域,迷宫存在一个入口和一个出口,其内部包含了不能穿越的墙或者障碍。

迷宫的建立即是建立这样一个迷宫矩阵,用于存储迷宫信息,包括可穿越的路和不可穿越的墙或者障碍,分别用0表示通路,1表示障碍。

对于迷宫矩阵,用m×n的矩阵来描述,m和n分别代表迷宫的行数和列数。

这样,则迷宫中的每个位置都可以用其行号和列号来指定。

从入口到出口的路径是由一组位置构成的。

每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的上、下、左、右的邻居。

为了描述迷宫中位置(i,j)处有无障碍,规定,当位置(i,j)处有一个障碍时,其值为1,否则为0.这样迷宫就可以用0、1矩阵来描述,在构造矩阵时,为了操作方便会将矩阵四周置为1(不通)。

对于查找迷宫路由问题

首先,考察,迷宫的入口位置,如果该位置就是迷宫出口,则已经找到了一条路径,搜索工作结束。

否则,考察其上、下、左、右位置上的邻居是否是障碍,若不是就移动到这个相邻位置上,然后对于这个位置开始搜索通往出口的路径。

如果不成功,就选择另一个相邻的位置,并从它开始搜索路径。

为防止搜索出现重复,则将已搜索过的位置标记为1。

同时为保留过搜索的痕迹,在考察相邻位置之前,将当前位置保存在一个堆栈中,如果所有相邻的非障碍位置均被搜索过,且未能找到通往出口的路径,则表明不存在从入口到出口的路径。

且对于此,实现的是深度优先遍历算法,如果查找到路径,则为从入口到出口的路径。

下面实现如何利用堆栈实行深度优先遍历算法进行迷宫最短路径的查找。

以矩阵1111111

1001011

1100101

1100011

1001001

1111111

首先,将位置(1,1)放入堆栈中,从它开始搜索,标记。

由于其只有一个非障碍位置,所以接下来移动到(1,2),防止稍后的搜索再经过这个位置。

从(1,2)移动到(2,2),放入堆栈中,(2,2)存在(2,3)、(3,2)两个可移动位置。

标记已被搜索过,对于每一个非障碍位置,它的相邻非障碍节点均入队列,实现了深度优先遍历算法。

所以如果存在路径,则从出口处节点的位置,逆序则可以找到其从出口到入口的通路。

实现了查找路径。

宫路由算法流程图:

N

N

YY

Y

N

Y

N

Y

N

Y

N

图1迷宫路由算法流程图

1、数据输入形式和输入值的范围:

生成迷宫时可选择手动或者自动生成;手动输入迷宫矩阵时以0表示无障碍为通路,1表示该点有障碍为墙。

所有输入中,元素的值均为整数。

2、结果的输出形式:

当完成迷宫生成后,会提示输入入口与出口,进入迷宫路由查找算法,如找到出口,则打印出路径矩阵坐标,并显示显示迷宫生成图形

3、测试数据:

a、进入界面,选择2,自动生成

b、输入入口与出口

c、查看结果

三、概要设计

1、为了实现上述功能,需要:

①构造一个二维数组maze[M+2][N+2]用于存储迷宫矩阵,构造一个二维数组backup[M+2][N+2]用于备份迷宫矩阵;②自动或手动生成迷宫,即为二维数组maze[M+2][N+2]赋值并备份;③将构造一个堆栈用于存储迷宫路由;④建立迷宫节点structMlink,用于存储迷宫中每个访问过的节点。

⑤实现迷宫路由算法,用深度优先遍历实现查找迷宫路径。

如找到路径则显示路径,否则提示无通路。

同时显示生成迷宫。

⑥在屏幕上显示操作菜单。

2、本程序包含6个函数:

(1)主函数main()

(2)生成迷宫函数create()

(3)打印迷宫矩阵与图形函数prin()

(4)寻找迷宫路由Mazepath()

(5)输出迷宫通路坐标printonglu1()

(6)输出迷宫生成图形printonglu2()

各函数之间的关系如下图(图2)所示:

函数关系图:

create()

prin()

 

main()Mazepath()

 

printonglu1()

 

printonglu2()

图2各函数间关系图

四、详细设计

实现概要设计中定义的所有数据类型,对各个操作给出伪代码算法。

对于主程序和各个模块也给出相应的伪代码算法。

1、节点类型和指针类型

迷宫矩阵类型:

Mlink*stack;全局变量堆栈,存储迷宫通路

intabc[M+2][N+2]辅助数组

intmaze[M+2][N+2];迷宫矩阵

intbackup[M+2][N+2];备份矩阵,便于操作,定义为全局变量

迷宫中节点类型及队列类型:

structMlink{introw,col;structnode*next;}Mlink;

2、迷宫的操作

(1)生成迷宫

voidcreate(intmaze[][N+2])

{定义变量i,j,flag;

srand((unsigned)time(NULL))以时间产生随机种子

利用for初始化迷宫矩阵与备份矩阵,包括边界全置为1

利用for将迷宫置为0

选择迷宫生成方式1为手动生成,2为自动生成,输入值并赋给flag

flag=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)打印迷宫矩阵与字符图形

voidprin(intmaze[][N+2]){

此函数主要用于将迷宫矩阵显示出来

定义变量i,j,z;

for(z=1;z<=N;z++)

{if(z<10)

printf("%d",z);

else

printf("%d",z);

}此语句用来标明列号

用for控制循环在第一重循环里,使用语句{

printf("\n");

if(i<10)printf("%d",i);

elseprintf("%d",i);}以此用来标明行号

以i,j控制迷宫中行列数的循环操作,将maze[i][j]显示出来

并用字符□,■分别代表可通与不可通}

(3)迷宫求解路由求解操作{

Mlink*p;用以操作堆栈

①入口若不通,return(0)否则下一步

②将其入栈

③未找到出口并且堆栈不空{

1)栈顶位置以下是否可通,可通则返回②,否则2),

2)栈顶位置以上是否可通,可通则返回②,否则3),

3)栈顶位置以右是否可通,可通则返回②,否则4),

4)栈顶位置以左是否可通,可通则返回②,否则出栈并返回,}

④如果栈顶为出口,return

(1);否则return(0);}

(4)打印迷宫通路坐标

voidprintonglu1(){

Mlink*q;用以操作堆栈

q=stack

q不空{

输出q指向的坐标

q=q->next}

}

(5)输出迷宫通路的字符图形

voidprintonglu2(){

此函数根据堆栈内栈顶与“次栈顶”的位置关系决定输出字符↑,←,→或↓,其中2=↑,3=←,4=→,5=↓所有的操作都是在备份矩阵backup[][]上。

出口位置输出㊣

inti,z,j;Mlink*p=stack;

p不空{

if(p->row>p->next->row)backup[p->next->row][p->next->col]=5;下一位置在下

elseif(p->rownext->row)backup[p->next->row][p->next->col]=2;下一位置在上

elseif(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、主函数

voidmenu(){

定义迷宫数组矩阵maze[M+2][N+2]

定义辅助数组abc[M+2][N+2]以用来在可以在第一次产生迷宫中重复选择入口与出口

定义变量k以用来控制循环

定义整型变量x1,y1,用于存储入口。

定义整型变量x2,y2,用于存储出口。

定义整型变量x用于接收mazepash的返回值。

输入入口与出口。

如果x=1则条用函数{

printonglu1();

printonglu2();}

否则提示无通路。

}

界面开始会显示:

1,手动建立

2,自动建立

按提示操作,输入入口与出口,回车即会看到结果

五、调试分析

在调试过程中,开始用堆栈实现了路径的查找并调试成功,但输出的结果仅仅只是路径坐标,看起来不形象,于是想到了用字符来表示图形并标出通路,虽然不是太完美,但比之之前好好多了

在实现这一算法过程,注意将访问过的节点进行标记,并且在遍历过程中对矩阵数组是“破坏性”遍历,在算法完成后,矩阵已被破坏,堆栈中会存用路径,为了再原矩阵中用字符图形表示出通路,在建立矩阵后会迷宫矩阵备份一下,当然或许会有更好的处理方法。

六、使用说明

程序名为迷宫.exe,运行环境为DOS,程序执行后显示:

建立迷宫矩阵(选择1或者2):

1,手动建立

2,自动建立进

请输入您的选择:

在输入选择后输入数字选择执行不同的迷宫建立。

按要求输入入口与出口

七、测试结果

1主页面

图3主页面

2选择自动建立

图4迷宫自动生成中

3,自动生成迷宫,上面为数组矩阵,其中0可通,1障碍。

下面为字符图形,其中白色可通,黑色障碍,

图5打印出的迷宫矩阵与迷宫图形

4,根据提示输入入口与出口

图6输入入口与出口

5,回车后输出路径

图7打印出的迷宫路径

6,输入一个非“0”继续

图8输入非“0”继续走该迷宫

7,输入入口与出口,无通路

图9无通路

八、参考文献

[1]王昆仑,李红.《数据结构与算法.》北京:

中国铁道出版社,2007年6月。

附录:

源代码:

#include"iostream"

#include"stdio.h"

#include"time.h"

#include"malloc.h"

#defineM20

#defineN20

typedefstructnode//堆栈结构

{

introw;//行

intcol;//列

structnode*next;

}Mlink;

Mlink*stack;//定义一个栈

intbackup[M+2][N+2];//备份数组

/*********************************建立迷宫矩阵**************************/

 

voidcreate(intmaze[][N+2])//建立迷宫

{

inti,j,flag;

srand((unsigned)time(NULL));//以时间产生随机种子

for(i=0;i<=M+1;i++)

for(j=0;j<=N+1;j++)

maze[i][j]=1;//将四周置为1

for(i=1;i<=M;i++)

for(j=1;j<=N;j++)

{

maze[i][j]=0;//初始化矩阵

backup[i][j]=0;//初始化备份矩阵

}

printf("建立迷宫矩阵(选择1或者2):

\n1,手动建立\n2,自动建立\n请输入您的选择:

\n");

scanf("%d",&flag);

if(flag==1)//手动建立迷宫

{

printf("手动建立迷宫矩阵(0表示可通1表示障碍):

\n");

for(i=1;i<=M;i++)

for(j=1;j<=N;j++)

scanf("%d",&maze[i][j]);

}

 

if(flag==2){//自动建立迷宫

intc,i1,j1;

for(c=1;c<=M*N;c++){//矩阵初始为“0”,随机选择位置赋予一个随机的0或1,

i1=(int)(rand()%M)+1;

j1=(int)(rand()%N)+1;

maze[i1][j1]=int(rand()%2);//随机矩阵按照王教授的要求这样可以产生更多的“0”即通路

}

printf("自动生成中……\n");

system("pause");

}

for(i=1;i<=M;i++)

for(j=1;j<=N;j++)

backup[i][j]=maze[i][j];//备份数组矩阵

}

/***************************华丽的分割线*******************************/

 

/********************************打印迷宫矩阵*****************/

voidprin(intmaze[][N+2])

{

inti,j;

printf("迷宫矩阵如下(0可通):

\n");

intz;

for(z=1;z<=N;z++)//在矩阵上方标明列号

{if(z<10)

printf("%d",z);

else

printf("%d",z);

}

for(i=1;i<=M;i++)

{

printf("\n");

if(i<10)printf("%d",i);//矩阵左方标明行号

elseprintf("%d",i);

for(j=1;j<=N;j++)

printf("%d",maze[i][j]);

}

printf("\n迷宫图形如下(白色可通):

\n");

printf("");

for(z=1;z<=N;z++)//在图形上方标明列号

{if(z<10)

printf("%d",z);

else

printf("%d",z);

}

for(i=1;i<=M;i++)

{

printf("\n");

if(i<10)printf("%d",i);//矩阵左方标明行号

elseprintf("%d",i);

for(j=1;j<=N;j++)

{

if(maze[i][j]==0)printf("□");

if(maze[i][j]==1)printf("■");

}

}

}

/*******************************分割线***************************/

 

intMazepath(intmaze[][N+2],intx1,intx2,inty1,inty2)

{

Mlink*p;

if(maze[x1][y1]==0){

p=(Mlink*)malloc(sizeof(Mlink));

p->row=x1;

p->col=y1;

p->next=NULL;

stack=p;//将入口放入堆栈

maze[stack->row][stack->col]=1;//标志入口已访问

while((!

(stack->row==NULL&&stack->col==NULL))&&(!

(stack->row==x2&&stack->col==y2)))//未找到出口并且堆栈不空

{

if(maze[stack->row][stack->col+1]==0)//下面位置可通

{

p=(Mlink*)malloc(sizeof(Mlink));

p->row=stack->row;

p->col=stack->col+1;

p->next=stack;//入栈

stack=p;

maze[stack->row][stack->col]=1;//标记已访问

}

elseif(maze[stack->row][stack->col-1]==0)//上面可通

{

p=(Mlink*)malloc(sizeof(Mlink));

p->row=stack->row;

p->col=stack->col-1;

p->next=stack;//入栈

stack=p;

maze[stack->row][stack->col]=1;//标记已访问

}

elseif(maze[stack->row+1][stack->col]==0)//右面可通

{

p=(Mlink*)malloc(sizeof(Mlink));

p->row=stack->row+1;

p->col=stack->col;

p->next=stack;//入栈

stack=p;

maze[stack->row][stack->col]=1;//标记已访问

}

elseif(maze[stack->row-1][stack->col]==0)//左面可通

{

p=(Mlink*)malloc(sizeof(Mlink));

p->row=stack->row-1;

p->col=stack->col;

p->next=stack;//入栈

stack=p;

maze[stack->row][stack->col]=1;//标记已访问

}

else//不可通返回上一点

{

if(stack->next!

=NULL){//堆栈里布置一个顶点则出栈并返回循环

p=stack;

stack=stack->next;//出栈

free(p);//释放空间

}

else//堆栈里只有一个顶点即入口,此时若释放空间出栈会使循环

{//控制语句无法比较(因为stack->col,stack->row都已不存在,)

stack->row=NULL;

stack->col=NULL;

stack->next=NULL;}

}

}

if(stack->row==x2&&stack->col==y2)return

(1);

elsereturn(0);

}

elsereturn(0);

}

/****************************输出坐标通路*******************/

voidprintonglu1()

{

Mlink*q;

printf("其中的一条通道为:

\n");

q=stack;

printf("出口<--");

while(q!

=NULL)

{

printf("(%d%3d)<--",q->row,q->col);

q=q->next;

}

printf("入口\n");

}

/*******************************分割线**********************/

 

/**********************输出图形通路**************************/

//2时输出↑,3时输出←,4时输出→,5时输出↓

voidprintonglu2()

{

printf("图形通路如下:

\n");

intz;

printf("");

for(z=1;z<=N;z++)//图形上方标明列号

{if(z<10)

printf("%d",z);

else

printf("%d",z);

}

inti,j;

Mlink*p;

p=stack;

backup[p->row][p->col]=6;

while(p->next!

=NULL)

{

if(p->next->col!

=NULL)

{

if(p->row>p->next->row)backup[p->next->row][p->next->col]=5;//下一节点在下

elseif(p->rownext->row)backup[p->next->row][p->next->col]=2;//下一节点在上

elseif(p->col>p->next->col)backup[p->next->row][p->next->col]=4;//下一节点在右

elsebackup[p->next->row][p-

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1