C++ 基于BFS算法的走迷宫自动寻路的实现

C++ 基于BFS算法的走迷宫自动寻路的实现攻略

算法介绍

BFS即广度优先搜索,它的主要思想是从起点出发,依次访问离起点最近的所有未访问的节点。它除了可以用于寻路,也可以用于其他需要搜索的问题中。在Maze寻路问题中,把所有可能走的路线一个个枚举出来,找到最短的一条。

实现步骤

1. 定义节点

定义一个节点,它包含迷宫的当前位置,当前步数,以及该位置的前一步位置。例如:

struct Node {
    int x;
    int y;
    int step;
    int pre;
};

2. 生成地图

可以使用二维数组来表示地图,0表示可以通过的路,1表示障碍物。例如:

int map[5][5] = {
    {0, 1, 0, 0, 0},
    {0, 1, 0, 1, 0},
    {0, 0, 0, 0, 0},
    {0, 1, 1, 1, 0},
    {0, 0, 0, 1, 0},
};

3. 定义搜索方向

因为搜索方向有上下左右四个方向,所以可以定义dx和dy来表示每个方向的移动情况。例如:

int dx[4] = {0, 1, 0, -1};  // x轴移动
int dy[4] = {1, 0, -1, 0};  // y轴移动

4. 实现BFS算法

从起点出发,依次访问从当前位置可到达的所有未被访问的节点,并计算它们到起点的步数,最后找到终点的位置和步数。

void bfs() {
    queue<Node> q;
    Node start = {0, 0, 0, -1};
    q.push(start);
    visited[0][0] = true;

    while (!q.empty()) {
        Node cur = q.front();
        q.pop();

        if (cur.x == endX && cur.y == endY) {  // 到达终点
            printf("到达终点,步数为:%d\n路径为:", cur.step);
            printRoute(cur.pre);
            return;
        }

        for (int i = 0; i < 4; ++i) {  // 尝试4个方向    
            int nx = cur.x + dx[i];
            int ny = cur.y + dy[i];

            if (nx < 0 || ny < 0 || nx >= n || ny >= m || map[nx][ny] == 1 || visited[nx][ny]) {
                continue;  // 越界或障碍物或已经访问过
            }

            visited[nx][ny] = true;
            Node next = {nx, ny, cur.step + 1, q.size()-1};  // 记录前一步下标
            q.push(next);
        }
    }
}

5. 输出路径

找到终点后,可以通过记录每个节点的前一节点下标位置,递归输出路径。

void printRoute(int pre) {
    if (pre == -1) {
        return;
    }

    printRoute(q[pre].pre);
    printf("(%d, %d) ", q[pre].x, q[pre].y);
}

示例说明

示例一

图示:

S:起点
E:终点
0:可以通过的路
1:障碍物
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

代码示例:

#include <iostream>
#include <queue>

using namespace std;

const int N = 110;

int map[N][N];
bool visited[N][N];

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

struct Node {
    int x;
    int y;
    int step;
    int pre;
};

vector<Node> q;

int n, m;
int startX, startY, endX, endY;

void bfs();
void printRoute(int pre);

int main() {
    cin >> n >> m >> startX >> startY >> endX >> endY;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> map[i][j];
        }
    }

    bfs();

    return 0;
}

void bfs() {
    queue<Node> q;
    Node start = {startX, startY, 0, -1};
    q.push(start);
    visited[startX][startY] = true;

    while (!q.empty()) {
        Node cur = q.front();
        q.pop();

        if (cur.x == endX && cur.y == endY) {
            printf("到达终点,步数为:%d\n路径为:", cur.step);
            printRoute(cur.pre);
            return;
        }

        for (int i = 0; i < 4; ++i) {
            int nx = cur.x + dx[i];
            int ny = cur.y + dy[i];

            if (nx < 0 || ny < 0 || nx >= n || ny >= m || map[nx][ny] == 1 || visited[nx][ny]) {
                continue;
            }

            visited[nx][ny] = true;
            Node next = {nx, ny, cur.step + 1, q.size()-1};
            q.push(next);
        }
    }
}

void printRoute(int pre) {
    if (pre == -1) {
        return;
    }

    printRoute(q[pre].pre);
    printf("(%d, %d) ", q[pre].x, q[pre].y);
}

输入样例:

5 5 0 0 4 3
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0

输出样例:

到达终点,步数为:9
路径为:(0, 0) (1, 0) (2, 0) (2, 1) (2, 2) (3, 2) (4, 2) (4, 3) (4, 4) 

示例二

图示:

S:起点
E:终点
0:可以通过的路
1:障碍物
0 1 0 0 0
0 1 0 1 0
0 0 0 0 1
0 1 1 1 1

代码示例:

#include <iostream>
#include <queue>

using namespace std;

const int N = 110;

int map[N][N];
bool visited[N][N];

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};

struct Node {
    int x;
    int y;
    int step;
    int pre;
};

vector<Node> q;

int n, m;
int startX, startY, endX, endY;

void bfs();
void printRoute(int pre);

int main() {
    cin >> n >> m >> startX >> startY >> endX >> endY;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> map[i][j];
        }
    }

    bfs();

    return 0;
}

void bfs() {
    queue<Node> q;
    Node start = {startX, startY, 0, -1};
    q.push(start);
    visited[startX][startY] = true;

    while (!q.empty()) {
        Node cur = q.front();
        q.pop();

        if (cur.x == endX && cur.y == endY) {
            printf("到达终点,步数为:%d\n路径为:", cur.step);
            printRoute(cur.pre);
            return;
        }

        for (int i = 0; i < 4; ++i) {
            int nx = cur.x + dx[i];
            int ny = cur.y + dy[i];

            if (nx < 0 || ny < 0 || nx >= n || ny >= m || map[nx][ny] == 1 || visited[nx][ny]) {
                continue;
            }

            visited[nx][ny] = true;
            Node next = {nx, ny, cur.step + 1, q.size()-1};
            q.push(next);
        }
    }
}

void printRoute(int pre) {
    if (pre == -1) {
        return;
    }

    printRoute(q[pre].pre);
    printf("(%d, %d) ", q[pre].x, q[pre].y);
}

输入样例:

4 5 0 0 3 4
0 1 0 0 0
0 1 0 1 0
0 0 0 0 1
0 1 1 1 1

输出样例:

无法到达终点

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++ 基于BFS算法的走迷宫自动寻路的实现 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • 详解C++内存的代码区,全局区,栈区和堆区

    首先我们来了解一下 C++ 内存分区的四个部分:代码区、全局区、栈区和堆区。 代码区 代码区是用于存放程序的可执行代码,是只读的,它的大小在程序编译时就已经确定了。在代码区中,每个函数都有一个入口地址,这些入口地址按照函数声明的顺序保存在函数表中。 全局区 全局区用于全局变量和静态变量的存储,它在程序运行前就已经分配好了固定的内存空间,程序结束时才会被释放。…

    C 2023年5月24日
    00
  • Node.js在child_process域和错误冒泡及捕获实践

    在Node.js中,子进程模块child_process提供了一些API用于创建和管理子进程,允许Node.js应用程序在新的进程中执行命令和脚本。但是,在使用child_process创建的子进程中,可能会出现错误。本篇攻略将着重介绍子进程中的错误冒泡及其如何捕获这些错误。 错误冒泡 在一个子进程中,如果一个错误出现在子进程的某个方法中并且没有被捕获和处理…

    C 2023年5月22日
    00
  • C语言实现简易连连看游戏

    C语言实现简易连连看游戏攻略 1. 游戏规则 游戏界面为 $n\times m$ 的方格矩阵,每个格子中隐藏着一些图案。 玩家需要在规定时间内消去所有连在一起的同一图案的格子。 连接两个同一图案的格子,需要一条不超过2个直角的直线。 2. 游戏实现 2.1 数据结构设计 地图矩阵:使用二维数组存储,每个元素存放一个图案编号。 连线路径:使用链表存储,维护消除…

    C 2023年5月23日
    00
  • HKC疾风系列SG27C/SG27QC/SG27CPLUS三款显示器对比评测

    HKC疾风系列SG27C/SG27QC/SG27CPLUS三款显示器对比评测 简介 本文将对HKC疾风系列SG27C/SG27QC/SG27CPLUS三款显示器进行全方位评测对比,分析它们的优缺点,从而帮助广大用户更好地了解这三款产品,以便于选择合适自己的显示器。 参数对比 参数对比 SG27C SG27QC SG27CPLUS 屏幕尺寸 27英寸 27英寸…

    C 2023年5月23日
    00
  • C++ vector的基本使用示例详解

    C++ vector的基本使用示例详解 什么是C++ vector? C++ vector 是STL(Standard Template Library)中的一个动态数组容器类型,能够灵活地存储和访问不同类型的数据。 如何使用C++ vector? 头文件引入 使用C++ vector,首先需要在代码中引入vector头文件: #include <ve…

    C 2023年5月22日
    00
  • c++如何保存vector到文件

    下面我将为您详细讲解C++如何保存vector到文件。 1. 使用文件流将vector对象保存到文件中 我们可以使用C++的文件流(fstream)来将vector对象保存到文件中。具体步骤如下: 引入头文件#include 打开文件,可以使用ofstream类的构造函数来打开文件,并指定打开方式、文件名等信息。如下: std::ofstream ofs(&…

    C 2023年5月23日
    00
  • C语言编程入门之程序头文件的简要解析

    C语言编程入门之程序头文件的简要解析 什么是头文件 头文件(Header Files)通常是一些包含函数定义、变量声明等的文本文件,其内容可以被多个源文件引用(#include)以便让其内部定义的函数和变量可以在引用这个头文件的源文件中被使用。 头文件的分类 头文件可以分为两类: 1. 系统头文件 系统头文件是由编译器提供的,主要包含一些常用的函数库、数据类…

    C 2023年5月23日
    00
  • C++实现简易选课系统代码分享

    以下是关于“C++实现简易选课系统代码分享”的完整攻略。 1. 实现思路 选课系统需要维护学生信息和课程信息,同时需要记录每个学生选修的课程。因此,在设计程序时,需要建立以下几个类: 学生类 学生类用于存储学生的基本信息,例如学号、姓名、性别等,同时需要用一个vector容器来存储该学生所选的课程。 课程类 课程类用于存储课程的基本信息,例如课程编号、课程名…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部