问题描述:给定一个迷宫,给定入口和出口,找到从入口到出口的一条路径(任何一条路径都可以),迷宫为0表示可走,为1表示墙。用1将迷宫围起来避免边界问题。

实现思路:1.DFS搜索(递归)

2.采用的数据结构

下面分别用这两种方法来解决这个问题。

DFS搜索(即递归+回溯)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <unistd.h>
#define ROW 9
#define COL 9int integer[ROW][COL]={     //表示迷宫{1,0,1,1,1,1,1,1,1},{1,0,1,1,1,0,0,0,1},{1,0,0,0,0,0,1,0,1},{1,0,1,1,1,0,1,0,1},{1,0,1,0,0,0,1,0,1},{1,0,1,1,1,0,1,0,1},{1,0,0,0,0,1,1,0,1},{1,0,1,1,1,1,1,0,0},{1,1,1,1,1,1,1,1,1}
};
/*int integer[ROW][COL]={{2,0,2,2,2,2,2,2,2,2},//1{2,0,0,2,0,0,0,2,0,2},//2{2,0,0,2,0,0,0,2,0,2},//3{2,0,0,0,0,2,2,0,0,2},//4{2,0,2,2,2,0,0,0,0,2},//5{2,0,0,0,2,0,0,0,0,2},//6{2,0,2,0,0,0,2,0,0,2},//7{2,0,2,2,2,0,2,2,0,2},//8{2,2,0,0,0,0,0,0,0,0},//9{2,2,2,2,2,2,2,2,2,2} //10
}; 大家可以用这个迷宫进行再次观察*/int  print(int integer[ROW][COL],int x,int y);//打印该迷宫int dir[4][2]={
{1,0},{-1,0},
{0,1},{0,-1},
}  ;     //方向数组,代表 4 个方向int visted[120][120] ;    //  1  代表访问过  0 代表没有访问过int check(int x,int y) //检查下一步是否越界和是否已经走过以及是否是墙
{if(x< 0 || y<0 || x>= ROW || y>= COL)  return 0;if(visted[x][y])return 0;if(integer[x][y] !=  0 )return 0;return 1;
}int dfs(int x,int y)    //已经踏到了  x , y ,即x,y  可踏
{int xx,yy ,i ;usleep(100000);printf("\033c");print(integer,x,y);if(x ==  7 && y == 8 )exit(0);for(i= 0;i< 4 ;i++)   // 4 个方向 {xx =  x + dir[i][0];yy =  y + dir[i][1];if(check(xx,yy))    //xx ,yy 可踏上去{visted[xx][yy]= 1;dfs(xx,yy) ;visted[xx][yy] = 0 ;  //回溯}}usleep(100000); //再次打印,显示回溯的效果printf("\033c");print(integer,x,y);return 0;
}int print(int integer[ROW][COL],int x,int y)
{int i,j;for(i=0;i<ROW ;i++){for(j=0 ;j<COL ;j++){if(visted[i][j])printf("\033[41;32m  *  \033[0m") ;else printf("  %d  ",integer[i][j]);}printf("\n\n");}
}
int main(void)
{int i,j ;memset(visted,0,sizeof(visted));visted[0][1]=1;      //从入口出发dfs(0,1) ;
}

运行截图:

PS 1.这是一个动态演示的程序,可以清晰的看到移动的动作,所以运行有奇效

2. 回溯之后要再打印一次,才能有回溯的效果,并且必须有sleep 函数,否则会因为程序运行太快而导致看不到回溯的效果。

3. 如果对于DFS搜索还不太懂的–>点这里,文中提到的马踏棋盘我会在下一篇博客中提到。

采用的数据结构

先来提出几个问题

1.为什么要用栈来实现?有什么好的地方?
2.di 有什么作用?为什么要它?
3.栈空与栈不空,有什么用?
4.大体思路是什么?
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#define  MAXSTACKSIZE  100  //栈的大小
#define      N          10     //二维迷宫大小
#define  Entrance_row   0  //入口
#define  Entrance_col   1
#define  Exit_row   8   //出口
#define  Exit_col   9
typedef struct position{   //坐标   int x;int y;
}position ;
typedef struct SElement {position p;   int di;     //记录已经走了多少个方向
}SElement ;
typedef struct Mystack{SElement  *top;SElement  *base;int stackSize ;
}Mystack ;int Maze[N][N]={{2,0,2,2,2,2,2,2,2,2},//1{2,0,0,2,0,0,0,2,0,2},//2{2,0,0,2,0,0,0,2,2,2},//3{2,0,0,0,0,2,2,0,0,2},//4{2,0,2,2,2,0,2,0,2,2},//5{2,0,0,0,2,0,0,0,0,2},//6{2,0,2,0,0,0,2,0,0,2},//7{2,0,2,2,2,0,2,2,0,2},//8{2,2,0,0,0,0,0,0,0,0},//9{2,2,2,2,2,2,2,2,2,2} //10
};int IsEmptyStack(Mystack *path);int InitStack(Mystack *path)   // top ,base  ,size
{path->top = path->base =(SElement *)malloc(sizeof(SElement)*MAXSTACKSIZE);if(path->top == NULL ){printf("Init  stack is failed !!! \n");return -1;}path->stackSize = MAXSTACKSIZE;return 0;
}int pop(Mystack *path ,SElement *t)  //从path 中出一个元素给t
{if(IsEmptyStack(path) == 1)return 0;*t = *(path->top-1);path->top-- ;return 1;
}int push(Mystack *path ,SElement p) //入栈
{*(path->top) = p ;path->top++;
}int IsEmptyStack(Mystack *path)
{if(path->top == path->base )   return 1;  //空栈返回 1  else return 0 ;
}
int print_MAZE(int Maze[N][N])  //打印迷宫
{int i,j;for(i= 0 ;i< N;i++){for(j= 0 ;j< N ;j++){if(Maze[i][j] == 10)    printf("\033[31m  *  \033[0m") ;else  printf("  %d  ",Maze[i][j]);}printf("\n\n");}
}
int check(position now_try) //检查下一步是否越界和是否是墙
{if(Maze[now_try.x][now_try.y]  !=  0)  //0  代表走的通return 0;if(now_try.x <  0 && now_try.x >=  N  )return 0;if(now_try.y <  0 && now_try.y >=  N  )return 0;return 1;
}position   NextPosition(position  now_try ,int direction)  //获得下一个位置的坐标 x,y
{position next ;next.x= now_try.x;next.y  = now_try.y;switch(direction){case 4:next.y+=1;break; //东case 3:next.x+=1;break; //南case 1:next.x-=1;break;//西case 2:next.y-=1;break;//北}return next ;
}
int main(void)
{print_MAZE(Maze) ;Mystack  path ;InitStack(&path);position  now_try ; //所尝试的位置now_try.x= Entrance_row;now_try.y= Entrance_col;do{if(check(now_try)) //进入if 语句就说明这个点能走,就把他赋值为10 ,入栈,找下一步,继续{Maze[now_try.x][now_try.y]  =10 ;SElement temp ;temp.p.x= now_try.x;temp.p.y= now_try.y;push(&path,temp);if(now_try.x == Exit_row && now_try.y == Exit_col )break;now_try  = NextPosition(now_try,1);  //先向一个方向进行探索printf("\033c"); // 动态演示所走的路的语句print_MAZE(Maze);usleep(800000);}else     //这个点为 2 ,不能走,那么就取出它的上一个(即栈顶元素),寻找其他方向{if(IsEmptyStack(&path) !=  1)  //栈不空{SElement t ;pop(&path,&t);    //要在被调函数中改变twhile(t.di == 4 && IsEmptyStack(&path) !=  1){   //检查是否四个方向都已经被走过Maze[t.p.x][t.p.y] = 9 ;   //9 代表已经被探索过的路pop(&path,&t);}if(t.di < 4) //如果四个方向没有走够,就换一个方向走{now_try = NextPosition(t.p,t.di+1);t.di++;push(&path,t);}}}}while( IsEmptyStack(&path) ==  0  );  //0 就是有元素printf("\033c");print_MAZE(Maze);return 0;
}

运行截图:

问题解答:

1.首先我们都知道栈有先进后出的特点,那么我们的迷宫是否需要这种特点呐。如果走的通,那么就走,如果走不通,那是不是要回到前一步,找另外一个方向走。那么前一步怎么存储?是不是符合一个先存后取的顺序!OK !这不正好与我们的栈的特点重合吗。

2.di 的作用有两个。一是表示方向,二是表示走了几个方向了。是不是感觉很拗口。那么我来简单解释一下。用1,2,3,4来表示东南西北,如果di==3,那么就说明北面还没有走,如果di == 4,那么就说明四个方向都已经走过了。

3.栈空与栈不空,有什么用?假如我们将迷宫改成了这样,那么会发生什么?

int Maze[N][N]={{2,0,2,2,2,2,2,2,2,2},{2,0,2,2,2,2,2,2,2,2},{2,0,2,2,2,2,2,2,2,2},{2,0,2,2,2,2,2,2,2,2},{2,0,2,2,2,2,2,2,2,2},{2,0,2,2,2,,2,2,2,2},{2,0,2,2,2,2,2,2,2,2},{2,0,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,2,2}
};

是不是会依次入栈,然后依次出栈,出栈之后是不是会栈空,如果不判断栈空的话是不是会陷入一种死循环的状态呐。

4.核心代码:

    now_try.x= Entrance_row;now_try.y= Entrance_col;do{if(check(now_try)) //进入if 语句就说明这个点能走,就把他赋值为10 ,入栈,找下一步,继续{Maze[now_try.x][now_try.y]  =10 ;SElement temp ;temp.p.x= now_try.x;temp.p.y= now_try.y;push(&path,temp);if(now_try.x == Exit_row && now_try.y == Exit_col )break;now_try  = NextPosition(now_try,1);  //先向一个方向进行探索printf("\033c"); // 动态演示所走的路的语句print_MAZE(Maze);usleep(800000);}else     //这个点为 2 ,不能走,那么就取出它的上一个(即栈顶元素),寻找其他方向{if(IsEmptyStack(&path) !=  1)  //栈不空{SElement t ;pop(&path,&t);    //要在被调函数中改变twhile(t.di == 4 && IsEmptyStack(&path) !=  1){   //检查是否四个方向都已经被走过Maze[t.p.x][t.p.y] = 9 ;   //9 代表已经被探索过的路pop(&path,&t);}if(t.di < 4) //如果四个方向没有走够,就换一个方向走{now_try = NextPosition(t.p,t.di+1);t.di++;push(&path,t);}}}}while( IsEmptyStack(&path) ==  0  );  //0 就是有元素

大体思路:

参考资料:参考资料

转载于:https://www.cnblogs.com/Tattoo-Welkin/p/10335326.html

栈的应用--迷宫问题相关推荐

  1. 栈的应用--迷宫求解

    栈的应用–迷宫求解 思路: 从一个起点(1,1)坐标开始, 依次判断它的右,下,左,上, 方位能不能走 如果能就直接走, 每走一步将这个位置的坐标入栈, 并且标记为2, 若都不能走, 说明走到死路了, ...

  2. 栈的应用——迷宫的非递归解法

    迷宫的求解是一个经典的问题,一直以来都想自己动手写写,虽然网上有无数的代码,虽然对算法比较清楚,但我觉得只有在不参考任何资料的情况下,能写的出来才算是真正掌握.今天有时间,有心情,终于静下心来写完了这 ...

  3. 数据结构——详解栈应用之迷宫问题

    文章目录 一.算法概述 迷宫如下: 1.初始化迷宫并输出 2.用二维数组记录是否到过迷宫中的点 3.定义(1,1,3)为起始点坐标 4.算法核心: 5.循环结束,栈中从底到顶即为一条路线 6.输出所有 ...

  4. (十三)栈的应用 --- 迷宫解题五行八卦阵

    迷宫解题 迷宫解题是我最喜欢的栈的实际应用,可以用来做一些外挂,具体什么外挂?呵呵..自己好好想想. 这个迷宫能走出来吗?我想99.999%的人都能够解出来.用笔沿着空白处画,路不通折回去再走下一条路 ...

  5. Java用栈简单实现迷宫

    迷宫 用0表示可以走,1表示不可以走,从左上角走到右下角,能否找到一条路,如果找到,那么打印出来路径,用2表示走过的路径 如果找不到,那么图中尝试过的点置为 -1. 程序运行如下 输出如下 我的主要思 ...

  6. java栈 迷宫_利用栈实现迷宫的求解

    问题描述:这时实验心理学中的一个典型的问题,心理学家吧一只老鼠从一个无顶的大盒子的入口处赶进迷宫.迷宫设置很多隔壁,对前进方向形成了许多障碍,心理学家在迷宫的唯一出口处放置了一块奶酪,吸引老鼠仔迷宫中 ...

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

    本文适合于对迷宫问题已有初步研究,或阅读代码能力较强的人. 因此,如果你对迷宫问题一无所知,请参考其他更详细的资料. 迷宫问题,是一个对栈(Stack)典型应用的例子之一. 假如,有如下10X10的迷 ...

  8. C语言 迷宫问题求解(顺序栈应用示例)

    [cpp] view plaincopy //顺序栈的应用:迷宫 //作者:nuaazdh //时间:2011年12月7日 #include <stdio.h> #include < ...

  9. 栈应用之简单迷宫问题(C语言版)

    迷宫在这儿--–>(用二维数组实现) 栈的应用有很多,前面解决了括号问题和后缀表达式问题,迷宫便可以解决了!! 迷宫的解题思路有点绕,并且其栈的结构也有所改变!但是本次解决迷宫仍然用的普通的栈 ...

最新文章

  1. ISE调用Notepad++并且实现错误高亮定位的方法
  2. 【lora模块技术无线数传电台】E90-DTU产品高防护等级的体现
  3. kangle虚拟主机空间销售网站源码
  4. Professional C# 6 and .NET Core 1.0 - Chapter 43 WebHooks and SignalR
  5. java 缓冲流 刷新_java – 缓冲和刷新Apache Beam流数据
  6. Windows和linux(ubuntu)互传文件简便快捷的方法
  7. UML中对关系的描述
  8. kworker内核工作队列详解
  9. python 断言方法
  10. 数据产品经理——数据指标
  11. 使用OpenResty达到十万级并发超高性能Web应用(一):HelloWorld
  12. [转]UserData使用总结 - lanyu
  13. 补淘宝单平台哪个便宜?如何补单才能增加权重?
  14. python微信群聊机器人_Python + itchat 实现微信机器人聊天(支持自动回复指定群聊)...
  15. SpringBoot整合腾讯云COS对象存储实现文件上传
  16. 提高浏览器渲染页面速度
  17. 拨号vps是什么?有哪些功能?
  18. d3成神之路(三):折线图
  19. 架构师之路系列:接口幂等性是个什么东东?如何实现接口幂等设计?
  20. vif诊断多重共线性

热门文章

  1. 使用BusyBox制作嵌入式Linux根文件系统
  2. Linux 字符设备驱动开发基础(五)—— ioremap() 函数解析
  3. React开发(107):回显数据直接getFieldDecorator定义
  4. [html] link标签的属性media有哪些值?都有什么作用?
  5. [html] 你能否画出一个0.5px的直线?
  6. [css] 对比下px、em、rem有什么不同?
  7. [css] 写出div在不固定高度的情况下水平垂直居中的方法?
  8. [css] 如何让IE6支持min-width和max-width?
  9. 工作187:表单校验规则
  10. 前端学习(2344):高阶组件和函数子组件