迷宫问题

迷宫问题

使用队列和BFS算法来解决迷宫问题:

我们定义了一个MazeSolver类,它包含一个二维数组maze表示迷宫地图,以及迷宫的行数rows和列数cols。我们使用BFS算法来搜索从起点(startX, startY)到终点(endX, endY)的路径,具体实现如下:

  • 首先创建一个visited数组,用于标记每个位置是否已经访问过,初始时全部为false。

  • 创建一个队列queue,将起点(startX, startY)加入队列中,并将其标记为已访问。

  • 循环执行以下步骤,直到队列为空:

  • 弹出队列中的第一个位置(x, y)。

  • 如果(x, y)是终点(endX, endY),则搜索完成,返回true。

  • 遍历四个方向,对于每个方向,计算出下一个位置(nx, ny),如果下一个位置越界、是障碍物或已经访问过,则不能继续访问,否则将该位置加入队列中,并标记为已访问。

  • 如果队列为空仍然没有找到终点,则搜索失败,返回false。

  • 在上面的main方法中,我们创建了一个迷宫地图,并使用MazeSolver类来搜索从起点(0, 0)到终点(3, 3)的路径。如果找到了路径,则输出"可以到达终点",否则输出"无法到达终点"。

代码实现

package demo.data;

import java.util.LinkedList;
import java.util.Queue;

public class MazeSolver {
    private static final int[][] DIRS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 上下左右四个方向
    private int[][] maze; // 迷宫地图
    private int rows, cols; // 迷宫的行数和列数

    public MazeSolver(int[][] maze) {
        this.maze = maze;
        this.rows = maze.length;
        this.cols = maze[0].length;
    }

    public boolean solve(int startX, int startY, int endX, int endY) {
        boolean[][] visited = new boolean[rows][cols]; // 标记每个位置是否已经访问过
        Queue<int[]> queue = new LinkedList<>(); // 存储待访问的位置
        queue.offer(new int[] {startX, startY});
        visited[startX][startY] = true;

        while (!queue.isEmpty()) {
            int[] curr = queue.poll();
            int x = curr[0], y = curr[1];
            if (x == endX && y == endY) { // 找到了终点
                return true;
            }
            for (int[] dir : DIRS) { // 遍历四个方向
                int nx = x + dir[0], ny = y + dir[1];
                if (nx < 0 || nx >= rows || ny < 0 || ny >= cols || maze[nx][ny] == 1 || visited[nx][ny]) {
                    // 越界、障碍物或已经访问过,都不能继续访问
                    continue;
                }
                queue.offer(new int[] {nx, ny});
                visited[nx][ny] = true;
            }
        }
        return false; // 没有找到终点
    }

    public static void main(String[] args) {
        int[][] maze = {
                {0, 1, 0, 0},
                {0, 0, 0, 1},
                {1, 0, 1, 0},
                {0, 0, 0, 0}
        };
        MazeSolver solver = new MazeSolver(maze);
        boolean found = solver.solve(0, 0, 3, 3);
        System.out.println(found ? "可以到达终点" : "无法到达终点");
    }
}

定义了一个5×5的迷宫,用二维数组 maze 表示,并输出迷宫。

  • 接着,定义起点和终点的坐标为 (0, 0) 和 (4, 4),并定义队列 queue 和标记数组 visited,将起点加入队列,并标记起点已访问。
  • 定义方向数组 directions,依次为上、右、下、左,用于依次尝试四个方向。
  • 定义变量 endNode 用于存储最短路线,初始值为 null。
  • 接着,进行广度优先搜索,取出队列第一个元素,判断是否为终点,若是,则记录该节点并退出循环;否则,依次尝试四个方向,判断下一个位置是否越界或为墙壁,若是,则跳过;判断下一个位置是否已经访问过,若是,则跳过;否则,将下一个位置加入队列,并标

代码实现

package demo.data;

import java.util.LinkedList;

public class migong {
    public static void main(String[] args) {

            // 定义迷宫
            int[][] maze = {
                    {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}
            };
            // 输出迷宫
            System.out.println("迷宫:");
            for (int i = 0; i < maze.length; i++) {
                for (int j = 0; j < maze[i].length; j++) {
                    System.out.print(maze[i][j] + " ");
                }
                System.out.println();
            }
            // 定义起点和终点
            int startX = 0, startY = 0;
            int endX = 4, endY = 4;
            // 定义队列和标记数组
        LinkedList<Node> queue = new LinkedList<>();
            boolean[][] visited = new boolean[5][5];
            // 将起点加入队列
            queue.offer(new Node(startX, startY, 0, null));
            // 标记起点已访问
            visited[startX][startY] = true;
            // 定义方向数组,依次为上、右、下、左
            int[][] directions = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
            // 定义变量用于存储最短路线
            Node endNode = null;
            // 广度优先搜索
            while (!queue.isEmpty()) {
                // 取出队列第一个元素
                Node curr = queue.poll();
                // 如果当前位置是终点,记录该节点并退出循环
                if (curr.x == endX && curr.y == endY) {
                    endNode = curr;
                    break;
                }
                // 否则,依次尝试上、右、下、左四个方向
                for (int[] direction : directions) {
                    int nextX = curr.x + direction[0];
                    int nextY = curr.y + direction[1];
                    // 判断下一个位置是否越界或为墙壁,若是,则跳过
                    if (nextX < 0 || nextX >= 5 || nextY < 0 || nextY >= 5 || maze[nextX][nextY] == 1) {
                        continue;
                    }
                    // 判断下一个位置是否已经访问过,若是,则跳过
                    if (visited[nextX][nextY]) {
                        continue;
                    }
                    // 将下一个位置加入队列,并标记已访问
                    queue.offer(new Node(nextX, nextY, curr.step + 1, curr));
                    visited[nextX][nextY] = true;
                }
            }
            // 输出最短路线
            System.out.println("最短路线:");
            printPath(endNode);
        }

        // 输出一条路径
        public static void printPath(Node endNode) {
            if (endNode == null) {
                return;
            }
            printPath(endNode.parent);
            System.out.println("(" + endNode.x + ", " + endNode.y + ")");
        }

        // 定义节点类
        private static class Node {
            int x, y; //节点坐标
            int step; //到达该节点的步数
            Node parent; //到达该节点的上一节点

            public Node(int x, int y, int step, Node parent) {
                this.x = x;
                this.y = y;
                this.step = step;
                this.parent = parent;
            }
        }

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值