Peg Solitaire无法找到回溯的解决方案

时间:2013-04-06 23:37:14

标签: java recursion backtracking

我正在研究Java游戏Peg Solitaire的解决方案。但是,似乎我的解决方案无法解决游戏问题。

我正在使用'标准'版本,所以董事会看起来像:

{2, 2, 1, 1, 1, 2, 2}
{2, 2, 1, 1, 1, 2, 2}
{1, 1, 1, 1, 1, 1, 1}
{1, 1, 1, 0, 1, 1, 1}
{1, 1, 1, 1, 1, 1, 1}
{2, 2, 1, 1, 1, 2, 2}
{2, 2, 1, 1, 1, 2, 2}

0为空,1为钉,2为无

董事会的理想状态是

{2, 2, 0, 0, 0, 2, 2}
{2, 2, 0, 0, 0, 2, 2}
{0, 0, 0, 0, 0, 0, 0}
{0, 0, 0, 1, 0, 0, 0}
{0, 0, 0, 0, 0, 0, 0}
{2, 2, 0, 0, 0, 2, 2}
{2, 2, 0, 0, 0, 2, 2}

我的solve()方法的工作原理如下:

  1. x,y(向上,向下,向左或向右)中的位置direction上移动挂钩
  2. 检查电路板是否处于所需状态,如果是,则打印板并移动并退出程序
  3. 检查是否还有可以移动的挂钩,如果没有退出该功能
  4. 找到可以在一个或多个方向上移动的第一个可能的钉子;为那个挂钩和它的方向调用solve()。
  5. (如果我们到达此处,第4步产生了一个不受欢迎的电路板状态)撤消在步骤4中进行的移动,并在下一个可能的移动时调用步骤4(如果有的话)。
  6. 返回步骤4,查看步骤4中找到的挂钩之后的下一个挂钩。
  7. 我已经实施了上述说明:

    private void play(int xx, int yy, Direction direction) {
        board.move(xx, yy, direction);
    
        if (board.finished()) {
            board.printBoard();
            System.out.println(moves);
            System.exit(0);
        }
    
        if (board.noMoreMoves()) {
            return;
        }
    
        for (int y = 0; y < board.board.length; y++) {
            for (int x = 0; x < board.board[y].length; x++) {
                if (board.containsPeg(x, y)) {
                    Direction[] moves = board.getMovesFor(x, y);
    
                    for (Direction move : moves) {
                        if (move != null) {
                            this.moves++;
                            play(x, y, move);
    
                            if (move.equals(Direction.UP)) {
                                board.undoMove(x, y-2, move);
                            } else if (move.equals(Direction.DOWN)) {
                                board.undoMove(x, y+2, move);
                            } else if (move.equals(Direction.LEFT)) {
                                board.undoMove(x-2, y, move);
                            } else if (move.equals(Direction.RIGHT)) {
                                board.undoMove(x+2, y, move);
                            }
                        }
                    }
                }
            }
        }
    
        return;
    }
    

    然而,上述解决方案不能产生所需的电路板状态。我现在这个版本在eclipse中运行了一个多小时,没有任何结果。

    我测试了方法board.move(x,y,direction),board.finished(),board.noMoreMoves(),board.containsPeg(x,y),board.getMovesFor(x,y )和board.undoMove(x,y,direction)处于隔离状态,它们似乎都按预期运行。

    我在这里是否遗漏了一些东西,无论是在我的实现中还是在递归/回溯中?我非常确定该解决方案不需要超过<2>百万次的移动。

1 个答案:

答案 0 :(得分:0)

您需要的是一种调试策略。

使用可输出电路板状态的方法。另外写一个将保存您的电路板表示的电路,以及一个比较两个状态以查看它们是否相同的电源。

第一种方法失败后的输出,然后是回溯后的不同点,以确保回溯已回溯到正确的轨道。

同时确保您不会多次跟踪同一个动作。

至于可能的移动次数,不要太确定。人们不会认为,先验,国际象棋的前10-20次移动中有数十亿次可能的移动,但有。