使用Java破解二维迷宫

假设有一个二维网格迷宫,左上角为起点,右下角为终点。迷宫中存在障碍点无法到达,问迷宫是否有解,有则显示路线。

 

import java.util.Stack;

/**
 * 二维迷宫,默认8*8,起点左上角,终点右下角,只允许上下左右移动
 */
public class Test2 {

    /**
     * 记录迷宫状态的二维数组
     */
    private static char[][] board;
    private static int size = 8;

    /**
     * 目前正在探索的点
     */
    private static int[] nowPoint = new int[]{0, 0};

    /**
     * 目前的探索路线记录于这个栈
     */
    private static Stack<int[]> solution = new Stack<>();

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        int barrierNum = size * size / 3;
        for (int i = 0; i < barrierNum; i++) {
            int bx = (int) (Math.random() * size) + 1;
            int by = (int) (Math.random() * size) + 1;
            setBarrier(bx, by);
        }
        solve();
    }

    private static void solve() {
        solution.push(nowPoint.clone());  //这里注意要复制一个新的数组
        if (goNext()) {
            for (int[] point : solution) {
                board[point[0]][point[1]] = '*';
            }
            showBoard();
        } else {
            showBoard();
            System.out.print("No solution");
        }
    }

    /**
     * 确认这个点能否通向终点
     */
    private static boolean goNext() {
        //checkEverything();

        //注意优先向下方和右方的探索
        if (down(nowPoint)) {
            nowPoint[0] += 1;
            if (processStack()) return true;
        }
        if (right(nowPoint)) {
            nowPoint[1] += 1;
            if (processStack()) return true;
        }
        if (up(nowPoint)) {
            nowPoint[0] -= 1;
            if (processStack()) return true;
        }
        if (left(nowPoint)) {
            nowPoint[1] -= 1;
            if (processStack()) return true;
        }
        return false;
    }

    /**
     * 确认这个方向(上下左右)是否能到终点,并处理探索路线
     */
    private static boolean processStack() {
        solution.push(nowPoint.clone());
        if (isGoal(nowPoint)) {
            return true;
        } else {
            if (goNext()) {
                return true;
            } else {
                solution.pop();
                nowPoint = solution.peek().clone();
            }
        }
        return false;
    }

    /**
     * 确认是否到达终点
     */
    private static boolean isGoal(int[] point) {
        return point[0] == size - 1 && point[1] == size - 1;
    }

    /**
     * 确认下方是否有障碍,是不是走过的点。
     * 下面3个方法类似
     */
    private static boolean down(int[] nowPoint) {
        int row = nowPoint[0];
        int column = nowPoint[1];
        if (row >= size - 1) {
            return false;
        }
        if (board[row + 1][column] != ' ') {
            return false;
        }
        return isNewPoint(row + 1, column);
    }

    private static boolean up(int[] nowPoint) {
        int row = nowPoint[0];
        int column = nowPoint[1];
        if (row <= 0) {
            return false;
        }
        if (board[row - 1][column] != ' ') {
            return false;
        }
        return isNewPoint(row - 1, column);
    }

    private static boolean left(int[] nowPoint) {
        int row = nowPoint[0];
        int column = nowPoint[1];
        if (column <= 0) {
            return false;
        }
        if (board[row][column - 1] != ' ') {
            return false;
        }
        return isNewPoint(row, column - 1);
    }

    private static boolean right(int[] nowPoint) {
        int row = nowPoint[0];
        int column = nowPoint[1];
        if (column >= size - 1) {
            return false;
        }
        if (board[row][column + 1] != ' ') {
            return false;
        }
        return isNewPoint(row, column + 1);
    }

    /**
     * 确认这个点是否已经存在于探索路线
     */
    private static boolean isNewPoint(int row, int column) {
        for (int i = solution.size() - 1; i >= 0; i--) {
            //这里注意从后往前遍历
            int[] oldPoint = solution.get(i);
            if ((oldPoint[0] == row) && (oldPoint[1] == column)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 设置障碍
     */
    public static void setBarrier(int[][] list) {
        for (int[] b : list) {
            if (b.length == 2) {
                setBarrier(b[0], b[1]);
            } else {
                System.out.println("Invalid input");
                return;
            }
        }
    }

    /**
     * 设置障碍
     */
    public static void setBarrier(int i, int j) {
        if (checkNum(i) || checkNum(j)) {
            System.out.println("Invalid input");
            return;
        }
        if ((i == 1 && j == 1) || (i == size && j == size)) {
            System.out.println("The start point and end point can't be barricaded");
            return;
        }
        board[i - 1][j - 1] = '\u2588';
    }

    private static boolean checkNum(int n) {
        return n <= 0 || n > size;
    }

    /**
     * 显示目前探索情况
     */
    private static void checkEverything() {
        System.out.println("Now point:" + nowPoint[0] + ", " + nowPoint[1]);
        System.out.print("Now Stack:");
        for (int[] point : solution) {
            System.out.printf("(%d, %d)", point[0], point[1]);
        }
        System.out.println();
    }

    /**
     * 使用控制台显示迷宫状态
     */
    public static void showBoard() {
        showALine();
        for (int i = 0; i < size; i++) {
            System.out.print("|");
            for (int j = 0; j < size; j++) {
                System.out.print(" " + board[i][j] + " |");
            }
            System.out.println();
            showALine();
        }
    }

    private static void showALine() {
        for (int i = 0; i < size; i++) {
            System.out.print("----");
        }
        System.out.println("-");
    }

    public static int getSize() {
        return size;
    }

    public static void setSize(int size) {
        if (size >= MIN_SIZE && size < MAX_SIZE) {
            Test2.size = size;
        }
    }

    private static final int MAX_SIZE = 20;
    private static final int MIN_SIZE = 2;

    static {
        board = new char[size][size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                board[i][j] = ' ';
            }
        }
    }
}

 

posted @ 2019-04-06 12:40  Elucidator  阅读(393)  评论(0编辑  收藏  举报