【数据结构】10分钟教你用栈求解迷宫老鼠问题超详细教程附C++源代码

问题描述

给定一张迷宫地图和一个迷宫入口,然后进入迷宫探索找到一个出口。如下图所示:

该图是一个矩形区域,有一个入口和出口。迷宫内部包含不能穿越的墙壁或者障碍物。这些障碍物沿着行和列放置,与迷宫的边界平行。迷宫的入口在左上角,出口在右下角。

问题分析

  1. 首先要有一张迷宫地图,地图由两部分组成:

    (1)一是迷宫中各处的位置坐标,

    (2)二是迷宫各位置处的状态信息,即该处是墙还是路

所以,该迷宫地图可由一个二维数组来表示。数组的横纵坐标表示迷宫各处的位置坐标,数组元素表示各位置处的状态信息。

2.在这里,假定:

(1)迷宫地图是m*n的,即二维数组是m行n列的。
(2)在迷宫中用1表示墙,用0表示路。当然,为了便于标识,我们后面还会用其他数字代表更多含义。

因此,迷宫的地图一个刻画如下:

现在我们要找一条从入口到出口的路径。路径是一个由位置组成的序列,每一个位置都没有障碍,并且除入口外,路径上的每一个位置都是前一个位置在东西南北方向上相邻的一个位置。

不过,考虑到边界问题不太好处理。我们做这样的工作,在地图外围加一层围墙,给它全部填上1。这样,在处理各个坐标时,都没有差别了。这样一来便大大简化了我们的工作。

下面我们要编写程序求解这个问题。

程序设计

这次还是采用一个简单的模块化来设计这个程序。那么主要有下面几个模块:

  1. 显示欢迎信息
  2. 初始化工作
  3. 生成地图
  4. 找路
  5. 打印地图和路径

下面我们分别完成这些功能。

显示欢迎信息

这个模块就很简单了,输出一些信息提醒使用者就行,主要是为了增加程序的友好性而设置的。大家根据自己的需要自行发挥。例如我的就很随便了:

1void welcome()2{3    cout << "welcome to RAT IN MAZE" << endl;4    system("pause");5    system("cls");6}

初始化工作

这个主要是设置一些全局变量的取值和完成内存的分配,地图的存储还是从堆上分配内存比较好。因为一般来说,考虑到地图可能会很大,这样需要的存储空间就很多了。在这里一并把相关的全局变量给讲解了吧。

 1typedef struct   2{ 3    int row; 4    int col; 5}POSITION; 6 7 8const POSITION maze_size = { 20 , 60 }; 910int ** const maze = new int*[maze_size.row + 2];1112stack<POSITION> path;13POSITION offset[4];//direction
  • POSITION结构体
    坐标结构体变量类型,很容易理解,有两个成员变量:x坐标和y坐标。
  • maze_size
    定义地图的大小,实际分配内存的时候,我们还需要考虑地图边界也需要存储空间。总之,我们的地图坐标范围是1 to maze_size。
  • maze
    二位数组,存储地图,分配的时候+2是用来存储边界的。至于const则是约束指针不改变。不过我们的地图数组是根据maze_size大小动态分配的。
  • path
    用来存路径的。
  • offset
    用来设置位置偏移的。比如我们当前位置是(row = 1, col = 1),那么通过row + 1便可往下走,row - 1就是往上走。col + 1往右走,col - 1 往左走。等等。通过坐标加减offset偏移,便可以移动了。
 1void init() 2{ 3    //偏移 4    offset[0].row = 0; offset[0].col = 1; //right 5    offset[1].row = 1; offset[1].col = 0; //down 6    offset[2].row = 0; offset[2].col = -1; //left 7    offset[3].row = -1; offset[3].col = 0; //up 8 9    //maze = new int*[maze_size.row + 2];10    for (int i = 0; i < maze_size.row + 2; i++)11    {12        maze[i] = new int[maze_size.col + 2];13    }14}

这个代码就是设置偏移的数值,以及动态分配地图数组了。

生成地图

生成地图还是根据地图尺寸,然后随机设置障碍。不过要注意障碍出现的概率设置得小一点,不然地图一般无解。可以用rand()随机数来做。这一步也要把围墙设置好。

 1//地图范围1 - maze_size 有围墙 2void randomMaze() 3{ 4    int i, j, rate; 5 6    for (i = 0; i < maze_size.row + 2; i++) 7    { 8        for (j = 0; j < maze_size.col + 2; j++) 9        {10            //设置围墙11            if ((i == 0) || (i == maze_size.row + 1) || (j == 0) || (j == maze_size.col + 1))12            {13                maze[i][j] = 1;14            }15            else16            {17                rate = rand() % 10+1;18                if (rate <= 3)19                {20                    maze[i][j] = 1;//随机生成障碍21                }22                else23                {24                    maze[i][j] = 0;25                }26            }27        }28    }29    //最后保证起点和终点能走30    maze[1][1] = maze[maze_size.row][maze_size.col] = 0;31}

找路

这个是整个程序设计的核心功能,没有之一。在写代码之前,我们需要弄明白,到底怎么找路呢?

  1. 首先,把迷宫入口作为当前位置。
  2. 如果当前位置是迷宫出口,那么已经找到一条路径了,程序结束。
  3. 如果当前位置不是出口,则在当前位置放置障碍物,表示这里已经来过,防止下次又重复绕回来。然后检查相邻位置是否能走。
  4. 如果一个相邻位置能走,就移动到这个位置上。然后在新的位置上重新开始寻找出口。如果不能走,就尝试下一个相邻位置。
  5. 如果所有的相邻位置都不能走了,则回退到上一个位置,重新选择上一个位置的其他相邻位置,继续探索。
  6. 如果所有的相邻位置都被探索过了,仍然找不到路径,那说明这个迷宫不存在这样的路径。

例如,下面的地图:

                                                                                                                                       图8-9

好了,说了这么多,相信大家已经了解得差不多,并且跃跃欲试了。

 1bool findPath() 2{ 3    POSITION here; //当前位置 4    here.row = here.col = 1; 5    maze[1][1] = 3; //放置障碍,防止回来 6    int option = 0; //next step 7    const int lastOption = 3;  8 9    //find a path10    while ( here.row != maze_size.row || here.col != maze_size.col)11    {12        //not reach the end13        int r, c;14        while (option <= lastOption)15        {16            r = here.row + offset[option].row;17            c = here.col + offset[option].col;18            if (maze[r][c] == 0)19            {20                break;21            }22            option++;//next choice23        }2425        //相邻的位置能走?26        if (option <= lastOption)27        {28            path.push(here);29            here.row = r;30            here.col = c;31            maze[r][c] = 3; //走过了32            option = 0;33        }34        else35        {36            if (path.empty())37            {38                return false;39            }40            //go back41            maze[here.row][here.col] = 3; //此路不可通42            here = path.top();43            path.pop();44            option = 0;45        }46    }4748    maze[maze_size.row][maze_size.col] = 2;4950    return true;51}

相关代码如上面所示,结合前面的讲解,相信大家也能看懂。

打印地图和路径

这个功能就比较简单了,主要是根据maze的信息,生成相应的地图显示出来给大家直观的看到。对于maze里面存的数值,我们也可以作一个小小的规定:

  • 0
    表示位置可通行。
  • 1
    表示位置有障碍。
  • 2
    表示该位置处在找到的路径上面。
  • 3
    探索过程中放置的障碍物。这个障碍物和1表示的障碍物不同的是,这个障碍我们放置的,和生成地图时的固定障碍物不同。因此还是要区分开来的。

然后打印的时候,遍历maze数组,遇到:

  • 0
    打印空格。
  • 1
    打印*号。
  • 2
    打印#号,并且设置下颜色。
  • 3
    还是打印空格。(或者根据自己的喜好打印另外的符号,这样就可以把探索过的所有位置显示出来。)

最后在打印最终的地图和路径之前,如果找到一条路径。我们还要根据path中的路径,在maze里面设置好相应的值,才做最终的输出:

 1void setPathOnMaze() 2{ 3    POSITION pos; 4    while (!path.empty()) 5    { 6        pos = path.top(); 7        path.pop(); 8        maze[pos.row][pos.col] = 2;//路径 9    }10}1112然后,可以开始输出我们的地图了。

具体代码:

 1void outputMaze() 2{ 3    int i, j; 4    for (i = 0; i < maze_size.row + 2; i++) 5    { 6        for (j = 0; j < maze_size.col + 2; j++) 7        { 8            if (maze[i][j] == 1) 9            {10                cout << "*";11            }12            else if ((maze[i][j] == 0) || (maze[i][j] == 3))13            {14                cout << " ";15            }16            else17            {18                HANDLE hOut;19                hOut = GetStdHandle(STD_OUTPUT_HANDLE);20                SetConsoleTextAttribute(hOut,FOREGROUND_GREEN | FOREGROUND_INTENSITY);21                cout << "#";22                SetConsoleTextAttribute(hOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);23            }24        }25        cout << endl;26    }27}

最终效果

  1. 没有找到路的情况:

  2. 找到了路径:

代码获取

欲获取代码,请关注我们的微信公众号【程序猿声】,在后台回复:rat。即可下载。

推荐文章:10分钟教你用Python做个打飞机小游戏超详细教程

推荐文章:10分钟教你用python下载和拼接微信好友头像图片

推荐文章:10分钟教你用python一行代码搞点大新闻

推荐文章:10分钟教你用python打造贪吃蛇超详细教程

原文地址:https://www.cnblogs.com/infroad/p/9853559.html

时间: 2024-11-08 01:49:13

【数据结构】10分钟教你用栈求解迷宫老鼠问题超详细教程附C++源代码的相关文章

10分钟教你拥有可编程QQ机器人

10分钟教你拥有可编程QQ机器人 --酷Q Air教程 --BY dudujerry 要想阅读本篇教程,读者需要基本的C++知识以及Visual Studio 2010/2015/2017 首先,需要从官方网站下载软件 https://cqp.cc/t/23253 .下载后从"下载"/"Download"文件夹中找到其压缩包.解压. 然后,我们从Github中下载酷Q的SDK. https://github.com/CoolQ/cqsdk-vc 解压发现.sln,是

利用数据结构栈求解迷宫问题

本段程序主要利用数据结构栈的先进后出特点,实现回溯求解迷宫路径问题. #include<iostream> #include<stack> using namespace std; //坐标类 struct Point { int x; int y; }; //地图类 template<int A> struct Map { int (*p)[A]; int row;//行数 int col;//列数 }; //start起始点, end终止点 template<

10分钟教你用python打造贪吃蛇超详细教程

10分钟教你用python打造贪吃蛇超详细教程 在家闲着没妹子约, 刚好最近又学了一下python,听说pygame挺好玩的.今天就在家研究一下, 弄了个贪吃蛇出来.希望大家喜欢. 先看程序效果: 01 整体框架 平台:pycharm 关于pygame的安装这里就不在赘述,大家自行上网找合适自己的版本的安装即可.关于pygame模块知识会穿插在下面代码中介绍,用到什么就介绍什么.这里就不统一介绍了. 整个程序由于是调用了大量的pygame里面的库函数,所以也非常简单(卧槽你这不是调包侠嘛).也就

【python】10分钟教你用python如何正确把妹

前言 今天没妹子约,刚好朋友研究一下python.让他教大家如何用神奇的python打造一个把妹神器吧.看完这个,你们就能走向人生巅峰,迎娶白富美啦. 我知道你们想看看效果 当然啦,这只是测试版的效果,真正的版本可比这个厉害多啦.不过作为一个直男,另一个男的给小编发这个测试感觉还是有点怪怪的哈. 文:吉柏言 暑假来了,各位又不得不和男女朋友暂时分开2个月了!!长达两个月的时间里不能相见,你可知我多想你啊,想知道你的城市下雨了吗,想知道你带伞了吗,想知道你长什么样,想知道你叫啥,咳咳,单身汪小编表

10分钟教你用Python玩转微信之抓取好友个性签名制作词云

01 前言+展示 各位小伙伴我又来啦.今天带大家玩点好玩的东西,用Python抓取我们的微信好友个性签名,然后制作词云.怎样,有趣吧~好了,下面开始干活.我知道你们还是想先看看效果的. 后台登录: 词云: 02 环境准备 Python版本:3.6.0系统平台:Windows 10 X64IDE:pycharm 相关模块:re模块:itchat模块:jieba模块:import matplotlib.pyplot模块:wordcloud模块:以及一些Python自带的模块. 03 获取个性签名 首

利用栈求解迷宫问题

利用栈求解迷宫问题 源代码: #include<stdio.h> #include<stdlib.h> #define M 8 #define N 8 #define MaxSize M*N typedef struct { int i;//当前方块的行号 int j;//当前方块的列号 int di; //di是下一个可走的相邻方块的方位号 }Box; typedef struct { Box data[MaxSize]; int top;      //栈顶指针 }StType

VMware10.0安装Mac OS X 10.9超详细教程

最新版的VMware10.0支持中文,无需汉化,安装即可:不过还是需要注册码,注册机是必须有的请放心,下载地址: 点击进入 其它所需软件: 1.系统:用的是论坛里网友做的懒人版是.cdr文件(真接把.cdr改为.iso就是镜像文件了)  点击进入 (也可以去下原版镜像dmg文件,有7z打开提取里面的InstallESD.dmg,然后用UltraISO转化为ISO镜像文件也可以安装,本人亲试成功) 2.mac补丁unlock-all-v120.zip  点击进入 3.VMware Tools da

数据结构--书上代码用栈求解迷宫问题存在BUG(非最优解)

数据结构第四版p79页迷宫问题我觉得存在BUG,下图盗用贺老师就会的QAQ,也希望贺老师能看到帮忙解答一下啦. BUG:  程序从起始点(1,1)开始寻找路径,在当前点进行判断其上下左右是否存在可走点,如果从(1,1)点开始判断如图那么它的右(1,2)下(2,1)都是可走点那么将右边的格子坐标进栈呢还是将下边的格子坐标进栈?书本上给的代码是先判断上边格子再判断右边格子再判断下边格子再判断左边格子,这就造成了一个问题:(1,2)则个点会被进栈(因为(1,2)点位于(1,1)点的右边被先判断进栈),

【python】10分钟教你用python一行代码搞点大新闻

准备 相信各位对python的语言简洁已经深有领会了.那么,今天就带大家一探究竟.看看一行python代码究竟能干些什么大新闻.赶紧抄起手中的家伙,跟我来试试吧. 首先你得先在命令行进入python.像下面一样. 1> python2Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win323Type "help", "copyright&q