数据结构课程设计 迷宫问题.docx

上传人:b****4 文档编号:12378241 上传时间:2023-04-18 格式:DOCX 页数:26 大小:225.05KB
下载 相关 举报
数据结构课程设计 迷宫问题.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

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

课程设计(论文)任务书

软件学院软件工程+电子商务2009专业2班

一、课程设计(论文)题目迷宫问题

二、课程设计(论文)工作自2010年12月27日起至2011年1月2日止

三、课程设计(论文)地点:

创新大楼实训中心

四、课程设计(论文)内容要求:

1.本课程设计的目的

(1)巩固和加深对数据结构基本知识的理解,提高综合运用课程知识的能力。

(2)使学生掌握软件设计的基本内容和设计方法,并培养学生进行规范化软

件设计的能力。

(3)使学生掌握使用各种计算机资料和有关参考资料,提高学生进行程序设

计的基本能力。

2.课程设计的任务及要求

1)基本要求:

(1)对系统进行功能模块分析、控制模块分析;

(2)系统设计要能完成题目所要求的功能;

(3)编程简练,可用,尽可能的使系统的功能更加完善和全面;

(4)说明书、流程图要清楚;

(5)提高学生的论文写作能力;

(6)特别要求自己独立完成;

2)创新要求:

在基本要求达到后,可进行创新设计,如改善算法性能、友好的人机界面。

3)课程设计论文编写要求

(1)要按照书稿的规格打印与写课程设计论文

(2)论文包括目录、正文、小结、参考文献、附录等

(3)课程设计论文装订按学校的统一要求完成

 

4)课程设计进度安排

内容天数地点

构思及收集资料1图书馆

编码与调试3实验室

撰写论文1图书馆、实验室

学生签名:

20011年1月3日

课程设计(论文)评审意见

(1)基本算法(20分):

优( )、良( )、中( )、一般( )、差( );

(2)设计分析 (20分):

优( )、良( )、中( )、一般( )、差( );

(3)调试分析 (20分):

优( )、良( )、中( )、一般( )、差( );

(4)论文内容 (20分):

优( )、良( )、中( )、一般( )、差( );

(5)答辩分析 (20分):

优( )、良( )、中( )、一般( )、差( );

(6)格式规范性及考勤是否降等级:

是()、否( )

评阅人:

职称:

讲师

2011年1月4日

目录

一、需求分析1

二、概要设计2

三、详细设计5

四、调试分析及测试15

五、个人工作及创新18

六、小结19

参考文献20

一、需求分析

1.选题理由

本次课设我选择了迷宫问题,迷宫求解是数据结构课程的一个经典问题,

迷宫问题要求寻找一条从入口到出口的路径。

通常用的是“穷举求解”的方法。

为了保证在任何位置上都能原路退回,显然需要用一个后进先出的结构来保存从入口到当前位置的路径。

因此,在求解迷宫通路的算法中要应用“栈”的思想。

对于栈的内容在整个学期的学习中我也有了一定的了解,所以选择了迷宫这一经典问题作为本次课设的内容。

2.基本原理分析

迷宫问题通常是用“穷举求解”方法解决,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前走;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。

假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。

栈是一个后进先出的结构,可以用来保存从入口到当前位置的路径。

以二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。

为处理方便起见,在迷宫的四周加一圈障碍。

对于迷宫任何一个位置,均约定东、南、西、北四个方向可通。

3.功能要求

(1)以一个二维数组Maze[m+2][n+2]表示迷宫,其中:

Maze[0][j]和Maze[m+1][j](0<=j<=n+1)及Maze[i][0]和Maze[i][n+1](0<=i<=m+1)为做外层的一圈障碍。

数组中以0表示通路,1表示障碍,限定迷宫的大小为:

m,n<=10。

(2)用户需用文件的形式输入迷宫的数据:

文件中第一行的数据为迷宫的行数m和列数n;从第2行至第m+1行(每行n个数)为迷宫值,用0,1输入,同行中的两个数字之间用空白字符相隔。

(3)迷宫的入口位置和出口位置可由用户随时设定。

(4)若设定的迷宫存在通路,则以长方阵形式将迷宫及其通路输出到标准输出文件上,其中字符“#”表示障碍,“*”表示路径,“@”表示曾途经该位置但不能到达出口,其余位置用空格符表示。

若设定迷宫不存在通路则报告相应信息

(5)本程序只求出一条成功的通路。

(6)程序执行的命令为:

1,创建迷宫;2,求解迷宫;3,输出迷宫的解。

二、概要设计

1、数据结构及其抽象数据类型的定义。

(1)栈的抽象数据类型

ADTStack{

数据对象:

D={ai|ai∈CharSet,i=1,2…n,n>=0}

数据关系:

R1={|ai-1,ai∈D,i=2,…n}

基本操作:

InitStack(&S)

操作结果:

构造一个空栈S。

DestroyStack(&S)

初始条件:

栈S已存在。

操作结果:

销毁栈S。

ClearStack(&S)

初始条件:

栈S已存在。

操作结果:

将S清为空栈。

StackLength(S)

初始条件:

栈S已存在。

操作结果:

返回栈S的长度。

StackEmpty(S)

初始条件:

栈S已存在。

操作结果:

若S为空栈,则返回TRUE,否则返回FALSE。

GetTop(S,&e)

初始条件:

栈S已存在。

操作结果:

若栈S不空,则以e返回栈顶元素。

Push(&S,e)

初始条件:

栈S已存在。

操作结果:

在栈S的栈顶插入新的栈顶元素e。

Pop(&S,&e)

初始条件:

栈S已存在。

操作结果:

删除S的栈顶元素,并以e返回其值。

StackTraverse(S,visit())

初始条件:

栈S已存在。

操作结果:

从栈底到栈顶依次对S中的每个元素调用函数visit()。

}ADTStack

 

(2)迷宫的抽象数据类型

ADTmaze{

数据对象:

D={ai,j|ai,j∈{'','#','@','*'},0<=i<=m+1,0<=j<=n+1,m,n<=10}

数据关系:

R={ROW,COL}

基本操作:

InitMaze(&M,a,row,col)

初始条件:

二维数组a[row+2][col+2]已存在,其中自第1行至第row+1行,每行中自第1列至第col+1列的元素已有值,并且以值0表示通路,以值1表示障碍。

操作结果:

构成迷宫的字符型数组,以空白字符表示通路,以字符‘#’表示障碍,并在迷宫四周加上一圈障碍。

MazePath(&M)

初始条件:

迷宫M已被赋值。

操作结果:

若迷宫M中存在一条通路,则按以下规定改变迷宫M的状态:

以字符’*’表示路径上的位置,字符‘@’表示“死胡同”,否则迷宫的状态不变。

PrintMaze(M)

初始条件:

迷宫M已存在。

操作结果:

以字符形式输出迷宫。

}ADTmaze

 

2、整体框架

本程序包含三个模块

(1)栈模块——实现栈抽象数据类型

(2)迷宫模块——实现迷宫抽象数据类型

(3)主程序模块:

voidmian()

{

  初始化;

 Do{

接受命令;

处理命令;

}while(命令!

=“退出”);

}

 

各模块之间的调用关系如图一:

图一:

调用关系图

函数的调用关系图反映了程序的层次结构如图二:

图二:

函数的调用关系图

 

三、详细设计

源程序:

#include

#include

#include

#defineMAXLEN10//迷宫包括外墙最大行列数目

#defineTRUE1

#defineFALSE0

#defineOK1

#defineERROR0

 

typedefintStatus;

//坐标位置类型 

typedefstruct{

   intr,c;

}PosType;//迷宫中r行c列的位置

//迷宫类型 

typedefstruct{

    intr;

    intc;

    chararr[MAXLEN][MAXLEN];//可取'','*','@','#'

}MazeType;  

 

typedefstruct{

//intstep;//当前位置在路径上的“序号”

  PosTypeseat;//当前的坐标位置

  intdi;//往下一坐标位置的方向

}SElemType;

 //结点类型

typedefstructNodeType{

  SElemTypedata;

  NodeType*next;

}NodeType,*LinkType;

//栈类型 

typedefstruct{

  LinkTypetop;

  intstacksize;

}SqStack;

 

PosTypestart;

PosTypeend;

MazeTypemaze;

boolfound;

 

//创建栈

StatusInitStack(SqStack&S)

{

  S.top=(LinkType)malloc(sizeof(NodeType));

  S.top->next=NULL;

  S.stacksize=0;

  returnOK;

}

 

//进栈

StatusPush(SqStack&S,SElemType&e)

{

  LinkTypep;

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

  p->data=e;

  p->next=S.top;

  S.top=p;

  S.stacksize++;

  returnOK;

}

 

//判断是否为栈空

StatusStackEmpty(SqStackS)

{

  if(S.top->next==NULL)returnOK;

  returnERROR;

}

 

//出栈

StatusPop(SqStack&S,SElemType&e)

{

  LinkTypep;

  if(StackEmpty(S))returnERROR;

  p=S.top;

  e=p->data;

  S.top=S.top->next;

  S.stacksize--;

  free(p);

  returnOK;

}

 

//销毁栈

StatusDestroyStack(SqStack&S)

{

  LinkTypep;

  while(S.top!

=NULL)

  {

     p=S.top;

     S.top=S.top->next;

     free(p);

  }//一个一个删除

  if(S.top==NULL)returnOK;

  elsereturnERROR;

}

 

//曾走过但不是通路标记并返回OK

StatusMarkPrint(MazeType&maze,PosTypecurpos)

{

 maze.arr[curpos.r][curpos.c]='@';//"@"表示曾走过但不通

 returnOK;

}

 

//曾走过而且是通路标记并返回OK

StatusFootPrint(MazeType&maze,PosTypecurpos)

{

 maze.arr[curpos.r][curpos.c]='*';//"*"表示可通

 returnOK;

}

 

//选择下一步的方向

PosTypeNextPos(PosType&curpos,inti)

{

  PosTypecpos;

  cpos=curpos;

  switch(i){       //1.2.3.4分别表示东,南,西,北方向

     case1:

cpos.c+=1;

        break;

     case2:

cpos.r+=1;

        break;

     case3:

cpos.c-=1;

        break;

     case4:

cpos.r-=1;

        break;

}

returncpos;

}

 

//判断当前位置是否可通

StatusPass(MazeType&maze,PosTypecurpos)

{

   if(maze.arr[curpos.r][curpos.c]=='')returnTRUE;

     elsereturnFALSE;

}

 

//创建迷宫

//按照用户输入的二维数组(0或1),设置迷宫maze的初值,包括加上边缘一圈的值

voidInitMaze(MazeType&maze,chara[MAXLEN][MAXLEN],introw,intcol)

{

  maze.r=row;

  maze.c=col;

  for(inti=0;i<=col+1;i++){

     a[0][i]='1';

     a[row+1][i]='1';

  }

  for(i=0;i<=row+1;i++){

     a[i][0]='1';

     a[i][col+1]='1';

  }

  for(i=0;i<=maze.r+2;i++){

     for(intj=0;j

       if(a[i][j]=='1')maze.arr[i][j]='#';

       elsemaze.arr[i][j]='';

    }

  }

}

 

//求迷宫路径的伪码算法:

StatusMazePath(MazeType&maze,PosTypestart,PosTypeend)

{

//求解迷宫maze中,从入口start到出口end的一条路径,若存在,返回TRUE,否则返回FALSE

  PosTypecurpos;

  SqStackS;

  SElemTypee;

  InitStack(S);

  curpos=start;//设定“当前位置”为“入口位置”

 //curstep=1;//探索第一步

  found=false;

do{

  if(Pass(maze,curpos))

  {

   //当前位置可以通过,即是未曾走到过的通道块留下足迹

  FootPrint(maze,curpos);//做可以通过的标识

//e.step=curstep;

  e.seat=curpos;  

  e.di=1;         //为栈顶元素赋值

 

  Push(S,e);//加入路径

  if(curpos.r==end.r&&curpos.c==end.c)found=true;//如果到达终点返回true

    else{

         curpos=NextPos(curpos,1);//下一位置是当前位置的东邻

    }

  }

 else  //当前位置不能通过

    if(!

StackEmpty(S)){

        Pop(S,e);

        while(e.di==4&&!

StackEmpty(S)){

           MarkPrint(maze,e.seat); //留下不能通过的标记

           Pop(S,e);

        }

       if(e.di<4){

         e.di++;  //换下个方向

         Push(S,e);                      //

         curpos=NextPos(e.seat,e.di);    //进行探索

       }

     }

}while(!

StackEmpty(S)&&!

found);

DestroyStack(S);

returnfound;

}

 

//将标记路径信息的迷宫(字符型方阵)输出到终端(包括外墙)

voidPrintMaze(MazeType&maze)

{

   for(inti=0;i<=maze.r+2;i++){

     for(intj=0;j<=maze.c+2;j++){

 printf(" %c",maze.arr[i][j]);//输出迷宫        

    }

   printf("\n");

   }

}

 

//系统初始化

voidInitialization()

{

system("cls");

printf("    welcometothegame!

!

!

      ");

printf("\n************************************************");

printf("\n*创建迷宫--c执行迷宫--m 输出迷宫--p 退出--q*");

printf("\n************************************************");

printf("\n\n   操作:

-");

}

 

//读入操作命令符,显示提示信息

voidReadCommand(char&cmd)

{

 do{

  if(cmd=='c')

  {

   printf("\n******************************************");

   printf("\n*选择操作:

执行迷宫--m    *");

   printf("\n*退出--:

q          *");

   printf("\n******************************************");

   printf("\n\n 操作:

-");

  }

  elseif(cmd=='m'){

   printf("\n******************************************");

   printf("\n*选择操作:

输出迷宫--p         *");

   printf("\n* 退出--:

q      *");

   printf("\n******************************************");

   printf("\n\n操作:

-");

  }

   elseif(cmd=='p'){

   printf("\n******************************************");

   printf("\n*选择操作:

执行迷宫--c         *");

   printf("\n*         退出--:

q      *");

   printf("\n******************************************");

   printf("\n\n         操作:

-");

  }

 cmd=getchar();

}while(!

(cmd=='c'||cmd=='m'||cmd=='p'||cmd=='q'));

}

 

//解释cmd--具体执行

voidInterpre(charcmd)

{

switch(cmd){

case'c':

{

  intrnum,cnum,i=0,m=1,n=1;

  chara2[MAXLEN][MAXLEN];

  charinput[1];

  chardata[1000];

  printf("\n请输入迷宫数据文件名!

\n");

  scanf("%s",input);

  FILE*fp;

  fp=fopen(input,"r");

  if(!

fp)

  {

   printf("\n不能打开文件\n");

   break;

  }

while(!

feof(fp))

  {

   fscanf(fp,"%s",&data[i]);

   if(i==0)

   {

       rnum=(int)data[i]-(int)'0';

   }

   if(i==1)

   {

       cnum=(int)data[i]-(int)'0';

   }

   if(i>=2)

   {

    if(n>cnum){m++;n=1;}

    a2[m][n]=data[i];

    n++;

   }

   i++;

  }

  fclose(fp);

InitMaze(maze,a2,rnum,cnum);

  printf("\n迷宫建立完成!

\n");

  break;

   }

case'm':

{

  printf("\n请输入迷宫入口的坐标,以空格为间隔:

--");

  scanf("%d%d",&start.r,&start.c);

  printf("\n请输入迷宫出口的坐标,以空格为间隔:

--");

  scanf("%d%d",&end.r,&end.c);

  MazePath(maze,start,end);

  break;

   }

case'p':

{

  if(found)

  {

   printf("\n求解迷宫的结果如下--\n");

   PrintMaze(maze);

  }

  elseprintf("\n找不到路径!

\n");

        }

}

}

 

voidmain()

{

charcmd;

Initialization();

do{

  ReadCommand(cmd);   //读入一个操作符命令

  Interpre(cmd);      //解释执行命令操作符

}while(cmd!

='q');

}

 

四、调试分析及测试

1、调试分析:

(1)本程序有一个核心算法,即求迷宫的路径,在调试的时候,出现了两个问题:

没有想到要用‘@’记号,导致迷宫走不出来;没有设置‘found’,不知何时跳出。

(2)原本栈的元素e中除了di—往下一坐标位置的方向和seat—当前的坐标位置,还有一个step—当前位置在路径上的序号,后来发现step没什么用

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

当前位置:首页 > PPT模板 > 商务科技

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

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