【问题标题】:Java backtracking in a maze迷宫中的Java回溯
【发布时间】:2015-05-04 02:12:26
【问题描述】:

我正在编写一个程序,它本质上将有一个对象通过使用 java 回溯来搜索“猪”。截至目前,我让猪移动和搜索,但它实际上无法“回溯”。我完全不知道如何实际实现该段的代码,但我知道您会使用 pathIndex-- 来减少路径长度。任何有关如何执行此操作的帮助都会非常有帮助。

public class MazeWalker {
    /**
     * The possible states of the current "walk" through a maze.
     */
    public enum WalkerState {
        /**
         * Indicates that the maze walker has reached its assigned destination.
         */
        THERE_ALREADY,

        /**
         * Indicates that the maze walker has concluded that it is impossible to
         * reach its destination.
         */
        IMPOSSIBLE_TO_GET_THERE,

        /**
         * Indicates that the maze walker would like to move left.
         */
        MOVE_LEFT,

        /**
         * Indicates that the maze walker would like to move up.
         */
        MOVE_UP,

        /**
         * Indicates that the maze walker would like to move right.
         */
        MOVE_RIGHT,

        /**
         * Indicates that the maze walker would like to move down.
         */
        MOVE_DOWN
    }

    /**
     * Initializes the MazeWalker, providing it with the maze to use and the
     * walker's destination.
     */
    public MazeWalker(Maze maze, int destinationX, int destinationY) {
        this.maze = maze;
        this.destinationX = destinationX;
        this.destinationY = destinationY;

        // The path stack starts out empty.
        path = new WalkerState[this.maze.getMazeWidth() * this.maze.getMazeHeight()];
        pathIndex = -1;

        // The "been-there" array starts off completely clear.
        beenThere = new boolean[this.maze.getMazeHeight()][this.maze.getMazeWidth()];
        for (int row = 0; row < beenThere.length; row++) {
            for (int column = 0; column < beenThere[row].length; column++) {
                beenThere[row][column] = false;
            }
        }
    }

    /**
     * Takes a step toward reaching the given destination from the given current
     * location, and returns either the direction of the next step, whether or
     * not that destination has been reached, or whether that destination is
     * impossible to reach.
     */
    public WalkerState areWeThereYet(int currentX, int currentY) {
      ///currentWalkerState =

      if ((currentX == destinationX) && (currentY == destinationY)) {
        return WalkerState.THERE_ALREADY;

      } else if (maze.getLocation(currentX, currentY).getRight().isOpen() && !beenThere[currentY][currentX + 1]) {

      ///  currentWalkerState = WalkerState.MOVE_RIGHT;
        pathIndex++;
        path[pathIndex] = WalkerState.MOVE_RIGHT;
        return WalkerState.MOVE_RIGHT;

      } else if (maze.getLocation(currentX, currentY).getLeft().isOpen() && !beenThere[currentY][currentX - 1]) {

      ///  currentWalkerState = WalkerState.MOVE_LEFT;
        pathIndex++;
        path[pathIndex] = WalkerState.MOVE_LEFT;
        return WalkerState.MOVE_LEFT;

      } else if (maze.getLocation(currentX, currentY).getAbove().isOpen() && !beenThere[currentY + 1][currentX]) {

      ///  currentWalkerState = WalkerState.MOVE_UP;
        pathIndex++;
        path[pathIndex] = WalkerState.MOVE_UP;
        return WalkerState.MOVE_UP;

      } else if (maze.getLocation(currentX, currentY).getBelow().isOpen() && !beenThere[currentY - 1][currentX]) {

      ///  currentWalkerState = WalkerState.MOVE_DOWN;
        pathIndex++;
        path[pathIndex] = WalkerState.MOVE_DOWN;
        return WalkerState.MOVE_DOWN;
      }
        ///Returning 6 different values///
        ///MazeWalker is the thing thats moving///
        ///MazeWalker is initialized with a Maze Object with the desired destination coordinates///
        ///Steve's initial location is sx, sy///
        ///Pig's location is px, py///

      return WalkerState.IMPOSSIBLE_TO_GET_THERE;
    }

    /**
     * Returns a representation of the locations which the walker has visited.
     * The 2D array's dimensions should correspond to those of the walker's
     * assigned maze.
     */
    public boolean[][] getBeenThere() {
        return beenThere;
    }

    /**
     * Returns the current path taken by the walker.
     */
    public WalkerState[] getCurrentPath() {
        WalkerState[] currentPath = new WalkerState[pathIndex + 1];
        for (int i = 0; i < pathIndex + 1; i++) {
            currentPath[i] = path[i];
        }
        return currentPath;
    }

    /**
     * The data structure for maintaining the current path.
     */
    private WalkerState[] path;

    /**
     * The index for the current node in the path.
     */
    private int pathIndex;

    /**
     * The data structure for keeping track of "passed" squares.
     */
    private boolean[][] beenThere;

    /**
     * The maze that is being walked.
     */
    private Maze maze;

    /**
     * The x-coordinate of the walker's destination.
     */
    private int destinationX;

    /**
     * The y-coordinate of the walker's destination.
     */
    private int destinationY;
}

【问题讨论】:

  • 请对代码和代码 sn-ps、HTML/XML 等结构化文档或输入/输出使用代码格式。为此,请选择文本并单击消息发布/编辑表单顶部的{} 按钮。

标签: java backtracking maze


【解决方案1】:

我实际上是用 C++ 编写的,但是这些想法可以很容易地转移到 Java 中。请注意,在实现回溯算法方法时,通常使用递归

作者备注

请注意,我使用了 Cell 类和 Maze 类。变量“matrix”是 Maze 类中的一个二维数组,矩阵中的每个 [row][column] 位置都包含一个 Cell 对象。每个 Cell 都保存着布尔变量,这些变量决定了它的属性(它是一堵墙吗?它是否被访问过?它是开始吗?还是结束?等等)。

回溯迷宫求解器

/**
 * determines whether path to maze can be found using backtracking 
 * algorithm
 */

 bool MazeSolver::backtrackingFindPath(Cell toCell) {

    // if cell moving to is not valid, return false
    if (!maze.isValidMove(toCell)) {
        return false;
    }

    // (base case) if cell moving to is finish, return true
    if (maze.matrix[toCell.getRow()][toCell.getCol()].getIsFinish()) {
        return true;
    }

    // if cell moving to is already visited, return false
    if (maze.matrix[toCell.getRow()][toCell.getCol()].getIsVisited()) {
        return false;
    }

    else {

        // get row and column of cell moving to
        int row = toCell.getRow();
        int col = toCell.getCol();

        // move to this cell in maze and set as visited
        // store cell moved to in solution path
        maze.move(maze.matrix[row][col]);

        // if simply returned function call, first invalid cell would
        // return a false value and exit function
        // by wrapping in if statement, still calls function recursively
        // but only returns value if moves to maze to stop recursion

        // recurse north / up, if moves to finish, return true
        if (backtrackingFindPath(maze.matrix[row - 1][col]) == true)
            return true;
        // recurse east / right
        if (backtrackingFindPath(maze.matrix[row][col + 1]) == true)
            return true;
        // recurse south / down
        if (backtrackingFindPath(maze.matrix[row + 1][col]) == true)
            return true;
        // recurse west / left
        if (backtrackingFindPath(maze.matrix[row][col - 1]) == true)
            return true;

        // no valid or unvisited cells were available from this cell
        // set as bad path and remove from solution path
        maze.unmove(maze.matrix[toCell.getRow()][toCell.getCol()]);

        // return false and go back to previous function call
        return false;
    }
}

辅助方法

确定是否真的可以在迷宫中移动。

/**
 * is valid move
 */
bool isValidMove(Cell toCell) {

    int row = toCell.getRow();
    int col = toCell.getCol();

    // check if within bounds of maze
    if ((row >= 0 && row < rows) && (col >= 0 && col < cols)) {

        // if not a wall
        if (!matrix[row][col].getIsWall()) {

            // if not a bad path
            if (!matrix[row][col].getIsBadPath()) {
                return true;
            }
        }
    }
    return false;
}

实际上是移动,将 Cell 推到代表解决方案路径的堆栈上。

/**
 * move (forward) in maze
 */
void move(Cell goodCell) {

    // set cell moving to as visited
    matrix[goodCell.getRow()][goodCell.getCol()].setIsVisited(true);

    // update current location in maze to cell moving
    setCurrent(goodCell);

    // store cell moved to in stack (solution path)
    path.push(goodCell);
}

后退,从代表解决方案路径的堆栈中弹出最近保存的 Cell。

/**
 * unmove (move back) in maze
 */
void unmove(Cell badCell) {

    // set cell leaving as bad path
    matrix[badCell.getRow()][badCell.getCol()].setIsBadPath(true);
    matrix[badCell.getRow()][badCell.getCol()].setIsVisited(false);

    // remove cell leaving from stack (solution path)
    path.pop();
}

这是一个good reference,用于了解为什么这是回溯以及它为什么有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    相关资源
    最近更新 更多