BFS寻路讲解

前言

许多游戏里都需要给AI寻路算法,而其中最简单的就是BFS暴力搜索

思路

注:地图只有起点(S)、终点(E)、空地(.) 和 墙(#)


1.遍历:BFS遍历一遍地图,并记录下走到每一个格子的最短步数(最短步数为附近4格走过的格子的步数+1)

遍历

(若便利不到终点说明到不了终点)

2.回寻:从终点开始遍历,比较附近4个格子(走过的)的最短步数,选择其中最小的(一样的选先查询的那个),就可一知道最短路径了

回寻

(你或许看见两个视频不一样,是应为有一个丢失了重做的) 

代码流程

1.输入地图大小和地图

2. bfs一遍,直到找到终点,找不到就是(队列空)起点走不到终点,在寻找过程中记录每一个格子的最短路径,如果最终找不到终点就说明到不了

3.如果到得了就回寻,并把回寻路径在输出地图(一个数组变量)中标出来(或记录下来)

4.如果到得了就输出输出地图,否则输出"到不了"。

C++演示代码:

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;

const int M = 10001;

struct Node {
    int x, y;
    Node (int _x = 0, int _y = 0, int _step = 0) : x(_x), y(_y) {}
};

int n, m, step[M][M], dic[10][3] = { {1, 0}, {0, 1}, {-1, 0}, {0, -1} };
char map[M][M], ans[M][M];
int bfs(Node start, Node end);
bool rightful(int x, int y), vis[M][M];
void check(Node start, Node end);
void init(Node &start, Node &end), print();

int main() {
    Node start, end;
    init(start, end); // 输入

    if (bfs(start, end) == -1) cout << "到不了"; // 走不到终点
    else {
        check(start, end); // 查询终点到起点的路径
        print(); // 输出路径
    }    
    system("pause");
    return 0;
}

void print() {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) 
            printf("%c ", ans[i][j]);
        printf("\n");
    }
}

void init(Node &start, Node &end) {
    cin >> n >> m;
    
    for (int i = 1; i <= n; i++) 
        for (int j = 1; j <= m; j++) {
            cin >> map[i][j];
            ans[i][j] = map[i][j]; // 复制地图
            if (ans[i][j] == 'S') start = Node(i, j); // 找到起点
            if (ans[i][j] == 'E') end = Node(i, j); // 找到终点
        }
}

bool rightful(int x, int y) {
    if (x < 1 or x > n or y < 1 or y > m) return false; // 是否出界
    if (ans[x][y] == '#') return false; // 是否障碍
    if (vis[x][y]) return false; // 是否走过
    return true;
}

int bfs(Node start, Node end) {
    queue <Node> q;
    q.push(Node(start.x, start.y)); // 起点入队
    vis[start.x][start.y] = true; // 标记起点走过
    while (!q.empty()) {
        Node t = q.front();
        q.pop();
        
        if (t.x == end.x and t.y == end.y) return 0; // 到达终点
        
        for (int i = 0; i < 4; i++) {
            int x = t.x + dic[i][0], y = t.y + dic[i][1]; 
            if (rightful(x, y)) {
                step[x][y] = step[t.x][t.y] + 1; // 记录步数
                vis[x][y] = true; // 标记走过
                q.push(Node(x, y)); // 入队
            }
        }
    }
    return -1;
}

void check(Node start, Node end) {
    int x = end.x, y = end.y;
    while (1) {
        Node minn = Node(x, y); // INT_MAX是2147483647
        int ms = INT_MAX;
        for (int i = 0; i < 4; i++) {
            int tx = x + dic[i][0], ty = y + dic[i][1];

            if (tx == start.x and ty == start.y) return; // 到达起点
            if (step[tx][ty] == 0) continue; // 出界或障碍

            if (ms > step[tx][ty]) {
                minn = Node(tx, ty); // 记录最小步数
                ms = step[tx][ty];
            }
        }
        x = minn.x, y = minn.y; // 走到最小步数的位置
        ans[x][y] = '*'; // 标记路径
    }
}

 变量:
结构体Node:表示一个点,里面有坐标(x, y)

start, end:起点和终点

n, m:地图大小(长和宽)

step:记录节点起点的最短步数

dic:四个方向

map:输入的地图

ans:输出的地图(路径写在这里面)

常量:

M:最大地图大小

函数:

init():输入

bfs():bfs查找

rightful(int x, int y):此节点是否可走(rightful:正确的)

check():回寻

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值