Java迷宫中的回溯

时间:2015-05-04 02:12:27

标签: java backtracking maze

我正在编写一个程序,它基本上有一个使用java回溯搜索“pig”的对象。截至目前,我有猪移动和搜索,但它实际上无法“回溯”。我只是完全迷失了如何实际实现该段的代码,但我知道你会使用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;
}

1 个答案:

答案 0 :(得分:0)

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

作者注释

请注意,我使用的是Cell类和Maze类。变量&#34;矩阵&#34;是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,用于理解为什么会回溯以及为什么会有效。