数据结构C语言版 递归求解迷宫问题

合集下载

数据结构(C语言版)实验报告(迷宫)

数据结构(C语言版)实验报告(迷宫)

《数据结构与算法》实验报告评分依据及结果一、需求分析1.问题描述:以一个m*n的长方阵表示迷宫,空格和感叹号分别表示迷宫中的通路和障碍。

设计一个程序,对随机产生的迷宫,求一条从入口到出口的通路,或得出没有通路的结论。

2.基本要求首先实现一个以链表为存储结构的栈类型,然后编写一个求解迷宫的非递归程序。

求得的通路以三元组(i,j,d)的形式输出。

其中(i,j)表示迷宫的一个坐标,d表示走到下一座标的方向。

3.程序的执行命令有:1)输入迷宫的列数2)输入迷宫的行数二、概要设计为实现上述功能,需要以一个链表为存储结构的栈类型1.栈的顺序存储表示typedef struct{int x; /*列*/int y; /*行*/}PosType; //坐标位置类型typedef struct{int ord; //通道块在路径上的"序号"PosType seat; //通道块在迷宫中的"坐标位置"int di; //从此通道块走向下一通道块的"方向"}SElemType; //栈的元素类型typedef struct{SElemType *base;SElemType *top;int stacksize; //当前已分配的存储空间,以元素为单位}SqStack;//迷宫程序typedef struct{int lie; /*列数*/int hang; /*行数*/char a[999][999];}MazeType; /*迷宫类型*/2.基本操作int InitStack(SqStack *S)//分配空间int GetTop(SqStack *S,SElemType *e) //若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORint Push(SqStack *S,SElemType *e)//插入元素e作为新的栈顶元素int Pop(SqStack *S,SElemType *e) //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERRORint generatemaze( MazeType *maze)// 随机生成迷宫int Pass(MazeType *maze, PosType curpos ) //判断当前位置可否通过int FootPrint(MazeType *maze,PosType curpos) //留下足迹int MarkPrint(MazeType *maze,PosType curpos) //留下不能通过的标记PosType NextPos(PosType curpos,int di) //返回当前位置的下一位置int MazePath(MazeType *maze,PosType start,PosType end) //若迷宫有解,则求得一条存放在栈中(从栈底到栈顶),并返回OK,否则返回ERROR void PrintMaze(MazeType *maze) //打印迷宫三、详细设计//程序的头文件#include <stdio.h>#include <malloc.h>#include <stdlib.h>#include <string.h>#include <time.h>//函数的返回值#define OK 1#define ERROR 0#define NULL 0#define OVERFLOW -2#define STACK_INIT_SIZE 100#define STACKINCREMENT 10//栈的顺序存储表示typedef struct{int x; /*列*/int y; /*行*/}PosType; //坐标位置类型typedef struct{int ord; //通道块在路径上的"序号"PosType seat; //通道块在迷宫中的"坐标位置"int di; //从此通道块走向下一通道块的"方向"}SElemType; //栈的元素类型typedef struct{SElemType *base;SElemType *top;int stacksize; //当前已分配的存储空间,以元素为单位}SqStack;//基本操作int 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;}//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORint GetTop(SqStack *S,SElemType *e){if(S->top==S->base)return ERROR;*e=*(S->top-1);return OK;}int Push(SqStack *S,SElemType *e)//插入元素e作为新的栈顶元素{if(S->top-S->base>=S->stacksize)/*栈满,追加存储空间*/{S->base=(SElemType*)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(SElemType));if(!S->base)exit(OVERFLOW);S->top=S->base+S->stacksize;S->stacksize+=STACKINCREMENT;}*S->top++=*e;return OK;}//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERRORint Pop(SqStack *S,SElemType *e){if(S->top==S->base)return ERROR;*e=*--S->top;return OK;}int StackEmpty(SqStack *S){return(S->top==S->base);}//迷宫程序typedef struct{int lie; /*列数*/int hang; /*行数*/char a[999][999];}MazeType; /*迷宫类型*//*随机生成迷宫*/int generatemaze( MazeType *maze){int i,j;maze->a[0][0]=2;maze->a[++maze->hang][++maze->lie]=3; /*设置外墙*/maze->a[0][maze->lie]='!';maze->a[maze->hang][0]='!';for(j=1;j<maze->lie;j++){maze->a[0][j]='!';maze->a[maze->hang][j]='!';}for(i=1;i<maze->hang;i++){maze->a[i][0]='!';maze->a[i][maze->lie]='!';}srand((unsigned)time( NULL ));rand();for(i=1; i <maze->hang; i++)for(j=1;j<maze->lie;j++){if (rand()>=RAND_MAX/4) maze->a[i][j] =' '; //' ' 暗示出路else maze->a[i][j] ='!'; //'!'暗示无出路}return OK;}int Pass(MazeType *maze, PosType curpos ) //判断当前位置可否通过{if ((curpos.x < 1) || (curpos.x >= maze->lie))return ERROR;if ((curpos.y < 1) || (curpos.y >= maze->hang))return ERROR;if (maze->a[curpos.y][curpos.x]==' ')return OK;else return ERROR;}int FootPrint(MazeType *maze,PosType curpos) //留下足迹{maze->a[curpos.y][curpos.x]='*';return OK;}int MarkPrint(MazeType *maze,PosType curpos) //留下不能通过的标记{maze->a[curpos.y][curpos.x]='@';return OK;}PosType NextPos(PosType curpos,int di)//返回当前位置的下一位置{PosType pos=curpos;switch(di){case 1: //右东pos.x++;break;case 2: //下南pos.y++;break;case 3: //左西pos.x--;break;case 4: //上北pos.y--;break;}return pos;}//若迷宫有解,则求得一条存放在栈中(从栈底到栈顶),并返回OK,否则返回ERROR int MazePath(MazeType *maze,PosType start,PosType end){PosType curpos;SqStack *S=(SqStack *)malloc(sizeof(SqStack));InitStack(S);SElemType *e;e=(SElemType *)malloc(sizeof(SElemType));curpos=start; //设定当前位置为入口位置int curstep = 1; //探索第一步do {if(Pass(maze,curpos)) //当前位置可通过{FootPrint(maze,curpos);e->ord=curstep;e->seat=curpos;e->di=1;Push(S,e);if(curpos.x==end.x&&curpos.y==end.y)return (OK);curpos=NextPos(curpos,1);curstep++;}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=e->seat;curpos=NextPos(curpos,e->di);}}}}while(!StackEmpty(S));return ERROR;}void PrintMaze(MazeType *maze) //打印迷宫{int i,j,k,n;int c[999],d[999];for(i=0,k=0;i<=maze->hang;i++){for(j=0;j<=maze->lie;j++){printf("%c ",maze->a[i][j]);if(maze->a[i][j]=='*'){c[k]=i;d[k]=j;k++;}}printf("\n");}n=k;for(k=0;k<n;k++)printf("<%d,%d>",c[k],d[k]);printf("\n");printf("\n");}int main(){int zmg;char ch;printf(" 数据结构课程设计--迷宫问题求解\n\n");printf(" |----------------------------------------|\n");printf(" | |\n");printf(" | |\n");printf(" | |\n");printf(" | |\n");printf(" | XXXX XXXXXXXXXXXXXX |\n");printf(" | XXXXXXX |\n");printf(" |----------------------------------------|\n");getchar();do{system("cls");fflush(stdin);MazeType *maze=(MazeType *)malloc(sizeof(MazeType)); //设置迷宫的长宽不含外墙printf("请输入迷宫的列数(不含外墙时):");scanf("%d",&maze->lie);printf("请输入迷宫的行数(不含外墙时):");scanf("%d",&maze->hang);generatemaze(maze);printf("随机创建迷宫\n");PrintMaze(maze);getchar();getchar();PosType start,end;start.x=1;start.y=1;end.x=maze->lie-1;end.y=maze->hang-1;zmg=MazePath(maze,start,end);if(zmg){printf("此迷宫通路为\n");PrintMaze(maze);}elseprintf("此迷宫无通路\n"); //getchar();printf("再次尝试?(Y/N)?");scanf("%c",&ch);}while(ch=='Y'||ch=='y');return 0;}四、调试分析1.本程序界面设计合理,以空格为通路,感叹号!为障碍,笑脸为起始点,*为行走路线,心形为出口设计精巧,便于用户使用。

用C语言解决迷宫问题

用C语言解决迷宫问题

⽤C语⾔解决迷宫问题#include <stdio.h>#include <stdlib.h>#define ROW 10#define COL 10/*迷宫中位置信息*/typedef struct position{int x;int y;}position;/*在迷宫中的当前位置的信息,也是⼊栈的基本元素*/typedef struct SElem{int di;position seat;}SElem;/*链式栈中节点的定义*/typedef struct position_stack{SElem p;struct position_stack *next;}*Stack_pNode,Stack_Node;void InitStack(Stack_pNode *Link){*Link = NULL;}void push(Stack_pNode *Link,SElem e){Stack_pNode new_SElem = (Stack_pNode)calloc(1,sizeof(Stack_Node));new_SElem->p = e;new_SElem->next = NULL;if (*Link == NULL)*Link = new_SElem;else{new_SElem->next = *Link;*Link = new_SElem;}}int pop(Stack_pNode *Link,SElem *e){if (*Link == NULL)return 0;*e = (*Link)->p;Stack_pNode q = *Link;*Link = (*Link)->next;free(q);return 1;}int top(Stack_pNode Link, SElem *e){if (Link == NULL)return 0;*e = Link->p;return 1;}int empty(Stack_pNode Link){if (Link == NULL)return 1;elsereturn 0;}int reverse(Stack_pNode *Link){Stack_pNode p, q, r;if (*Link == NULL || (*Link)->next == NULL)return 0;r = *Link;p = (*Link)->next;q = NULL;while (p){r->next = q;q = r;r = p;p = p->next;}r->next = q;*Link = r;}void print(Stack_pNode Link){Stack_pNode r = Link;while (r){printf("(%d,%d) -> ",r->p.seat.x,r->p.seat.y);r = r->next;}printf("exit\n");}int curstep = 1;/*纪录当前的⾜迹,填写在探索前进的每⼀步正确的路上*//*迷宫地图。

C语言实现数据结构迷宫实验

C语言实现数据结构迷宫实验

C语⾔实现数据结构迷宫实验本⽂实例为⼤家分享了C语⾔实现简单的数据结构迷宫实验,供⼤家参考,具体内容如下分析:迷宫实验主要有两部分操作,其⼀是对迷宫的⽣成,其⼆是寻路使⽤栈的操作。

步骤:⼀、.h⽂件1、⾸先是迷宫的⽣成,可以使⽤随机数种⼦⽣成,但主要逻辑部分并不在此,所以在这⾥直接写死,固定下来。

定义⼀个坐标类型的结构体,和⼆维数组迷宫:typedef struct {int x;int y;}Pos;//迷宫类型typedef struct {int square[10][10] ={{1,1,1,1,1,1,1,1,1,1},{1,0,0,0,0,0,0,0,0,1},{1,1,1,1,0,1,1,1,0,1},{1,0,0,0,0,1,0,1,0,1},{1,0,1,1,1,1,0,1,1,1},{1,0,0,0,0,1,0,0,0,1},{1,0,1,1,0,0,0,1,0,1},{1,0,1,1,1,0,1,1,1,1},{1,0,0,0,1,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1},};}Maze;typedef Pos SElemType;2、然后是对栈的声明,栈⾥储存的元素为坐标类型//顺序栈#define MAXSIZE 50typedef struct {SElemType *base;SElemType *top; //栈顶指针int stacksize;}SqStack;3、栈操作函数声明typedef int Status;#define OK 1;#define ERROR 0;//栈的相关操作//初始化栈Status initStack(SqStack &s);//压栈Status push(SqStack &s, SElemType e);//出栈SElemType pop(SqStack &s);//清空栈Status clearStack(SqStack &s);//摧毁栈void destroyStack(SqStack &s);//遍历栈Status stackTravel(SqStack s);4、迷宫操作函数声明//初始化迷宫(同时⽣成起始点和终点)void initMaze(Maze &maze);//寻找出路;传⼊⼀个迷宫和栈找出出路void findWay(Maze &maze,SqStack &s);//判断该点的四个⽅向是否有通路,有就前进Pos isExit(Pos p, Maze maze);⼆、.cpp⽂件1、导⼊所需头⽂件#include "pch.h"#include <iostream>#include<time.h>#include<stdlib.h>using namespace std;2、栈操作实现//构造空栈Status initStack(SqStack &s) {s.base = new SElemType[MAXSIZE];if (!s.base){exit(OVERFLOW);//分配失败}s.top = s.base;s.stacksize = MAXSIZE;return OK;}//⼊栈Status push(SqStack &s, SElemType e) {//判断栈满if (s.top-s.base == s.stacksize){return ERROR;}//存⼊元素,*为取指针的值s.top++;*s.top = e;return OK;}//出栈,⽤e返回栈顶值SElemType pop(SqStack &s) {SElemType e;//判断栈为空if (s.top == s.base){//若为空则返回⼀个(-1,-1)的点,判断由外部调⽤时进⾏ e.x = -1;e.y = -1;return e;}e = *s.top;s.top--;return e;}Status clearStack(SqStack &s) {s.top = s.base;return OK;}void destroyStack(SqStack &s) {s.top = NULL;s.stacksize = 0;free(s.base);}Status stackTravel(SqStack s) {while (s.top != s.base){s.base++;Pos p = *s.base;if ( p.x == 0 || p.y == 0|| p.x == 9 ||p.y == 9){//终点输出为“End”cout << "End";}}cout << endl;return 0;}3、迷宫操作实现///////////////////////////////////////迷宫操作//////////////////////////////////初始化函数,传⼊⼀个迷宫,随机⽣成起点和终点,由于起点有⼀定限制,所以这⾥起点也固定为⼏个最合适的点void initMaze(Maze &maze) {//⽣成随机数srand((unsigned)time(NULL));int index = rand() % 36 + 1;int start = index % 6 + 1;//⽣成起始点数值为‘s'switch (start){case 1:maze.square[1][1] = 's';break;case 2:maze.square[3][8] = 's';break;case 3:maze.square[3][6] = 's';break;case 4:maze.square[6][8] = 's';break;case 5:maze.square[8][3] = 's';break;case 6:maze.square[8][8] = 's';break;}//随机⽣成终点'e'表⽰while (index = rand()%36+1){//出⼝在顶部if (index >1 &&index<10 && maze.square[1][index-1]!='s'){maze.square[0][index-1] = 'e';break;}//出⼝在右侧else if (index>10 &&index <19){if (maze.square[index-10][8] != 1 && maze.square[index-10][8]!='s') {maze.square[index-10][9] = 'e';break;}}//底部出⼝else if (index >19&&index<28){if (maze.square[8][index - 19] != 's' && maze.square[8][index - 19] != 1) {maze.square[9][index - 19] = 'e';break;}}//左侧出⼝else if (index >28 && index <=36){if (maze.square[index-28][1] != 1 &&maze.square[index-28][1] != 's'){maze.square[index - 28][0] = 'e';break;}}}void showMaze(Maze maze) {for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){if (maze.square[i][j] == 1){cout << "* ";}else if (maze.square[i][j] == 0){cout << " ";}else{cout << (char)maze.square[i][j]<<" ";}}cout << endl;}}//寻找迷宫路径void findWay(Maze &maze,SqStack &s) {//⾸先遍历找出起始点和终点并保存下来Pos start,end;for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++) {if (maze.square[i][j] == 's'){ //起点压⼊栈内start.x = i;start.y = j;push(s, start);}else if (maze.square[i][j] == 'e'){ //出⼝end.x = i;end.y = j;}}}//寻找路径Pos go = start;//直到找到出⼝才结束while ( s.top->x != end.x || s.top->y != end.y){//获得下⼀步坐标Pos path = isExit(go, maze);if (path.x != go.x || path.y != go.y){//前进maze.square[path.x][path.y] = 'p';push(s, path);go = path;}//如果所有放向都⾛不通(即返回的点是传⼊的点),则将其标为“@”,出栈到上⼀个点,继续判断else{//⾛不通popmaze.square[path.x][path.y] = '@';pop(s);go = *s.top;}}maze.square[end.x][end.y] = 'e';}//判断返回下⼀步路径(顺序:右下左上),传⼊所处位置,从右边开始判断是否⼜通路或者出⼝,有就返回哪个⽅向上的点Pos isExit(Pos p,Maze maze) {Pos tempP = p;if (maze.square[tempP.x][tempP.y+1] == 0 || maze.square[tempP.x][tempP.y + 1] == 'e'){tempP.y++;else if(maze.square[tempP.x+1][tempP.y] == 0 || maze.square[tempP.x +1][tempP.y] == 'e'){tempP.x++;}else if (maze.square[tempP.x][tempP.y - 1] == 0 || maze.square[tempP.x][tempP.y - 1] == 'e'){tempP.y--;}else if (maze.square[tempP.x - 1][tempP.y] == 0 || maze.square[tempP.x - 1][tempP.y] == 'e'){tempP.x--;}return tempP;}三、main函数调⽤int main(){while (true){//创建⼀个迷宫Maze maze;initMaze(maze);//初始化⼀个栈SqStack S;initStack(S);cout << "*****************************" << endl;cout << "* 1、⽣成迷宫 2、退出 *" << endl;cout << "*****************************" << endl;cout << "请输⼊你的选择:";int select = 0;cin >> select;if (select == 1){cout << "⽣成随机起点和出⼝迷宫:" << endl;showMaze(maze);cout << "⽣成迷宫路径:" << endl;findWay(maze, S);stackTravel(S);showMaze(maze);cout << endl;}if (select == 2){clearStack(S);break;}}return 0;}四、评价这是个叫简易的迷宫,但基本实现了迷宫的寻路逻辑,可改进的地⽅有:1、因为很多地⽅写死了,所以复⽤性不⾼,可以⽤循环遍历来随机⽣成起点,同理迷宫的⽣成也是这样2、判断路径可以⽤递归调⽤实现前进逻辑以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

C语言递归实现迷宫寻路问题

C语言递归实现迷宫寻路问题

C语⾔递归实现迷宫寻路问题迷宫问题采⽤递归和⾮递归两种⽅法,暂时完成递归⽅法,后续会补上⾮递归⽅法#include<stdio.h>#include<stdbool.h>bool findPath(int a[][8],int i,int j){//递归找出⼝if(i==6&&j==6)//如果找到了⽬标a[6][6]则返回truereturn true;if(a[i][j]==0)//若当前路径未被找到,则继续{a[i][j]=2;//当前⾛的路径置为2,表⽰⾛过if(findPath(a,i+1,j)||findPath(a,i,j+1)||findPath(a,i-1, j)||findPath(a,i-1,j))//每个⽅向都判断,依次展开递归,寻找最佳路径return true;//若选择的路径可以⾛,则返回trueelse{//若当前选择的路径不能⾛a[i][j]=0;//弹栈并恢复路径,回退到上⼀次的位置return false;}}else//未能找到最终点return false;}void print(int a[][8])//打印当前的⼆维数组表{for(int i=0;i<8;i++){for(int j=0;j<8;j++){printf("%d ",a[i][j]);}printf("\n");}}int main(){int a[8][8]={0};for(int i=0;i<8;i++)//设置围墙和障碍物{a[0][i]=1;a[i][0]=1;a[7][i]=1;a[i][7]=1;}a[3][1]=1;a[3][2]=1;print(a);printf("-----------after find path-----------\n");findPath(a, 1, 1);print(a);}。

数据结构迷宫算法实现c语言

数据结构迷宫算法实现c语言

数据结构迷宫算法实现c语⾔迷宫问题求解是⼀个⾮常经典的算法问题,该问题要求程序能根据⽤户的输⼊的长和宽去初始化迷宫,接着给⽤户提供两个选择,⽤户可以选择在迷宫⾥⼿动或⾃动⽣成指定个数的障碍,接着程序会⾃动找到⼀条能够从⼊⼝⾛到出⼝的路径,并且输出该路径下⾯开始分析,因为迷宫是由多个点组成的,那么要实现上述功能,我们可以定义⼀个结构体去存放每个点的横纵坐标去表⽰位置,还需要⽤到⼀个⼆维数组去存放迷宫,在迷宫⾥有三种状态,0代表通路,1代表障碍,2代表已经⾛过的路,那么可以将指定的值⼀⼀赋给数组中每个元素,迷宫⾥的点是需要⽤坐标去表⽰的,那么为了⽅便,可以将⼆维数组下标(横坐标或纵坐标)为0的点(及迷宫的外围)都设置为1(障碍),为了防⽌找路时⾛出去,⾛过的路(⾛过的每个坐标)需要⽤到⼀个栈去存放每个点,栈其实就是⼀段内存,有两个指针⼀开始都指向数组的头地址(也能理解为栈底),接着随着数据的存放,栈顶指针会跟着存放的数据移动,栈底指针不变,那么根据这两个指针就可以随时确定栈顶元素的位置和栈的状态(空或满),因为栈这种特殊的数据结构可以保证后进⼊的数据先出来,所以栈在迷宫找路是可以模拟出⾛过的每⼀步以及遇到障碍时往后退的上⼀步位置(也就是后进⼊的栈顶元素),所以可以创建⼀个栈,⾥⾯的指针类型为定义的结构体类型2.详细设计⾸先根据⽤户输⼊的长和宽m和n⽤new去开辟⼤⼩为m+2(算上围墙)⼤⼩的内存,在m+2的基础上再⽤new开放n+2(算上围墙)⼤⼩的内存,就开辟了⼆维数组空间,返回的值(数组的地址)⽤⼀个⼆重指针去存放:具体代码如下(该函数在function.h)int **initmaze(int &m,int &n)//⽤0或1输⼊代表迷宫,0代表通路{cout << "请输⼊迷宫的长和宽" << endl;cout << "长度:";cin >> m;cout << "宽度:";cin >> n;cout << "请创建迷宫,0代表通路,1代表此路不通" << endl;int **maze = new int *[n + 2];//⽤new,避免缓冲区溢出for (int i = 0; i <= n + 1; i++)//创建迷宫储存空间,为迷宫设置障碍{maze[i] = new int[m+2];//长度加2,为迷宫周围设置障碍}for (int i = 0; i <= n + 1; i++){maze[i][0] = maze[i][m + 1] = 1;//为每⼀⾏的第⼀个和最后⼀个元素初始化为1,为迷宫的障碍}for (int i = 0; i <= m + 1; i++){maze[0][i] = maze[n + 1][i] = 1;//为每⼀列的第⼀个和最后⼀个元素初始化值为1,为迷宫障碍}for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){maze[i][j]=0;}}return maze;}在stack.h这个头⽂件定义栈这种数据结构,定义结构体position⽤来存放迷宫⾥点的坐标,代码如下:struct position{int row;//⾏偏移int col;//列偏移};//定义⼀个结构体,⽤来存放位置坐标typedef position selemtype;typedef struct//定义栈结构为结构体栈,⽤来存放迷宫中某⼀点的横纵坐标{selemtype *top;//栈顶指针selemtype *base;//栈底指针int stacksize;}sqstack;定义initstack函数初始化栈,具体操作⽤new开辟⼀段内存,将这段内存的⾸地址赋值给top和base(两个指向position结构体类型的指针)⽤来表⽰存放路径的栈:bool initstack(sqstack &s)//顺序栈的初始化{s.base = new selemtype[MAXSIZE];//为顺序栈分配空间if (!s.base) return 0;//储存分配失败s.top = s.base;s.stacksize = MAXSIZE;return 1;}定义⼀些函数去对栈进⾏操作该函数将⾛过的点存放到栈⾥⾯,将栈顶指针重新向上移⼀位,指向栈顶元素bool push(sqstack &s, selemtype e)//插⼊元素e为栈顶元素{if (s.top - s.base == s.stacksize) exit(0);//空间已满,分配失败*s.top = e;//将值赋给栈顶指针s.top++;//栈顶指针向上移1位return 1;}该函数删除栈顶元素,即将栈顶指针向下移⼀位(在迷宫⾥表⽰遇到障碍退路):bool pop(sqstack &s, selemtype &e)//删除栈顶元素{if (empty(s)) return 0;//栈为空,不能删除e = *(s.top-1);//将栈顶指针减⼀,将栈顶元素赋给es.top--;return 1;}该函数取得栈顶元素,及取回top指针指向的元素(在迷宫⾥表⽰退到上⼀位置,因为栈顶元素就是对应上⼀步)该函数判断栈是否为满,根据指针位置判断bool full(sqstack &s)//判断栈是否满了{if (s.top - s.base == 0)return 0;else return 1;}该函数判断栈是否为空,根据指针位置判断bool empty(sqstack &s)//判断栈是否为空{if (s.base == s.top)return 1;else return 0;}该函数输出栈中元素,表⽰输出迷宫从⼊⼝到出⼝的路径void stackprint(sqstack s)//输出栈中元素{selemtype *q;for (q = s.base; q !=s.top; q++){cout << "("<<q->row << "," <<q->col<<")"<< endl;}}以上对栈的操作都放⼊stack.h头⽂件中上述实现了迷宫需要⽤到的⼀些数据类型和数据结构接下来分析如何实现迷宫问题⽐如以下是⼀个迷宫,长和宽为4,旁边代表围墙,⼊⼝为(1,1),⾸先要⽣成障碍,有两个选择,⼿动和⾃动⽣成,其实没区别,只需要把障碍对应的坐标设置为1即可,⾃动就是在指定的长宽内去⽣成随机数,⼀下为⾃动和⼿动的代码实现int **randmaze(int **p, int &m, int &n)//随机产⽣障碍{time_t t=time(0);srand(t);int num, x, y;cout << "请输⼊障碍物的个数"<<endl;cin >> num;cout << "ok,正在为你⽣出障碍物....请稍等" << endl;for (int i = 0; i < num; i++){x = rand() % m;//⽣成的随机数在指定迷宫长度的范围内,不包括出⼝y = rand() % n;//⽣成随机数在指定迷宫宽度的范围内p[x][y] = 1;//设置障碍}return p;}int **inputmaze(int **p, int &m, int &n)//⼿动输⼊障碍{int num, x, y;cout << "请输⼊设置障碍物的个数" << endl;cin >> num;cout << "请输⼊障碍物的位置,⾏和列" << endl;for (int i = 0; i < num; i++){cout << "⾏:";cin >> x;cout << "列:";cin >> y;while ((x<=1 || x >=n) && (y <= 1 || y >=m))//出⼝⼊⼝均不能有障碍{cout << "输⼊不在范围内" << endl;cout << "⾏:";cin >> x;cout << "列:";cin >> y;}p[x][y] = 1;}return p;}设置好障碍后就开始找路,每个点都有四个选择,及向上下左右,那么可以⽤结构体去存放相应的偏移量,⽐如右偏移为⾏为0,列偏移为1position offset[4];//结构体数组,存放位置偏移量offset[0].row = 0; offset[0].col = 1;//右偏移offset[1].row = 1; offset[1].col = 0;//下偏移offset[2].row = 0; offset[2].col = -1;//左偏移offset[3].row = -1; offset[3].col = 0;//上偏移这个顺序是有要求的先向右尝试,然后是下,再左,最后上假设⽣成的障碍为如下所⽰先从⼊⼝(1,1)当前位置向右尝试,不⾏(右为1障碍),于是向下(可以,因为下个位置为0),⾛到(2,1),将(1,1)设为2(表⽰来过,防⽌再次⾛),然后将(1,1)存⼊栈,接着(2,2)⼜有4种尝试,先向右(右(2,2)为0,所以可以⾛)于是将(1,2)设为2表⽰⾛过并存⼊栈中,接着到(2,2),先向右尝试,(2,3)为1,遇到障碍,再向下尝试,还是障碍,接着上和左都不⾏,于是只能后退了,于是将上个位置(1,2)从栈中弹出来,将上个位置变成当前位置,接着因为(1,2)已经向右尝试过了不⾏,于是要从下(结构体下标为1offset[1].row = 1; offset[1].col = 0;//下偏移)开始尝试,向下可以,于是到(1,3),将(1,2)压⼊栈,下⾯都是按照上⾯讲的⼀⼀去尝试,直到⾛到出⼝,接着将栈输出即可,该找路部分实现代码如下bool findpath(int **p,int &m,int &n,sqstack &path)//sqstack为存放路径的结构体栈{initstack(path);position offset[4];//结构体数组,存放位置偏移量offset[0].row = 0; offset[0].col = 1;//右偏移offset[1].row = 1; offset[1].col = 0;//下偏移offset[2].row = 0; offset[2].col = -1;//左偏移offset[3].row = -1; offset[3].col = 0;//上偏移position here;//⽤来存放位置here.row = here.col = 1;p[1][1] = 2;//⼊⼝设为2,防⽌在回来int option = 0;//移动⽅向,根据移动⽅向进⾏不同的偏移int lastoption = 3;while (here.row != n||here.col != m)//没到出⼝{int r, c;while (option <= lastoption)//依次⾛⼏个⽅向{r = here.row + offset[option].row;c = here.col + offset[option].col;if (p[r][c] == 0) break;//如果有通路,则跳出option++;//否则尝试下⼀个⽅向}if (option <= lastoption)//如果找到⽅向{push(path, here);//将⽅向压⼊结构体栈here.row = r;here.col = c;p[r][c] = 2;//将该点改为2,表⽰来过option = 0;//重新设置为0,进⾏下⼀次寻路}else{position next;if (empty(path)){return false;}next = gettop(path);//取栈顶元素,及前⼀点坐标pop(path, next);//将栈顶弹出if (here.row == next.row)//如果当前位置和上⼀位置⾏相等,说明他们在列上移{if (here.col > next.col){option = 1;}else{option = 3;}//option = 2 + next.col - here.col;//下⼀个移动位置}else{if (here.row > next.row){option = 2;}else{return false;}//option = 3 + next.row - here.row;//如果当前位置和上⼀位置列相同,说明当前位置是从⾏上移过来的}here = next;//把栈顶元素(上⼀位置坐标赋给当前位置,表⽰退回来)}}return true;}具体代码在此贴出#ifndef _STACK0_#define_STACK0_#define MAXSIZE 100struct position{int row;//⾏偏移int col;//列偏移};//定义⼀个结构体,⽤来存放位置坐标typedef position selemtype;typedef struct//定义栈结构为结构体栈,⽤来存放迷宫中某⼀点的横纵坐标{selemtype *top;//栈顶指针selemtype *base;//栈底指针int stacksize;}sqstack;bool full(sqstack &s)//判断栈是否满了{if (s.top - s.base == 0)return 0;else return 1;}bool empty(sqstack &s)//判断栈是否为空{if (s.base == s.top)return 1;else return 0;}bool initstack(sqstack &s)//顺序栈的初始化{s.base = new selemtype[MAXSIZE];//为顺序栈分配空间if (!s.base) return 0;//储存分配失败s.top = s.base;s.stacksize = MAXSIZE;return 1;}bool push(sqstack &s, selemtype e)//插⼊元素e为栈顶元素{if (s.top - s.base == s.stacksize) exit(0);//空间已满,分配失败*s.top = e;//将值赋给栈顶指针s.top++;//栈顶指针向上移1位return 1;}bool pop(sqstack &s, selemtype &e)//删除栈顶元素{if (empty(s)) return 0;//栈为空,不能删除e = *(s.top-1);//将栈顶指针减⼀,将栈顶元素赋给es.top--;return 1;}selemtype gettop(sqstack s)//获取栈顶元素的值{if (s.top == s.base) exit(0);//e=*(s.top - 1);//取栈顶元素return *(s.top-1);}void stackprint(sqstack s)//输出栈中元素{selemtype *q;for (q = s.base; q !=s.top; q++){cout << "("<<q->row << "," <<q->col<<")"<< endl;}}#endif;#ifndef _FUNCTION0_#define_FUNCTION0_#include<iomanip>#include<cstdlib>//⽤来⽣成随机数#include<ctime>#include"stack.h"void welcome(){cout << "初始化迷宫......" << endl;}int **initmaze(int &m,int &n)//⽤0或1输⼊代表迷宫,0代表通路{cout << "请输⼊迷宫的长和宽" << endl;cout << "长度:";cin >> m;cout << "宽度:";cin >> n;cout << "请创建迷宫,0代表通路,1代表此路不通" << endl;int **maze = new int *[n + 2];//⽤new,避免缓冲区溢出for (int i = 0; i <= n + 1; i++)//创建迷宫储存空间,为迷宫设置障碍{maze[i] = new int[m+2];//长度加2,为迷宫周围设置障碍}for (int i = 0; i <= n + 1; i++){maze[i][0] = maze[i][m + 1] = 1;//为每⼀⾏的第⼀个和最后⼀个元素初始化为1,为迷宫的障碍}for (int i = 0; i <= m + 1; i++){maze[0][i] = maze[n + 1][i] = 1;//为每⼀列的第⼀个和最后⼀个元素初始化值为1,为迷宫障碍}for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){maze[i][j]=0;}}return maze;}int **randmaze(int **p, int &m, int &n)//随机产⽣障碍{time_t t=time(0);srand(t);int num, x, y;cout << "请输⼊障碍物的个数"<<endl;cin >> num;cout << "ok,正在为你⽣出障碍物....请稍等" << endl;for (int i = 0; i < num; i++){x = rand() % m;//⽣成的随机数在指定迷宫长度的范围内,不包括出⼝y = rand() % n;//⽣成随机数在指定迷宫宽度的范围内p[x][y] = 1;//设置障碍}return p;}int **inputmaze(int **p, int &m, int &n)//⼿动输⼊障碍{int num, x, y;cout << "请输⼊设置障碍物的个数" << endl;cin >> num;cout << "请输⼊障碍物的位置,⾏和列" << endl;for (int i = 0; i < num; i++){cout << "⾏:";cout << "列:";cin >> y;while ((x<=1 || x >=n) && (y <= 1 || y >=m))//出⼝⼊⼝均不能有障碍{cout << "输⼊不在范围内" << endl;cout << "⾏:";cin >> x;cout << "列:";cin >> y;}p[x][y] = 1;}return p;}void printmaze(int **p,int m,int n){for (int i = 0; i <= n + 1; i++){for (int j = 0; j <= m + 1; j++){if (p[i][j] == 1){cout << setw(2) <<"□";}if (p[i][j] == 2){cout << setw(2) << "○";}if (p[i][j] == 0){cout << setw(2) << "";}}cout << endl;}}void delmaze(int **p, int m, int n)//销毁迷宫{for (int i = 0; i <= n + 1; i++){delete[] p[i];}}bool findpath(int **p,int &m,int &n,sqstack &path)//sqstack为存放路径的结构体栈{initstack(path);position offset[4];//结构体数组,存放位置偏移量offset[0].row = 0; offset[0].col = 1;//右偏移offset[1].row = 1; offset[1].col = 0;//下偏移offset[2].row = 0; offset[2].col = -1;//左偏移offset[3].row = -1; offset[3].col = 0;//上偏移position here;//⽤来存放位置here.row = here.col = 1;p[1][1] = 2;//⼊⼝设为2,防⽌在回来int option = 0;//移动⽅向,根据移动⽅向进⾏不同的偏移int lastoption = 3;while (here.row != n||here.col != m)//没到出⼝{int r, c;while (option <= lastoption)//依次⾛⼏个⽅向{r = here.row + offset[option].row;c = here.col + offset[option].col;if (p[r][c] == 0) break;//如果有通路,则跳出option++;//否则尝试下⼀个⽅向}if (option <= lastoption)//如果找到⽅向{push(path, here);//将⽅向压⼊结构体栈here.row = r;here.col = c;p[r][c] = 2;//将该点改为2,表⽰来过option = 0;//重新设置为0,进⾏下⼀次寻路}else{position next;if (empty(path)){return false;}next = gettop(path);//取栈顶元素,及前⼀点坐标pop(path, next);//将栈顶弹出if (here.row == next.row)//如果当前位置和上⼀位置⾏相等,说明他们在列上移{if (here.col > next.col){option = 1;}else{option = 3;}//option = 2 + next.col - here.col;//下⼀个移动位置}else{if (here.row > next.row){option = 2;}else{return false;}//option = 3 + next.row - here.row;//如果当前位置和上⼀位置列相同,说明当前位置是从⾏上移过来的}here = next;//把栈顶元素(上⼀位置坐标赋给当前位置,表⽰退回来)}}return true;}#endif;#include<iostream>using namespace std;#include"function.h"int main(){int m, n,t;int **maze;sqstack path;//⽤来存放路径welcome();maze=initmaze(m,n);//初始化函数printmaze(maze,m,n);//输出初始化的迷宫cout << "选择1⾃动⽣成障碍" << endl;cout << "选择2⼿动创建障碍" << endl;cin >> t;while (t != 1 && t != 2){cout << "输⼊错误,请重输" << endl;cin >> t;}switch (t){case 1:maze = randmaze(maze, m, n); break; case 2:maze = inputmaze(maze, m, n); break; }cout << "迷宫如下"<<endl;printmaze(maze,m,n);cout << "正在寻找路径" << endl;if (findpath(maze, m, n,path)){stackprint(path);}else{cout << "没有找到路径" << endl;}printmaze(maze,m,n);delmaze(maze, m, n);//销毁迷宫,释放内存return 0;}。

数据结构之迷宫问题求解(一)利用栈与递归求解出口

数据结构之迷宫问题求解(一)利用栈与递归求解出口

数据结构之迷宫问题求解(⼀)利⽤栈与递归求解出⼝ 本⽂适合于对迷宫问题已有初步研究,或阅读代码能⼒较强的⼈. 因此,如果你对迷宫问题⼀⽆所知,请参考其他更详细的资料. 迷宫问题,是⼀个对栈(Stack)典型应⽤的例⼦之⼀. 假如,有如下10X10的迷宫(0代表通路,1代表障碍),我们需要⽤写程序来找出迷宫的出⼝.1 1 1 1 1 1 1 1 1 11 1 1 0 1 1 1 0 1 10 0 0 0 1 0 0 0 1 11 1 0 1 1 0 1 0 0 11 1 0 1 0 0 1 0 1 11 1 0 1 1 1 1 0 0 11 1 0 0 0 0 0 0 1 11 1 0 1 0 1 1 0 1 11 1 0 1 0 1 1 0 1 11 1 1 1 1 1 1 0 1 1那么,我们可以通过两种⽅式完成.⽅式⼀:通过利⽤栈FILO(First In Last Out)的特性核⼼代码/**函数说明:通过栈来进⾏迷宫求解*参数说明:* Maze:迷宫地图数组* sz:迷宫⼤⼩* entry:迷宫⼊⼝点* path:⽤于寻找迷宫出⼝的栈*返回值:找到出⼝返回true,没找到返回false.*/bool FindMazePath(int *Maze,size_t sz,Pos &entry,stack<Pos>& path){//将⼊⼝压栈path.push(entry);//如果栈不为空while(!path.empty()){//获取栈顶元素,即上⼀次⾛的路径Pos cur = path.top();//将其标记为已⾛过Maze[cur.x*sz+cur.y] = 3;//找到出⼝if(sz-1==cur.x){return true;}Pos next = cur;//下⼀步,向右移动next.x += 1;if(CheckIsAccess(Maze,sz,next)){//可以向右移动,将当前步⼊栈path.push(next);continue;}next = cur;//下⼀步,向左移动next.x -= 1;if(CheckIsAccess(Maze,sz,next)){//可以向左移动,⼊栈path.push(next);continue;}//下⼀步,向上移动next = cur;next.y += 1;if(CheckIsAccess(Maze,sz,next)){//可以向上移动path.push(next);continue;}next = cur;//向下移动next.y -= 1;if(CheckIsAccess(Maze,sz,next)){//可以向下移动path.push(next);continue;}//上、下、左、右都不能⾛path.pop();}return false;}⽅式⼆:通过递归核⼼代码/**函数说明:根据递归寻找迷宫出⼝*参数说明* Maze:迷宫地图* sz:迷宫⼤⼩* entry:迷宫⼊⼝* path:⽤来判断是否存在出⼝的栈*返回值:⽆(如果存在出⼝,栈为空;如果不存在出⼝,栈中存在起点坐标)*/void FindMazePathR(int *Maze,size_t sz,Pos &entry,stack<Pos> & path){//将⼊⼝压栈path.push(entry);Pos cur = entry;//将已⾛过的路标记为3Maze[cur.x*sz+cur.y] = 3;//找到出⼝,直接返回if(sz-1==entry.x){//将起点坐标弹出path.pop();return ;}Pos next = cur;//右next.x += 1;if(CheckIsAccess(Maze,sz,next)){//以当前位置为起点,递归进⾏下⼀步FindMazePathR(Maze,sz,next,path);}next = cur;//左next.x -= 1;if(CheckIsAccess(Maze,sz,next)){FindMazePathR(Maze,sz,next,path);}//上next = cur;next.y += 1;if(CheckIsAccess(Maze,sz,next)){FindMazePathR(Maze,sz,next,path);}//下next = cur;next.y -= 1;if(CheckIsAccess(Maze,sz,next)){FindMazePathR(Maze,sz,next,path);}path.pop();}最后,附上整个程序的完整代码(代码量较少,声明与实现我就不分⽂件了)迷宫问题求解完整代码//相关函数的声明与实现#ifndef __MAZE_H__#define __MAZE_H__#include<iostream>#include<iomanip>#include<stack>#include<assert.h>namespace Maze{using namespace std;//迷宫⼤⼩static const int N = 10;//迷宫地图⽂件名static const char *const FILENAME = "MazeMap.txt";//坐标struct Pos{int x; //横坐标(本质是数组arr[i][j]的j)int y; //纵坐标(本质是数组arr[i][j]的i)};/*函数说明:从⽂件中获取迷宫地图参数说明:Maze:迷宫地图数组sz:迷宫⼤⼩返回值:⽆*/void GetMaze(int *Maze,size_t sz){FILE *fp = fopen(FILENAME,"r");//打开失败if(NULL==fp){//输出错误信息perror(FILENAME);//结束程序exit(1);}//将⽂件中的迷宫地图读⼊Maze数组内for(size_t i=0; i<sz; ++i){for(size_t j=0; j<sz;){//从⽂件流中获取字符char tmp = getc(fp);//字符为0或为1时,导⼊数组if(tmp=='0'||tmp=='1'){Maze[i*sz+j]=tmp -'0';++j;}else if(EOF==tmp){//⽂件已读完,循环还未停⽌//说明此处⽂件中的迷宫地图存在问题assert(false);return ;}}}//关闭⽂件fclose(fp);}/*函数说明:打印迷宫参数说明:Maze:迷宫地图数组sz:迷宫⼤⼩返回值:⽆*/void PrintMaze(int *Maze,size_t sz){cout<<setw(2);for(size_t i=0; i<sz; ++i){for(size_t j=0; j<sz; ++j){cout<<Maze[i*sz+j]<<setw(2);}cout<<endl;}}/*函数说明:检测当前位置是否可以通过参数说明:Maze:迷宫地图数组sz:迷宫⼤⼩cur:当前所在位置返回值:可以通过返回true,不能通过返回false.*/bool CheckIsAccess(int *Maze,size_t sz,Pos cur){if(cur.x>=0 && cur.x<sz && //⾏坐标是否越界cur.y>=0 && cur.y<sz && //列坐标是否越界Maze[cur.x*sz+cur.y]==0 ){ //所在⾏列是否可以通过return true;}return false;}/*函数说明:通过栈来进⾏迷宫求解参数说明:Maze:迷宫地图数组sz:迷宫⼤⼩entry:迷宫⼊⼝点path:⽤于寻找迷宫出⼝的栈返回值:找到出⼝返回true,没找到返回false.*/bool FindMazePath(int *Maze,size_t sz,Pos &entry,stack<Pos>& path){ //将⼊⼝压栈path.push(entry);//如果栈不为空while(!path.empty()){//获取栈顶元素,即上⼀次⾛的路径Pos cur = path.top();//将其标记为已⾛过Maze[cur.x*sz+cur.y] = 3;//找到出⼝if(sz-1==cur.x){return true;}Pos next = cur;//下⼀步,向右移动next.x += 1;if(CheckIsAccess(Maze,sz,next)){//可以向右移动,将当前步⼊栈path.push(next);continue;}next = cur;//下⼀步,向左移动next.x -= 1;if(CheckIsAccess(Maze,sz,next)){//可以向左移动,⼊栈path.push(next);continue;}//下⼀步,向上移动next = cur;next.y += 1;if(CheckIsAccess(Maze,sz,next)){//可以向上移动path.push(next);continue;}next = cur;//向下移动next.y -= 1;if(CheckIsAccess(Maze,sz,next)){//可以向下移动path.push(next);continue;}//上、下、左、右都不能⾛path.pop();}return false;}/**函数说明:根据递归寻找迷宫出⼝*参数说明* Maze:迷宫地图* sz:迷宫⼤⼩* entry:迷宫⼊⼝* path:⽤来判断是否存在出⼝的栈*返回值:⽆(如果存在出⼝,栈为空;如果不存在出⼝,栈中存在起点坐标)*/void FindMazePathR(int *Maze,size_t sz,Pos &entry,stack<Pos> & path){ //将⼊⼝压栈path.push(entry);Pos cur = entry;//将已⾛过的路标记为3Maze[cur.x*sz+cur.y] = 3;//找到出⼝,直接返回if(sz-1==entry.x){//将起点坐标弹出path.pop();return ;}Pos next = cur;//右next.x += 1;if(CheckIsAccess(Maze,sz,next)){//以当前位置为起点,递归进⾏下⼀步FindMazePathR(Maze,sz,next,path);}next = cur;//左next.x -= 1;if(CheckIsAccess(Maze,sz,next)){FindMazePathR(Maze,sz,next,path);}//上next = cur;next.y += 1;if(CheckIsAccess(Maze,sz,next)){FindMazePathR(Maze,sz,next,path);}//下next = cur;next.y -= 1;if(CheckIsAccess(Maze,sz,next)){FindMazePathR(Maze,sz,next,path);}path.pop();}}#endif迷宫求解测试代码#include"Maze.h"using namespace Maze;void MazeTest(){int arr[N][N]; //迷宫地图Pos entry = {2,0}; //起点坐标stack<Pos> path; //栈GetMaze((int *)arr,N); //将⽂件中迷宫导⼊到arr数组中PrintMaze((int *)arr,N);//打印迷宫FindMazePath((int *)arr,N,entry,path);//找迷宫出⼝cout<<endl<<endl; //换⾏处理(使界⾯更整齐)PrintMaze((int *)arr,N);//打印⾛过的迷宫}int main(){MazeTest();return 0;}总结: 1.利⽤栈去寻找迷宫出⼝,栈内最终会保存从⼊⼝到出⼝的所有路径. 2.利⽤递归去寻找迷宫出⼝,传进去的栈仅仅只是⽤来判断迷宫是否有出⼝, 3.利⽤递归去寻找出⼝时,因为递归的特性,将会遍历完迷宫内的所有路径. 最后,还有⼀个问题:如果⼀个迷宫存在多条路径可以到达出⼝,那么如何得到迷宫到出⼝的最短路径 有机会的话,我将会在下篇⽂章讨论此事.。

C语言解决迷宫求解问题

C语言解决迷宫求解问题
0110000110100111001011000迷宫的路径为括号内的内容分别表示为行坐标列坐标数字化方向即方向方向111212221321422431532542550迷宫路径探索成功
迷宫求解
任务:
可以输入一个任意大小的迷宫数据,用非递归的方法求出一条走出迷宫的路
径,并将路径输出。
#include<iostream>
//获取栈顶元素
if(!(p.GetPop().x==q.GetPop().x&&p.GetPop().y==q.GetPop().y))
p.Push(Temp2);
//如果有新位置入栈,则把上一个探索的位置存入栈 p
for(loop=0;loop<4;loop++) //探索当前位置的 4 个相邻位置
//使栈顶元素出栈
T GetPop();
//取出栈顶元素
void Clear();
//把栈清空
bool empty();
//判断栈是否为空,如果为空则返回 1,否则返回 0
};
Stack::Stack()
//构造函数,置空栈
{
top=NULL;
}
Stack::~Stack()
//析构函数
{
}
void Stack::Push(T e)
//输出路径
{
cout<<"迷宫的路径为\n";
cout<<"括号内的内容分别表示为(行坐标,列坐标,数字化方向,方向)\n";
Stack t;
//定义一个栈,按从入口到出口存取路径
int a,b;
T data;

c语言课程设计迷宫问题

c语言课程设计迷宫问题

c语言课程设计 迷宫问题一、课程目标知识目标:1. 学生能够理解并掌握C语言中的基本语法,如变量定义、数据类型、运算符、控制语句等;2. 学生能够运用数组解决二维迷宫问题,理解数组在存储空间中的应用;3. 学生能够掌握递归算法的基本原理,并将其应用于迷宫问题的解决。

技能目标:1. 学生能够运用C语言编写简单的程序,解决迷宫问题,培养编程解决问题的能力;2. 学生能够通过分析迷宫问题,培养逻辑思维和问题分解能力;3. 学生能够运用所学知识,调试并优化迷宫问题的解决方案。

情感态度价值观目标:1. 学生在解决迷宫问题的过程中,培养面对困难时的耐心和毅力,增强解决问题的信心;2. 学生通过团队协作,学会与他人沟通、分享和合作,培养团队精神;3. 学生能够认识到编程在解决实际问题中的价值,激发对计算机科学的兴趣。

课程性质:本课程为C语言程序设计课程,通过迷宫问题引导学生运用所学知识解决实际问题。

学生特点:学生已具备一定的C语言基础,具有一定的逻辑思维能力和编程能力。

教学要求:教师应引导学生通过实践探索,掌握迷宫问题的解决方法,注重培养学生的编程技能和团队协作能力。

在教学过程中,将目标分解为具体的学习成果,以便进行教学设计和评估。

二、教学内容本课程教学内容紧密围绕课程目标,结合课本相关章节,具体安排如下:1. C语言基础语法回顾:变量定义、数据类型、运算符、控制语句(选择、循环)等,对应教材第1-3章;- 课堂讲解:10分钟;- 实践操作:20分钟。

2. 数组的应用:介绍二维数组在迷宫问题中的应用,对应教材第4章;- 课堂讲解:15分钟;- 实践操作:25分钟。

3. 递归算法:讲解递归的基本概念及其在迷宫问题中的应用,对应教材第6章;- 课堂讲解:20分钟;- 实践操作:30分钟。

4. 迷宫问题解决方案:结合前面所学知识,设计并实现迷宫问题的解决方案;- 课堂讲解:10分钟;- 实践操作:40分钟。

5. 团队协作与项目实践:分组进行迷宫问题的编程实践,培养学生的团队协作能力和编程技能;- 实践操作:2课时。

数据结构(C语言版)实验报告(迷宫)

数据结构(C语言版)实验报告(迷宫)

《数据结构与算法》实验报告评分依据及结果一、需求分析1.问题描述:以一个m*n的长方阵表示迷宫,空格和感叹号分别表示迷宫中的通路和障碍。

设计一个程序,对随机产生的迷宫,求一条从入口到出口的通路,或得出没有通路的结论。

2.基本要求首先实现一个以链表为存储结构的栈类型,然后编写一个求解迷宫的非递归程序。

求得的通路以三元组(i,j,d)的形式输出。

其中(i,j)表示迷宫的一个坐标,d表示走到下一座标的方向。

3.程序的执行命令有:1)输入迷宫的列数2)输入迷宫的行数二、概要设计为实现上述功能,需要以一个链表为存储结构的栈类型1.栈的顺序存储表示typedef struct{int x; /*列*/int y; /*行*/}PosType; //坐标位置类型typedef struct{int ord; //通道块在路径上的"序号"PosType seat; //通道块在迷宫中的"坐标位置"int di; //从此通道块走向下一通道块的"方向"}SElemType; //栈的元素类型typedef struct{SElemType *base;SElemType *top;int stacksize; //当前已分配的存储空间,以元素为单位}SqStack;//迷宫程序typedef struct{int lie; /*列数*/int hang; /*行数*/char a[999][999];}MazeType; /*迷宫类型*/2.基本操作int InitStack(SqStack *S)//分配空间int GetTop(SqStack *S,SElemType *e) //若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORint Push(SqStack *S,SElemType *e)//插入元素e作为新的栈顶元素int Pop(SqStack *S,SElemType *e) //若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERRORint generatemaze( MazeType *maze)// 随机生成迷宫int Pass(MazeType *maze, PosType curpos ) //判断当前位置可否通过int FootPrint(MazeType *maze,PosType curpos) //留下足迹int MarkPrint(MazeType *maze,PosType curpos) //留下不能通过的标记PosType NextPos(PosType curpos,int di) //返回当前位置的下一位置int MazePath(MazeType *maze,PosType start,PosType end) //若迷宫有解,则求得一条存放在栈中(从栈底到栈顶),并返回OK,否则返回ERROR void PrintMaze(MazeType *maze) //打印迷宫三、详细设计//程序的头文件#include <stdio.h>#include <malloc.h>#include <stdlib.h>#include <string.h>#include <time.h>//函数的返回值#define OK 1#define ERROR 0#define NULL 0#define OVERFLOW -2#define STACK_INIT_SIZE 100#define STACKINCREMENT 10//栈的顺序存储表示typedef struct{int x; /*列*/int y; /*行*/}PosType; //坐标位置类型typedef struct{int ord; //通道块在路径上的"序号"PosType seat; //通道块在迷宫中的"坐标位置"int di; //从此通道块走向下一通道块的"方向"}SElemType; //栈的元素类型typedef struct{SElemType *base;SElemType *top;int stacksize; //当前已分配的存储空间,以元素为单位}SqStack;//基本操作int 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;}//若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERRORint GetTop(SqStack *S,SElemType *e){if(S->top==S->base)return ERROR;*e=*(S->top-1);return OK;}int Push(SqStack *S,SElemType *e)//插入元素e作为新的栈顶元素{if(S->top-S->base>=S->stacksize)/*栈满,追加存储空间*/{S->base=(SElemType*)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(SElemType));if(!S->base)exit(OVERFLOW);S->top=S->base+S->stacksize;S->stacksize+=STACKINCREMENT;}*S->top++=*e;return OK;}//若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERRORint Pop(SqStack *S,SElemType *e){if(S->top==S->base)return ERROR;*e=*--S->top;return OK;}int StackEmpty(SqStack *S){return(S->top==S->base);}//迷宫程序typedef struct{int lie; /*列数*/int hang; /*行数*/char a[999][999];}MazeType; /*迷宫类型*//*随机生成迷宫*/int generatemaze( MazeType *maze){int i,j;maze->a[0][0]=2;maze->a[++maze->hang][++maze->lie]=3; /*设置外墙*/maze->a[0][maze->lie]='!';maze->a[maze->hang][0]='!';for(j=1;j<maze->lie;j++){maze->a[0][j]='!';maze->a[maze->hang][j]='!';}for(i=1;i<maze->hang;i++){maze->a[i][0]='!';maze->a[i][maze->lie]='!';}srand((unsigned)time( NULL ));rand();for(i=1; i <maze->hang; i++)for(j=1;j<maze->lie;j++){if (rand()>=RAND_MAX/4) maze->a[i][j] =' '; //' ' 暗示出路else maze->a[i][j] ='!'; //'!'暗示无出路}return OK;}int Pass(MazeType *maze, PosType curpos ) //判断当前位置可否通过{if ((curpos.x < 1) || (curpos.x >= maze->lie))return ERROR;if ((curpos.y < 1) || (curpos.y >= maze->hang))return ERROR;if (maze->a[curpos.y][curpos.x]==' ')return OK;else return ERROR;}int FootPrint(MazeType *maze,PosType curpos) //留下足迹{maze->a[curpos.y][curpos.x]='*';return OK;}int MarkPrint(MazeType *maze,PosType curpos) //留下不能通过的标记{maze->a[curpos.y][curpos.x]='@';return OK;}PosType NextPos(PosType curpos,int di)//返回当前位置的下一位置{PosType pos=curpos;switch(di){case 1: //右东pos.x++;break;case 2: //下南pos.y++;break;case 3: //左西pos.x--;break;case 4: //上北pos.y--;break;}return pos;}//若迷宫有解,则求得一条存放在栈中(从栈底到栈顶),并返回OK,否则返回ERROR int MazePath(MazeType *maze,PosType start,PosType end){PosType curpos;SqStack *S=(SqStack *)malloc(sizeof(SqStack));InitStack(S);SElemType *e;e=(SElemType *)malloc(sizeof(SElemType));curpos=start; //设定当前位置为入口位置int curstep = 1; //探索第一步do {if(Pass(maze,curpos)) //当前位置可通过{FootPrint(maze,curpos);e->ord=curstep;e->seat=curpos;e->di=1;Push(S,e);if(curpos.x==end.x&&curpos.y==end.y)return (OK);curpos=NextPos(curpos,1);curstep++;}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=e->seat;curpos=NextPos(curpos,e->di);}}}}while(!StackEmpty(S));return ERROR;}void PrintMaze(MazeType *maze) //打印迷宫{int i,j,k,n;int c[999],d[999];for(i=0,k=0;i<=maze->hang;i++){for(j=0;j<=maze->lie;j++){printf("%c ",maze->a[i][j]);if(maze->a[i][j]=='*'){c[k]=i;d[k]=j;k++;}}printf("\n");}n=k;for(k=0;k<n;k++)printf("<%d,%d>",c[k],d[k]);printf("\n");printf("\n");}int main(){int zmg;char ch;printf(" 数据结构课程设计--迷宫问题求解\n\n");printf(" |----------------------------------------|\n");printf(" | |\n");printf(" | |\n");printf(" | |\n");printf(" | |\n");printf(" | XXXX XXXXXXXXXXXXXX |\n");printf(" | XXXXXXX |\n");printf(" |----------------------------------------|\n");getchar();do{system("cls");fflush(stdin);MazeType *maze=(MazeType *)malloc(sizeof(MazeType)); //设置迷宫的长宽不含外墙printf("请输入迷宫的列数(不含外墙时):");scanf("%d",&maze->lie);printf("请输入迷宫的行数(不含外墙时):");scanf("%d",&maze->hang);generatemaze(maze);printf("随机创建迷宫\n");PrintMaze(maze);getchar();getchar();PosType start,end;start.x=1;start.y=1;end.x=maze->lie-1;end.y=maze->hang-1;zmg=MazePath(maze,start,end);if(zmg){printf("此迷宫通路为\n");PrintMaze(maze);}elseprintf("此迷宫无通路\n"); //getchar();printf("再次尝试?(Y/N)?");scanf("%c",&ch);}while(ch=='Y'||ch=='y');return 0;}四、调试分析1.本程序界面设计合理,以空格为通路,感叹号!为障碍,笑脸为起始点,*为行走路线,心形为出口设计精巧,便于用户使用。

C语言数据结构之迷宫问题

C语言数据结构之迷宫问题

C语⾔数据结构之迷宫问题本⽂实例为⼤家分享了数据结构c语⾔版迷宫问题栈实现的具体代码,供⼤家参考,具体内容如下程序主要参考⾃严蔚敏⽼师的数据结构c语⾔版,在书中程序的⼤体框架下进⾏了完善。

关于迷宫问题的思路可查阅原书。

#include<iostream>using namespace std;#define MAXSIZE 10typedef int Status;typedef struct{int x;int y;}Postype;typedef struct{int ord;Postype seat;int dir;}SElemType;//栈的元素类型typedef struct{//SElemType data[MAXSIZE];SElemType* top;SElemType* base;}Stack;//栈的结构类型typedef struct{char arr[MAXSIZE][MAXSIZE];}MAZETYPE;//迷宫结构体MAZETYPE maze;void InitMaze(){maze.arr[0][0] = maze.arr[0][1] = maze.arr[0][2] = maze.arr[0][3] = maze.arr[0][4] = maze.arr[0][5] = maze.arr[0][6] = maze.arr[0][7] = maze.arr[0][8] = maze.arr[0][9] = '1'; maze.arr[1][0] = maze.arr[1][3] = maze.arr[1][7] = maze.arr[1][9] = '1';maze.arr[1][1] = maze.arr[1][2] = maze.arr[1][4] = maze.arr[1][5] = maze.arr[1][6] = maze.arr[1][8] = '0';maze.arr[2][0] = maze.arr[2][3] = maze.arr[2][7] = maze.arr[2][9] = '1';maze.arr[2][1] = maze.arr[2][2] = maze.arr[2][4] = maze.arr[2][5] = maze.arr[2][6] = maze.arr[2][8] = '0';maze.arr[3][0] = maze.arr[3][5] = maze.arr[3][6] = maze.arr[3][9] = '1';maze.arr[3][1] = maze.arr[3][2] = maze.arr[3][3] = maze.arr[3][4] = maze.arr[3][7] = maze.arr[3][8] = '0';maze.arr[4][0] = maze.arr[4][2] = maze.arr[4][3] = maze.arr[4][4] = maze.arr[4][9] = '1';maze.arr[4][1] = maze.arr[4][5] = maze.arr[4][6] = maze.arr[4][7] = maze.arr[4][8] = '0';maze.arr[5][0] = maze.arr[5][4] = maze.arr[5][9] = '1';maze.arr[5][1] = maze.arr[5][2] = maze.arr[5][3] = maze.arr[5][5] = maze.arr[5][6] = maze.arr[5][7] = maze.arr[5][8] = '0';maze.arr[6][0] = maze.arr[6][2] = maze.arr[6][6] = maze.arr[6][9] = '1';maze.arr[6][1] = maze.arr[6][3] = maze.arr[6][4] = maze.arr[6][5] = maze.arr[6][7] = maze.arr[6][8] = '0';maze.arr[7][0] = maze.arr[7][2] = maze.arr[7][3] = maze.arr[7][4] = maze.arr[7][6] = maze.arr[7][9] = '1';maze.arr[7][1] = maze.arr[7][5] = maze.arr[7][7] = maze.arr[7][8] = '0';maze.arr[8][0] = maze.arr[8][1] = maze.arr[8][9] = '0';maze.arr[8][2] = maze.arr[8][3] = maze.arr[8][4] = maze.arr[8][5] = maze.arr[8][6] = maze.arr[8][7] = maze.arr[8][8] = '0';maze.arr[9][0] = maze.arr[9][1] = maze.arr[9][2] = maze.arr[9][3] = maze.arr[9][4] = maze.arr[9][5] = maze.arr[9][6] = maze.arr[9][7] = maze.arr[9][8] = maze.arr[9][9] = '1'; }Status initStack(Stack &s){s.base = (SElemType*)malloc(MAXSIZE*sizeof(SElemType));if (!s.base) return 0;s.top = s.base;return 1;}void Push(Stack &s, SElemType e){*s.top++ = e;}void Pop(Stack &s, SElemType &e){e = *--s.top;}Status StackEmpty(Stack &s){if (s.top == s.base) return 1;else return 0;}Status Pass(Postype curpos){if (maze.arr[curpos.x][curpos.y] == '0')return 1;else return 0;}void Foot(Postype curpos){maze.arr[curpos.x][curpos.y] = '*';}void MarkPrint(Postype curpos){maze.arr[curpos.x][curpos.y] = '!';}Status StructCmp(Postype a, Postype b){if (a.x = b.x&&a.y == b.y) return 1;else return 0;}//下⼀个位置Postype NextPos(Postype CurPos, int Dir){Postype ReturnPos;switch (Dir){case 1:ReturnPos.x = CurPos.x;ReturnPos.y = CurPos.y + 1;break;case 2:ReturnPos.x = CurPos.x + 1;ReturnPos.y = CurPos.y;break;case 3:ReturnPos.x = CurPos.x;ReturnPos.y = CurPos.y - 1;break;case 4:ReturnPos.x = CurPos.x - 1;ReturnPos.y = CurPos.y;break;}return ReturnPos;}Status MazePath(Postype start, Postype end) {Stack s;SElemType e;initStack(s);Postype curpos = start;int curstep = 1;do{if (Pass(curpos)){Foot(curpos);e = { curstep, curpos, 1 };Push(s, e);if (StructCmp(curpos, end)) return 1;curpos = NextPos(curpos, 1);curstep++;}else{if (!StackEmpty(s)){Pop(s, e);while (e.dir ==4 &&!StackEmpty(s)){MarkPrint(e.seat); Pop(s, e);}if (e.dir < 4 && !StackEmpty(s)){e.dir++;Push(s, e);curpos = NextPos(e.seat, e.dir);}}}} while (!StackEmpty(s));return 0;}int main(){InitMaze();Postype s, e;s.x = s.y = 1;e.x = e.y = 8;if (MazePath(s, e))printf("迷宫成功解密!\n");elseprintf("解密失败\n");for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){printf("%c ", maze.arr[i][j]);}printf("\n");}cout << "-=================================" << endl;for (int i = 0; i < 10; i++){for (int j = 0; j < 10; j++){if (maze.arr[i][j] == '*' || maze.arr[i][j] == '!')printf("%c ", maze.arr[i][j]);else cout << " ";}printf("\n");}}以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

数据结构C语言版递归求解迷宫问题

数据结构C语言版递归求解迷宫问题

数据结构C语言版_递归求解迷宫问题/*数据结构C语言版递归求解迷宫问题用递归函数求解迷宫问题(求出所有解)编译环境:Dev-C++ 4.9.9.2日期:2011年2月12日*/#include&lt;stdio.h&gt;// 迷宫坐标位置类型struct PosType{int x; // 行值int y; // 列值};#define MAXLENGTH 25 // 设迷宫的最大行列为25typedef int MazeType[MAXLENGTH][MAXLENGTH]; // [行][列]// 全局变量struct PosType end; // 迷宫终点位置MazeType m; // 迷宫数组int x, y; // 迷宫行数,列数// 定义墙元素值为0,可通过路径为-1,通过路径为足迹// 输出解void Print(int x,int y){int i,j;for(i=0;i&lt;x;i++){for(j=0;j&lt;y;j++)printf(&quot;%3d&quot;,m[i][j]);printf(&quot;\n&quot;);}printf(&quot;\n&quot;);}// 由当前位置cur、当前步骤curstep试探下一点void Try(struct PosType cur,int curstep){int i;struct PosType next; // 下一个位置// {行增量,列增量}struct PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};// 移动方向,依次为东南西北for(i=0;i&lt;=3;i++) // 依次试探东南西北四个方向{next.x=cur.x+direc[i].x;next.y=cur.y+direc[i].y;if(m[next.x][next.y] == -1) // 是通路{m[next.x][next.y]=++curstep;if(next.x != end.x || next.y != end.y) // 没到终点Try(next,curstep); // 试探下一点(递归调用)elsePrint(x,y); // 输出结果m[next.x][next.y]=-1; // 恢复为通路,试探下一条路curstep--;}}}// 0为墙,-1为通道int main(){struct PosType begin; //起点int i,j,x1,y1;printf(&quot;请输入迷宫的行数,列数(包括外墙):(空格隔开)&quot;); scanf(&quot;%d%d&quot;,&amp;x,&amp;y);for(i=0;i&lt;x;i++) // 定义周边值为0(同墙){m[0][i]=0; // 迷宫上面行的周边即上边墙m[x-1][i]=0;// 迷宫下面行的周边即下边墙}for(j=1;j&lt;y-1;j++){m[j][0]=0; // 迷宫左边列的周边即左边墙m[j][y-1]=0;// 迷宫右边列的周边即右边墙}for(i=1;i&lt;x-1;i++)for(j=1;j&lt;y-1;j++)m[i][j]=-1; // 定义通道初值为-1printf(&quot;请输入迷宫内墙单元数(即墙的个数):&quot;);scanf(&quot;%d&quot;,&amp;j);if(j)printf(&quot;请依次输入迷宫内墙每个单元的行数,列数:(空格隔开)\n&quot;); for(i=1;i&lt;=j;i++){scanf(&quot;%d%d&quot;,&amp;x1,&amp;y1);m[x1][y1]=0;}printf(&quot;迷宫结构如下:\n&quot;);Print(x,y);printf(&quot;请输入起点的行数,列数:(空格隔开)&quot;);scanf(&quot;%d%d&quot;,&amp;begin.x,&amp;begin.y);printf(&quot;请输入终点的行数,列数:(空格隔开)&quot;);scanf(&quot;%d%d&quot;,&amp;end.x,&amp;end.y);m[begin.x][begin.y]=1;Try(begin,1); // 由第一步起点试探起system(&quot;pause&quot;);return 0;}/*输出效果:请输入迷宫的行数,列数(包括外墙):(空格隔开)4 4请输入迷宫内墙单元数(即墙的个数):1请依次输入迷宫内墙每个单元的行数,列数:(空格隔开)1 2迷宫结构如下:0 00 00 -1 0 00 -1 -1 00 0 0 0请输入起点的行数,列数:(空格隔开)1 1 请输入终点的行数,列数:(空格隔开)2 2 0 0 0 00 1 0 00 2 3 00 0 0 0请按任意键继续. . .*/。

顺序栈和迷宫求解(C语言)

顺序栈和迷宫求解(C语言)

顺序栈和迷宫求解(C语⾔)顺序栈 根据《数据结构》书中的讲解,对顺序栈的⼀个基本实现。

define.h1// define.h2 #ifndef __MENGQL_DEFINE__3#define __MENGQL_DEFINE__45#define C_LOG_DBG(format, ...)6//printf("[%s@%s,%d] " format ,__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);7#define C_LOG_ERR(format, ...) printf("[%s@%s,%d] " format ,__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);8 typedef enum EStatus {ERROR, OK} Status;910#endifSqStack.h1// SqStack.h2 #ifndef __SQ_STACK_H__3#define __SQ_STACK_H__4 #include "define.h"56 typedef struct7 {8int x;9int y;10 }PosType;1112 typedef struct13 {14int ord;15 PosType seat;16int di;17 }SElemType;1819#define STACK_INIT_SIZE 10020 typedef struct21 {22 SElemType* base;23 SElemType* top;24int stacksize;25 }SqStack;2627extern Status InitStack(SqStack *S);28extern Status GetTopStack(SqStack S, SElemType *e);29extern Status PushStack(SqStack *S, SElemType e);30extern Status PopStack(SqStack *S, SElemType *e);31extern Status StackEmpty(SqStack *S);32extern Status DestoryStack(SqStack *S);33#endifSqStack.c1// SqStack.c2 #include "define.h"3 #include "SqStack.h"4 #include <stdlib.h>5 #include <stdio.h>6 Status InitStack(SqStack *S)7 {8 S->stacksize = STACK_INIT_SIZE;9 S->base = (SElemType *)malloc(S->stacksize * sizeof(SElemType));10if(S->base == NULL)11 {12 C_LOG_ERR("%s\n","MALLOC OVERFLOW");13return ERROR;14 }15 S->top = S->base;1617return OK;18 }19 Status GetTopStack(SqStack S, SElemType *e)20 {21if(S.top == S.base)22 {23 C_LOG_ERR("%s\n","STACK IS EMPTY");24return ERROR;25 }26 *e = *(S.top-1);27return OK;28 }29 Status PushStack(SqStack *S, SElemType e)30 {31if(S->top - S->base >= S->stacksize)32 {33 S->base = (SElemType *)realloc(S->base, (S->stacksize * 2) * sizeof(SElemType)); 34if(S->base == NULL)35 {36 C_LOG_ERR("%s\n","REMALLOC OVERFLOW");37return ERROR;38 }39 S->stacksize *= 2;40 }41 *(S->top++) = e;42return OK;43 }44 Status PopStack(SqStack *S, SElemType *e)45 {46if(S->top == S->base)47 {48 C_LOG_ERR("%s\n","STACK IS EMPTY");49return ERROR;50 }51 *e = *(--S->top);52return OK;53 }54 Status StackEmpty(SqStack *S)55 {56if(S->top == S->base)57 {58return OK;59 }60return ERROR;61 }62 Status DestoryStack(SqStack *S)63 {64 S->stacksize = 0;65 free(S->base);66 S->top = S->base = NULL;67return OK;68 }迷宫求解 顺序栈实现的迷宫求解是深度优先搜索,得出的路径是⾮最短路径。

(完整word版)迷宫(C语言版)--数据结构课程设计

(完整word版)迷宫(C语言版)--数据结构课程设计

一.迷宫问题求解1.问题描述迷宫问题是实验心理学的一个经典问题,心理学家把一只老鼠从一个无顶盖的大盒子的入口出赶迷宫。

迷宫中设置了很多隔壁,对前进方向形成了多出障碍,心理学家在迷宫的唯一出口处放置了一块奶酪,吸引老鼠在迷宫中寻找路径以到达出口。

然而,用计机模拟迷宫问题,即划好迷宫的隔壁的设置,让计算机从入口处进入迷宫探究出一条通路。

2.设计思路回溯法是一种不断试探且及时纠正错误的探索方法。

下面的求解过程既是使用回溯法。

从入口出发,按某一个方向向前探索,若能走通并且未走过,即某处可以到达,则到达新点,否则试探下一个方向;若所有的方向均没有通路,则沿原路返回前一个点,换下一个方向继续探索,直到找到一条通路,或无路可走又返回到入口点。

在求解过程中,为了保证在到达某一点后不能向前继续行走(无路)时,能正确返回前一个点以便继续从下一个方向向前试探,则需要用一个栈保存所有到达点的下标。

另外,求解该问题的一个重要问题是如何防止回溯时走重复节点,以避免发生死循环。

这里,我们采用对走过的结点,修改其结点信息。

如在设计之初,我们设置保存迷宫结构的二维数组中0值代表该节点可走,1值代表其不可走,那么我们可以把走过的结点值改为非0,已使其不能被再次探索。

3.数据结构设计由上面的设计思路知,若想正确的使用回溯法求解迷宫问题,必须要借助一个栈以保存走过的结点信息。

而这里我活用了栈,只把其数据结构抽象为了一个结构体数组,具体设计如下:typedef struct{}pos;pos Pos[100]; /*结构体数组以保存走过的结点信息*/4.功能函数介绍(1)判断是否找到出口函数Isover();该函数的参数是当前结点的x、y坐标与出口结点的x、y坐标,通过比较其值来判断是否找到出口结点,从而控制程序结束。

(2)对程序相关信息的简单介绍函数introduce();该函数主要是在进行绘制迷宫的图形化界面之前开发者搞的一点小插曲,以介绍跟该程序的相关的部分信息。

c语言实现迷宫问题

c语言实现迷宫问题

数据结构试验——迷宫问题(一)基本问题1.问题描述这是心理学中的一个经典问题。

心理学家把一只老鼠从一个无顶盖的大盒子的入口处放入,让老鼠自行找到出口出来。

迷宫中设置很多障碍阻止老鼠前行,迷宫唯一的出口处放有一块奶酪,吸引老鼠找到出口。

简而言之,迷宫问题是解决从布置了许多障碍的通道中寻找出路的问题。

本题设置的迷宫如图1所示。

入口出口图1 迷宫示意图迷宫四周设为墙;无填充处,为可通处。

设每个点有四个可通方向,分别为东、南、西、北(为了清晰,以下称“上下左右”)。

左上角为入口。

右下角为出口。

迷宫有一个入口,一个出口。

设计程序求解迷宫的一条通路。

2.数据结构设计以一个m×n的数组mg表示迷宫,每个元素表示一个方块状态,数组元素0和1分别表示迷宫中的通路和障碍。

迷宫四周为墙,对应的迷宫数组的边界元素均为1。

根据题目中的数据,设置一个数组mg如下int mg[M+2][N+2]={{1,1,1,1,1,1,1,1},{1,0,0,1,0,0,0,1},{1,1,0,0,0,1,1,1},{1,0,0,1,0,0,0,1},{1,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1}};在算法中用到的栈采用顺序存储结构,将栈定义为Struct{ int i; //当前方块的行号int j; //当前方块的列号int di; //di是下一个相邻的可走的方位号}st[MaxSize];// 定义栈int top=-1 //初始化栈3设计运算算法要寻找一条通过迷宫的路径,就必须进行试探性搜索,只要有路可走就前进一步,无路可进,换一个方向进行尝试;当所有方向均不可走时,则沿原路退回一步(称为回溯),重新选择未走过可走的路,如此继续,直至到达出口或返回入口(没有通路)。

在探索前进路径时,需要将搜索的踪迹记录下来,以便走不通时,可沿原路返回到前一个点换一个方向再进行新的探索。

后退的尝试路径与前进路径正好相反,因此可以借用一个栈来记录前进路径。

数据结构与算法之迷宫

数据结构与算法之迷宫

数据结构预算法—迷宫问题哈尔滨工业大学金字塔的小蜗牛一、问题描述:编写一个程序:随机生成一个20 x 20的迷宫,并找到一条从入口到出口的路线。

要求:(1)“迷宫”大小可变,模式随机。

(2)迷宫没有通路时,给出警告;有通路时,任给一条具体路径。

(3)分析算法的效率。

二、算法基本思想:通过产生随机数的方式生成一个只含0和1的二维数组,用这个二维数组来表示迷宫,其中数字1表示通路,数字0表示围墙。

设定好迷宫的入口和出口,采用递归的方法找到一条走出迷宫的路线图,数组my_maze存有正寻找的路线图,在找路线图的运行过程中没有出口的路线图即被后来的路线覆盖,直到找到能走出迷宫的路线图,然后将my_maze中的元素赋给target_maze。

最终将路线图target_maze打印出来。

三、主要数据结构(编程环境:code blocks):1、二维数组一个表示迷宫的二维数组maze[i][j],相关操作有:(1)建立二维数组,赋初值。

(2)数组以指针形式在各函数中传递。

(3)改变数组中某个元素的值。

2、指针运算函数move_to、print_maze1、print_maze2都含有指针作为函数中的变量进行调用。

3、递归运算在寻找迷宫路径的时候,用到了递归运算。

在程序中即从一个点搜寻下一个点的反复过程中不断调用move_to函数自身,最终寻找到走出迷宫的路径。

四、主要函数功能:1、produce_maze()函数功能:随机生成一个20 x 20的二维迷宫。

2、move_to(int _i,int _j, int (*in_maze)[MAX_COL], int count)函数功能:采用递归思想找到一条走出迷宫的路径。

3、print_maze1(int (*maze)[MAX_COL])函数功能:打印出生成的迷宫图案。

4、print_maze2(int (*maze1)[MAX_COL],int (*maze2)[MAX_COL])函数功能:打印出附有路径的迷宫图案。

C语言数据结构中求解迷宫问题实现方法

C语言数据结构中求解迷宫问题实现方法

C语⾔数据结构中求解迷宫问题实现⽅法C语⾔数据结构中求解迷宫问题实现⽅法在学习数据结构栈的这⼀节遇到了求迷宫这个问题,拿来分享⼀下~⾸先求迷宫问题通常⽤的是“穷举求解” 即从⼊⼝出发,顺某⼀⽅向试探,若能⾛通,则继续往前⾛,否则原路返回,换另⼀个⽅向继续试探,直⾄⾛出去。

我们可以先建⽴⼀个8*8的迷宫其中最外侧为1的是墙int mg[M+2][N+2]={{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,1},{1,1,1,1,1,1,1,1,1,1},}如上所⽰,0对应通道⽅块,1代表墙。

对于迷宫中的每个⽅块,有上下左右4个⽅块相邻,我们规定第i⾏第j列⽅块的位置为(i,j)规定上⽅⽅块⽅位为0,顺时针⽅向递增编号。

(i,j)上⽅的即为(i-1,j),下⽅(i+1,j),左⽅(i,j-1),右⽅(i,j+1). 为了⽅⾯回溯,我们需要有进栈出栈操作,所以我们来定义:struct {int i;//当前⽅位⾏int j;//当前⽅位列int di;//下⼀个可⾛⽅位号}St[MaxSize];//栈int top=-1;//初始化栈顶指针我们来看看⽂字过程~~⾸先将⼊⼝进栈(初始⽅位为-1),在栈不空的情况下循环:取栈顶⽅块(不退栈),若该⽅块是出⼝,则退栈。

若存在这样的⽅块,则将其⽅位保存到栈顶元素中,并将这个可⾛的相邻⽅块进栈。

对应的算法:void mgpath(int x1,int y1,int x2,int y2){int i.j,di,find,k;top++;St[top].i=x1; St[top].j=y1; St[top].di=-1; mg[x1][y1]=-1;while (top>-1){i=St[top].i; j=St[top].j; di=St[top].di;if (i==x2 && j==y2){printf("迷宫路径如下:\n");for (k=0;k<=top;k++){printf("\t(%d,%d)",St[k].i,S[k].j);if ((k+1)%5==0) printf("\n"); //输出5个换⼀⾏}printf("\n"); //找到⼀条路径后结束return ;}find=0;while (di<4 && find==0){di++;switch(di){case 0: i=St[top].i-1; j=S[top].j;break;case 1: i=St[top].i; j=St[top].j+1;break;case 2: i=St[top].i+1;j=St[top].j;break;case 3: i=St[top].i; j=St[top].j-1;break;}if(mg[i] [j]==0) find=1;}if (find==1){ //找到了下⼀个可⾛⽅块St[top].di=di;//修改原栈顶的值top++; //下⼀个可⾛⽅块进栈St [top].i=i; St[top].j=j;St[top].di=-1;mg[i] [j]=-1;//避免重复⾛到该⽅块}else{ //没有路径可⾛,进⾏退栈操作mg[St[top].i] [St[top].j]=0;//让该位置变为其他路径的可⾛⽅块top--;}}printf("没有路径可⾛!\n");}当然我们也可以⽤队列去求该迷宫的最优算法,这只是⼀个⽤来理解栈的例⼦~~~感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

c语言解决迷宫问题课程设计

c语言解决迷宫问题课程设计

c语言解决迷宫问题课程设计一、课程目标知识目标:1. 学生理解并掌握C语言中的基本控制结构,包括顺序、选择和循环结构;2. 学生掌握C语言数组的定义和使用,特别是二维数组在表示迷宫中的应用;3. 学生学会使用递归方法解决迷宫问题,理解递归调用的原理和过程;4. 学生理解并掌握迷宫问题的算法逻辑,如深度优先搜索和广度优先搜索。

技能目标:1. 学生能够运用C语言编写程序,实现迷宫的创建、显示和路径寻找的功能;2. 学生通过调试和优化程序,培养解决问题的能力和程序调试技巧;3. 学生能够运用所学知识,迁移到类似问题解决上,提高编程解决实际问题的能力。

情感态度价值观目标:1. 学生在解决迷宫问题的过程中,培养逻辑思维能力和创新意识,激发学习兴趣;2. 学生通过小组合作完成任务,培养团队协作精神,增强沟通与表达能力;3. 学生在编程实践中,体验编程的魅力,提高对信息技术的认识和热爱;4. 学生面对编程难题时,能够保持积极的心态,勇于克服困难,培养坚持不懈的精神。

二、教学内容1. C语言基础回顾:顺序结构、选择结构(if-else)、循环结构(for、while);2. 二维数组:定义、初始化、访问元素,以及二维数组在迷宫问题中的应用;3. 函数:理解递归的概念、编写递归函数,掌握迷宫问题中的递归回溯法;4. 算法逻辑:深度优先搜索和广度优先搜索在迷宫问题中的实现;5. 程序设计:迷宫地图的创建、显示,路径寻找算法的设计与实现;6. 调试技巧:学会使用断点调试、查看变量值等方法,对程序进行优化;7. 小组合作:分组完成任务,进行程序设计、调试和优化,分享成果。

教学内容安排与进度:第一课时:C语言基础回顾,二维数组及其在迷宫问题的应用;第二课时:递归函数的概念和编写,迷宫问题的递归回溯法;第三课时:深度优先搜索和广度优先搜索算法在迷宫问题中的实现;第四课时:程序设计,小组合作,迷宫地图的创建和路径寻找;第五课时:程序调试和优化,成果分享,总结与拓展。

递归--解决迷宫问题

递归--解决迷宫问题

递归--解决迷宫问题1、递归概念⾃⼰调⽤⾃⼰每次调⽤传⼊的变量都不同2、递归怎么调⽤的3、递归应该遵守的规则执⾏⼀个⽅法时,就创建⼀个新的受保护的独⽴空间(栈空间)⽅法的局部变量是独⽴的,不会相互影响,⽐如n变量递归必须有退出的条件,否则就是⽆限递归,报stackOverFloweError(栈溢出错误)当⼀个万法执⾏完毕,或者遇到returm,就会返回,守谁调⽤,就将结果返回给谁如果万法中使⽤的是引⽤类型变量(⽐如数组),就会共享该引⽤类型的数据4、迷宫问题解决 先⽤⼆维数组模拟出表格,给部分表格赋值1来说明是墙壁(红⾊部分) public static void main(String[] args) {int[][] map=new int[10][10];//设置墙体for (int i=0;i<10;i++){map[0][i]=1;map[i][0]=1;map[i][9]=1;map[9][i]=1;}//设置障碍map[3][1]=1;map[3][2]=1;//map[1][2]=1;//map[2][2]=1;//打印表格for (int i=0;i<10;i++){for (int j=0;j<10;j++){System.out.print(map[i][j]+" ");}System.out.println();}//进⾏寻路setWay(map,1,1);//打印表格System.out.println("寻路完成");for (int i=0;i<10;i++){for (int j=0;j<10;j++){System.out.print(map[i][j]+" ");}System.out.println();}}设置寻路的⽅法,按照设置的策略(如下右上左)来逐个进⾏递归,如果能⾛通,这条路线标识为2,⾛不通(⽆法到达指定终点)递归进⾏回溯,将⾛过的路置为3判断这条路是否可⾏: 1是墙,2是⾛过的路,3是⾛不通的路//设置策略⽅法(下右上左)public static boolean setWay(int[][] map,int i,int j){ //map表⽰数组地图,i,j表⽰坐标if (map[8][8]==2){//开始前判断该节点是否找到return true;}else{if (map[i][j]==0){map[i][j]=2; //⾛过的地⽅都先置为2,回溯后置为3if (setWay(map,i+1,j)){ //下return true;}else if (setWay(map,i,j+1)){ //右return true;}else if (setWay(map,i-1,j)){ //上return true;}else if (setWay(map,i,j-1)){ //左return true;}else{map[i][j]=3; //查找失败时,这个路线回溯并设置为3return false;}}else{return false;}}运⾏结果是:注意:选择的策略不同,迷宫的查找路径就不同 如何获取最短路径?可以统计不同的策略⽣成的路线,通过获取策略的路径长度来⽐较出最短路径的策略如上⾯这种策略,统计路径长度//统计路长int count=0;//长度for (int i=0;i<10;i++){for (int j=0;j<10;j++){if (map[i][j]==2){ //当路径标识为2时为可⽤count+=1;}}}System.out.println("路径长"+count);。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
int x; // 行值
int y; // 列值
};
#define MAXLENGTH 25 // 设迷宫的最大行列为25
typedef int MazeType[MAXLENGTH][MAXLENGTH]; // [行][列]
// 全局变量
system("pause");
return 0;
}
/*
输出效果:
请输入迷宫的行数,列数(包括外墙):(空格隔开)4 4
请输入迷宫内墙单元数(即墙的个数):1
请依次输入迷宫内墙每个单元的行数,列数:(空格隔开)
1 2
迷宫结构如下:
0 0 0 0
struct PosType end; // 迷宫终点位置
MazeType m; // 迷宫数组
int x, y; // 迷宫行数,列数
// 定义墙元素值为0,可通过路径为-1ห้องสมุดไป่ตู้通过路径为足迹
}
for(j=1;j<y-1;j++)
{
m[j][0]=0; // 迷宫左边列的周边即左边墙
m[j][y-1]=0;// 迷宫右边列的周边即右边墙
}
m[x1][y1]=0;
}
printf("迷宫结构如下:\n");
Print(x,y);
printf("请输入起点的行数,列数:(空格隔开)");
scanf("%d%d",&begin.x,&begin.y);
*/
else
Print(x,y); // 输出结果
m[next.x][next.y]=-1; // 恢复为通路,试探下一条路
curstep--;
数据结构C语言版 递归求解迷宫问题
用递归函数求解迷宫问题(求出所有解)
编译环境:Dev-C++ 4.9.9.2
日期: 2011年2月12日
*/
#include<stdio.h>
// 迷宫坐标位置类型
struct PosType
// 输出解
void Print(int x,int y)
{
int i,j;
for(i=0;i<x;i++)
{
for(j=0;j<y;j++)
printf("%3d",m[i][j]);
printf("请输入终点的行数,列数:(空格隔开)");
scanf("%d%d",&end.x,&end.y);
m[begin.x][begin.y]=1;
Try(begin,1); // 由第一步起点试探起
struct PosType next; // 下一个位置
// {行增量,列增量}
struct PosType direc[4]={{0,1},{1,0},{0,-1},{-1,0}};
// 移动方向,依次为东南西北
for(i=0;i<=3;i++) // 依次试探东南西北四个方向
}
}
}
// 0为墙,-1为通道
int main()
{
struct PosType begin; //起点
int i,j,x1,y1;
printf("请输入迷宫的行数,列数(包括外墙):(空格隔开)");
scanf("%d",&j);
if(j)
printf("请依次输入迷宫内墙每个单元的行数,列数:(空格隔开)\n");
for(i=1;i<=j;i++)
{
scanf("%d%d",&x1,&y1);
0 -1 0 0
0 -1 -1 0
0 0 0 0
请输入起点的行数,列数:(空格隔开)1 1
请输入终点的行数,列数:(空格隔开)2 2
0 0 0 0
0 1 0 0
0 2 3 0
0 0 0 0
请按任意键继续. . .
printf("\n");
}
printf("\n");
}
// 由当前位置cur、当前步骤curstep试探下一点
void Try(struct PosType cur,int curstep)
{
int i;
{
next.x=cur.x+direc[i].x;
next.y=cur.y+direc[i].y;
if(m[next.x][next.y] == -1) // 是通路
{
for(i=1;i<x-1;i++)
for(j=1;j<y-1;j++)
m[i][j]=-1; // 定义通道初值为-1
printf("请输入迷宫内墙单元数(即墙的个数):");
m[next.x][next.y]=++curstep;
if(next.x != end.x || next.y != end.y) // 没到终点
Try(next,curstep); // 试探下一点(递归调用)
scanf("%d%d",&x,&y);
for(i=0;i<x;i++) // 定义周边值为0(同墙)
{
m[0][i]=0; // 迷宫上面行的周边即上边墙
m[x-1][i]=0;// 迷宫下面行的周边即下边墙
相关文档
最新文档