数据结构课设迷宫问题

news2024/11/17 5:54:02

迷宫问题

【问题描述】以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。

【基本要求】编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为z(1,1,1),(1,2,2),(2,2,2),(3,2,3),(3,1,2),··。

【测试数据】迷宫的测试数据如下:左上角(1,1)为入口,右下角(8,9)为出口。

               1    2    3    4    5    6    7    8

0

0

1

0

0

0

1

0

0

0

1

0

0

0

1

0

0

0

0

0

1

1

0

1

0

1

1

1

0

0

1

0

0

0

0

1

0

0

0

0

0

1

0

0

0

1

0

1

0

1

1

1

1

0

0

1

1

1

0

0

0

1

0

1

1

1

0

0

0

0

0

0

【实现提示】计算机解迷宫通常用的是“穷举求解“方法,即从入口出发,顺着某一个方向进行探索,若能走通,则继续往前进;否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。假如所有可能的通路都探索到而未能到达出口,则所设定的迷宫没有通路。

可以二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。为处理方便起见,可在迷宫的四周加一圈障碍。对于迷宫中任一位置,均可约定有东、南、西、北四个方向可通。

【选作内容】注:可参考教材50页

(l) 编写递归形式的算法,求得迷宫中所有可能的通路;

(2) 以方阵形式输出迷宫及其通路。

#include <stdio.h>
#include <malloc.h>
#include <pthread.h>
#include <unistd.h>
#define M 10
#define N 10 // 测试案例1,2
// #define M 12
// #define N 12 // 测试案例3
typedef struct
{ // 通路记录
    int current_x;
    int current_y;
    int di;
} Box;
typedef struct sNode
{ // 链栈定义
    Box box;
    struct sNode *next;
} *Linkstack;
void push(Linkstack &top, Box box)
{ // 入栈函数
    Linkstack p;
    p = (Linkstack)malloc(sizeof(struct sNode));
    p->box = box;
    p->next = top;
    top = p;
}
Box pop(Linkstack &top)
{
    Linkstack p = top; // 保存当前栈顶节点
    top = top->next;   // 栈顶指针指向下一个节点
    Box box = p->box;  // 获取出栈元素

    free(p); // 释放出栈节点内存空间

    return box;
}

bool isEmpty(Linkstack &top)
{
    if (top == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}
void print_stack(Linkstack top)
{
    Linkstack p;
    p = top;
    while (p)
    {
        printf("(%d,%d,%d)\n", p->box.current_y, p->box.current_x, p->box.di);
        p = p->next;
    }
}
void print_maze(int maze[M][N])
{
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (maze[i][j] == 1)
            {
                printf("■ ");
            }
            if (maze[i][j] == -1)
            {
                printf("★ ");
            }
            if (maze[i][j] == 0)
            {
                printf("□ ");
            }
            if (maze[i][j] == -2)
            {
                printf("○ ");
            }
        }
        printf("\n");
    }
    printf("--------------------\n");
    sleep(1.5);
}
bool DFS(int maze[M][N], int direction[][2], Linkstack &top, Box end, Box temp)
{
    int current_x, current_y, current_di; // 当前坐标
    int next_x, next_y;                   // 下一个位置的坐标
    maze[temp.current_y][temp.current_x] = -1;
    push(top, temp);
    while (!isEmpty(top))
    {
        temp = pop(top);
        current_x = temp.current_x;
        current_y = temp.current_y;
        current_di = temp.di + 1;
        while (current_di < 4)
        {
            next_x = current_x + direction[current_di][0]; // 确定下个位置的x坐标
            next_y = current_y + direction[current_di][1]; // 确定下个位置的y坐标

            if (maze[next_y][next_x] == 0)
            { // 判断下个位置坐标是否可走
                maze[next_y][next_x] = -1;
                temp.current_x = current_x;
                temp.current_y = current_y;
                temp.di = current_di; // 将当前方向保存
                push(top, temp);      // 入栈
                // print_maze(maze);
                current_x = next_x; // 更新坐标
                current_y = next_y; // 更新坐标
                current_di = 0;
                if (current_x == end.current_x && current_y == end.current_y)
                { // 到达终点
                    temp.current_x = current_x;
                    temp.current_y = current_y;
                    temp.di = current_di; // 将当前方向保存
                    push(top, temp);      // 入栈
                    return true;
                }
            }
            else
            {
                current_di++; // 更换方向
            }
        }
        if (current_di == 4 && maze[current_y][current_x] == -1) // 当前坐标已走完且无通路
        {
            maze[current_y][current_x] = -2;
        }
    }
    return false;
}
void RecursionDFS(int maze[M][N], int direction[][2], Linkstack &top, Box current, Box end)
{
    if (current.current_x == end.current_x && current.current_y == end.current_y)
    {
        printf("这是一条路径\n");
        print_stack(top);
        print_maze(maze);
        printf("============================\n");
        return;
    }
    for (int i = 0; i < 4; i++)
    {
        if (maze[current.current_y][current.current_x] == 0)
        { // 将起点进栈
            maze[current.current_y][current.current_x] = -1;
        }

        int next_x = current.current_x + direction[i][0];
        int next_y = current.current_y + direction[i][1];
        if (maze[next_y][next_x] == 0)
        {

            maze[next_y][next_x] = -1;
            Box temp;
            temp.current_x = next_x;
            temp.current_y = next_y;
            current.di = i;                                //!!!!!!!,记录当前要存入栈中位置的指向下一个位置的方向
            push(top, current);                            // 存入当前位置,以及当前指向下一个位置的方向
            RecursionDFS(maze, direction, top, temp, end); // 传入的temp是自己本身的坐标,不是下一个位置的坐标
            maze[next_y][next_x] = 0;
            pop(top);
        }
    }
}
int main()
{
    Linkstack top = NULL;
    int direction[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; // 方位数组,上右下左
    int maze[M][N] = {                                       // 测试案例1,M,N都为10
                      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
                      {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
                      {1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
                      {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
                      {1, 0, 0, 0, 1, 1, 1, 1, 0, 1},
                      {1, 0, 1, 0, 1, 0, 0, 0, 0, 1},
                      {1, 0, 1, 0, 1, 1, 1, 1, 0, 1},
                      {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
                      {1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
                      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
    //       int maze[M][N] = {                                       // 测试案例2,M,N都为10,无通路
    //   {1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
    //   {1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    //   {1, 0, 1, 1, 1, 1, 1, 1, 1, 1},
    //   {1, 0, 1, 0, 0, 0, 0, 0, 0, 1},
    //   {1, 0, 0, 0, 1, 1, 1, 1, 0, 1},
    //   {1, 0, 1, 0, 1, 0, 0, 0, 0, 1},
    //   {1, 0, 1, 0, 1, 1, 1, 1, 1, 1},
    //   {1, 0, 1, 1, 0, 0, 0, 0, 0, 1},
    //   {1, 1, 1, 1, 1, 1, 1, 1, 0, 1},
    //   {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
    // int maze[M][N] = {
    //     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // 测试案例3,M,N都为12
    //     {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
    //     {1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1},
    //     {1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1},
    //     {1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1},
    //     {1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1},
    //     {1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1},
    //     {1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1},
    //     {1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1},
    //     {1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1},
    //     {1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1},
    //     {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}};
    bool is = DFS(maze, direction, top, Box{8, 8, 0}, Box{1, 1, -1}); // 测试案例1
    // bool is = DFS(maze, direction, top, Box{8, 8, 0}, Box{1,1,-1});//测试案例2
    // bool is = DFS(maze, direction, top, Box{10, 10, 0}, Box{1, 1, -1});//测试案例3
    if (is)
    {
        printf("找到路径\n");
        print_stack(top);
        print_maze(maze);
    }
    else
    {
        printf("没有找到路径\n");
    }
    // RecursionDFS(maze, direction, top, Box{1, 1, 0}, Box{8, 8, 0}); // 递归求全路径,测试案例1,2
    //    RecursionDFS(maze, direction, top, Box{1, 1, 0}, Box{8, 8, 0}); // 递归求全路径,测试案例1,2
    // RecursionDFS(maze, direction, top, Box{1, 1, 0}, Box{10, 10, 0}); // 递归求全路径,测试案例3
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1338946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序获取手机号

1、先新建vue页面 打开看到页面是下图 在method定义方法 源码&#xff1a; <template><view><button type"primary" open-type"getPhoneNumber" getphonenumber"getPhoneNumberFn">登录</button><view class"&…

Explain分析-Mysql索引优化(三)

欢迎大家关注我的微信公众号&#xff1a; 传送门&#xff1a;Explain分析——索引优化实践 传送门&#xff1a;Explain分析-Mysql索引优化&#xff08;二&#xff09; 目录 分页查询优化 Join关联查询优化 in和exsits优化 count(*)查询优化 分页查询优化 示例表&am…

115基于matlab的用于铣削动力学建模的稳定性叶瓣图分析(stablity lobe)

基于matlab的用于铣削动力学建模的稳定性叶瓣图分析(stablity lobe)&#xff0c;程序已调通&#xff0c;可直接运行。 115matlab铣削动力学 (xiaohongshu.com)

HarmonyOS的功能及场景应用

一、基本介绍 鸿蒙HarmonyOS主要应用的设备包括智慧屏、平板、手表、智能音箱、IoT设备等。具体来说&#xff0c;鸿蒙系统是一款面向全场景(移动办公、运动健康、社交通信、媒体娱乐等)的分布式操作系统&#xff0c;能够支持手机、平板、智能穿戴、智慧屏、车机等多种终端设备…

SpringBoot 3.2.0 结合Redisson接入Redis

依赖版本 JDK 17 Spring Boot 3.2.0 Redisson 3.25.0 工程源码&#xff1a;Gitee 集成Redis步骤 导入依赖 <properties><redisson.version>3.25.0</redisson.version> </properties> <dependencies><dependency><groupId>org.pr…

无需手动搜索!轻松创建IntelliJ IDEA快捷方式的Linux教程

轻松创建IntelliJ IDEA快捷方式的Linux教程 一、IntelliJ IDEA简介二、在Linux系统中创建快捷方式的好处三、命令行创建IntelliJ IDEA快捷方式四、图形界面创建IntelliJ IDEA快捷方式五、常见问题总结 一、IntelliJ IDEA简介 IntelliJ IDEA是一个由JetBrains搞的IDE&#xff0…

Bridge桥模式(单一职责)

目的 链接&#xff1a;桥模式实例代码 解析 由于某些类型的固有的实现逻辑&#xff0c;使得它们具有两个变化的维度&#xff0c;乃至多个纬度的变化。 如何应对这种“多维度的变化”&#xff1f;如何利用面向对象技术来使得类型可以轻松地沿着两个乃至多个方向变化&#xff…

算法模板之单调栈和单调队列图文详解

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;算法模板、数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️单调栈讲解1.1 &#x1f514;单调栈的定义1.2 &#x1f514;如何维护一个单…

Socket与字节序

一、Socket "Socket"&#xff08;套接字&#xff09;是计算机网络编程中的一个重要概念&#xff0c;它提供了一种在网络上进行进程间通信的机制。套接字是一种抽象&#xff0c;它允许程序通过网络发送和接收数据。在通常的情况下&#xff0c;套接字用于实现不同计算…

【论文阅读+复现】SparseCtrl: Adding Sparse Controls to Text-to-Video Diffusion Models

SparseCtrl:在文本到视频扩散模型中添加稀疏控制。 &#xff08;AnimateDiff V3&#xff0c;官方版AnimateDiffControlNet&#xff0c;效果很丝滑&#xff09; code&#xff1a;GitHub - guoyww/AnimateDiff: Official implementation of AnimateDiff. paper&#xff1a;htt…

数据库开发之子查询的详细解析

1.4 子查询 1.4.1 介绍 SQL语句中嵌套select语句&#xff0c;称为嵌套查询&#xff0c;又称子查询。 SELECT * FROM t1 WHERE column1 ( SELECT column1 FROM t2 ... ); 子查询外部的语句可以是insert / update / delete / select 的任何一个&#xff0c;最常见…

SEGGER-RTT

wiki:https://wiki.segger.com/RTT 1.简介 Real Time Transfer&#xff08;简称RTT&#xff09;是Segger公司推出的用于嵌入式系统监控和交互的工具&#xff0c;其融合了SWO&#xff08;SWD调试技术中的调试日志输出&#xff09;等能力&#xff0c;且具备极高的性能。RTT的技术…

【JavaScript】Set、Map、WeakSet、WeakMap

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

【K8S 二进制部署】部署Kurbernetes的网络组件、高可用集群、相关工具

目录 一、K8S的网络类型&#xff1a; 1、K8S中的通信模式&#xff1a; 1.1、、pod内部之间容器与容器之间的通信 1.2、同一个node节点之内&#xff0c;不同pod之间的通信方式&#xff1a; 1.3、不同node节点上的pod之间是如何通信的呢&#xff1f; 2、网络插件一&#xff…

找不到msvcp140.dll怎么办-msvcp140.dll丢失的解决方法分享

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“msvcp140.dll丢失”。那么&#xff0c;msvcp140.dll究竟是什么文件&#xff1f;为什么会出现丢失的情况&#xff1f;本文将详细介绍msvcp140.dll的属性、作用以及丢失的原因&#xff0c;并…

1. pytorch mnist 手写数字识别

文章目录 一、数据集介绍1.1、简介1.2 详细介绍1、数据量2、标注量3. 标注类别4.数据下载5.数据集解读 二、读取、加载数据集1、pytorch 自带库函数2、通过重构Dataset类读取特定的MNIST数据或者制作自己的MNIST数据集 三、模型构建四、 runtraintest评估模型的性能检查点的持续…

element-plus修改主题颜色

一、自定义scss文件 在src\css\styles\element目录下新建index.scss 代码如下 forward "element-plus/theme-chalk/src/common/var.scss" with ($colors: ("primary": ("base": #d61b1a,"color": #fff,),) );use "element-plus…

STANFORD斯坦福FS725铷钟

FS725在一个紧凑的半宽2U机箱中集成了一个铷原子振荡器&#xff08;SRS型号PRS10&#xff09;、一个低噪声通用交流电源和分配放大器。它提供稳定和可靠的性能&#xff0c;估计20年的老化率低于510-9&#xff0c;并证明铷原子振荡器的MTBF超过20万小时。FS725是校准和研发实验室…

【JavaWeb学习笔记】18 - 文件上传下载

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/fileupdown 目录 文件上传 一、基本介绍 二、文件上传的基本原理 ​编辑 三、文件上传应用实例 四、文件上传的注意细节 1.解决中文乱码问题 2.分割文件夹 3.防止重名 4.百度WebUploader 5.空…