java迷宫寻找最短路径

利用广度优先遍历算法的特点,由于迷宫每次只能走一格,所以对于任意一个节点,bfs第一次到达该点时一定是最短路径

直接上代码:

package com.common.utils;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;

/**
 * @ClassName Calculator
 * @Description:  java迷宫寻找最短路径
 * @Author: mischen
 * @date: 14:57 2022/11/24
 * @Version 1.0
 */
public class Maze {
    private class Node{
        int x;
        int y;
        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }
    private int[][] map;
    //起点
    private int startX;
    private int startY;
    //终点
    private int endX;
    private int endY;
    //代表上下左右四个可能走的方向
    private int[] dx = {1,0,-1,0};
    private int[] dy = {0,1,0,-1};
    public Maze(int[][] map, int startX, int startY, int endX, int endY) {
        this.map = map;
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;
    }
    public static void print(int[][] map) {
        for(int i=0; i<map.length; i++) {
            for(int j=0; j<map[0].length; j++) {
                System.out.printf("%4d",map[i][j]);
            }
            System.out.println();
        }
    }
    //广度优先遍历寻找迷宫所有点的最短路径, x,y是起始点
    public void bfs() {
        Deque<Node> quene = new ArrayDeque<>();
        //存储每个点的前驱节点,方便打印最短路径的路线
        int[][] pre = new  int[this.map.length][this.map[0].length];
        //存储每个点的最短路径
        int[][] dis = new  int[this.map.length][this.map[0].length];
        for(int i=0; i<dis.length; i++) {
            for(int j=0; j<dis[0].length; j++) {
                dis[i][j] = 100;
            }
        }
        //将起点入队,起点的距离设为0,并标记为已访问
        quene.add(new Node(this.startX, this.startY));
        dis[this.startX][this.startY] = 0;
        map[this.startX][this.startY] = 2;
        Node temp;
        //广度优先遍历所有可访问的点,并记下每个点的最短路径和前驱节点
        while(!quene.isEmpty()) {
            temp = quene.poll();
            //尝试每个点的四个方向
            for(int i=0; i<4; i++) {
                int tx = temp.x + dx[i];
                int ty = temp.y + dy[i];
                //如果该点没有访问过,将该点入队并标记为访问过
                if(map[tx][ty] == 0) {
                    //迷宫中每次只能走一步,所以距离加一
                    dis[tx][ty] = dis[temp.x][temp.y] + 1;
                    pre[tx][ty] = i;
                    map[tx][ty] = 2;
                    quene.add(new Node(tx, ty));
                }
            }
        }//到这里dis中存放的就是最短路径,下面时利用pre数组打印路径

        int a = this.endX;
        int b = this.endY;
        System.out.printf("从(%d,%d)到(%d,%d)的最短距离是:%d,路线为:\n",
                this.startX, this.startY, a, b, dis[a][b]);
        //倒序访问最短路径的路线并入栈
        Stack<Node> stack = new Stack<>();
        stack.add(new Node(a, b));
        while(a != this.startX || b != this.startY) {
            int da = dx[pre[a][b]];
            int db = dy[pre[a][b]];
            a = a - da;
            b = b - db;
            stack.add(new Node(a,b));
        }
        //出栈的顺序就是从起点到终点的路线
        while(!stack.isEmpty()) {
            Node p = stack.pop();
            System.out.printf("(%d,%d)->",p.x,p.y);
        }
    }
    public static void main(String[] args) {
        //创建一个迷宫并初始化
        int[][] map = new int[8][8];
        for(int i=0; i<map.length; i++) {
            for(int j=0; j<map[0].length; j++) {
                map[i][j] = 0;
            }
        }
        for(int i=0; i<map.length; i++) {
            map[i][0] = -1;
            map[i][7] = -1;
            map[0][i] = -1;
            map[7][i] = -1;
        }
        map[4][1] = -1;
        map[4][2] = -1;
        map[5][3] = -1;
        map[4][4] = -1;
        map[3][4] = -1;

        print(map);
        Maze maze = new Maze(map, 1, 1, 5, 2);
        maze.bfs();
    }
}

运行结果:
-1 -1 -1 -1 -1 -1 -1 -1
-1 0 0 0 0 0 0 -1
-1 0 0 0 0 0 0 -1
-1 0 0 0 -1 0 0 -1
-1 -1 -1 0 -1 0 0 -1
-1 0 0 -1 0 0 0 -1
-1 0 0 0 0 0 0 -1
-1 -1 -1 -1 -1 -1 -1 -1
从(1,1)到(5,2)的最短距离是:13,路线为:
(1,1)->(2,1)->(2,2)->(2,3)->(2,4)->(2,5)->(3,5)->(4,5)->(5,5)->(6,5)->(6,4)->(6,3)->(6,2)->(5,2)->

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值