使用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] = ' '; } } } }