Java 佩格纸牌罐';无法找到回溯的解决方案

Java 佩格纸牌罐';无法找到回溯的解决方案,java,recursion,backtracking,Java,Recursion,Backtracking,我正在为Java中的Peg纸牌游戏开发一个解决方案。然而,我的解决方案似乎无法解决游戏 我使用的是“标准”版本,因此电路板看起来像: {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为peg,2为空 电路板的所需状态为 {2,

我正在为Java中的Peg纸牌游戏开发一个解决方案。然而,我的解决方案似乎无法解决游戏

我使用的是“标准”版本,因此电路板看起来像:

{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为peg,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()方法的工作原理如下:

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;
}
  • 沿
    方向(向上、向下、向左或向右)移动位置
    x、y
    上的销钉
  • 检查电路板是否处于所需状态,如果处于所需状态,请打印电路板并移动,然后退出程序
  • 检查是否还有可以移动的销钉,如果没有销钉,则退出该功能
  • 找到第一个可能在一个或多个方向上移动的销钉;为该桩调用solve(),并确定其方向
  • (如果我们到了这里,第4步产生了一个不希望出现的电路板状态)撤消第4步中的移动,并使用peg可能做出的下一个移动(如果有的话)调用第4步
  • 返回到步骤4,查看在步骤4中找到的销钉之后的下一个可能的销钉
  • 我已经像这样执行了上述指令:

    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;
    }
    
    private void play(整数xx,整数yy,方向){
    板移动(xx,yy,方向);
    if(board.finished()){
    印制板();
    系统输出打印项次(移动);
    系统出口(0);
    }
    if(board.noMoreMoves()){
    返回;
    }
    对于(int y=0;y
    但是,上述解决方案不会产生所需的板状态。这个版本在eclipse中运行了一个多小时,没有任何结果

    我已经分别测试了board.move(x,y,direction)、board.finished()、board.noMoreMoves()、board.containsPeg(x,y)、board.getMovesFor(x,y)和board.undoMove(x,y,direction)方法,它们似乎都能按预期运行


    在我的实现中,或者在递归/回溯中,这里是否缺少一些东西?我很确定解决方案不需要超过2亿次的移动。

    您需要的是一个调试策略

    使用将输出电路板状态的方法。还可以写一个保存电路板的表示,以及一个比较两种状态以确定它们是否相同的表示

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

    还要确保你不会多次跟踪同一个动作


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

    建议:使用较小的棋盘进行测试!最初有32个销钉。每一次移动都应该从棋盘上移除一个钉,如果只剩下一个钉,那么肯定没有有效的移动可以做,所以你绝对不应该让递归比31层更深。你确定
    board.move()
    移除了一个钉子吗?