蛇和梯子-增加计算机转弯和掷骰子的延迟

时间:2018-08-07 11:03:31

标签: java recursion javafx timertask delayed-execution

我正在创建游戏《蛇与梯子》。我使用的游戏模式可以让您在计算机上玩游戏。

人类玩家掷骰子时,将调用rollTheDiceAndMove方法。我们等待1秒钟(骰子正在滚动...)。然后我们调用move函数,该函数实际上将片段移动到指定的图块。如果碰到了蛇或梯子,我想再等1秒钟,然后再转到最后一块瓷砖。例如。我等待1秒钟,然后滚动5,然后在前面放my_current_pos + dice_roll砖,然后再移动一块。如果蛇或梯子撞到了:另一个延迟,然后递归再次移动。

最后,如果选择了“反对计算机”模式,那么当人类玩家移动时,我想等一秒钟,然后计算机自动掷骰子。如下所示,我正在使用TimerTimerTask类,但是它很复杂,因为Timer范围内的任何内容都会在一段时间后执行,但是计时器外部的代码会无延迟地执行这导致了我很多错误和异步。

您建议使用什么来创建此延迟?

public void rollTheDiceAndMove() {
    int diceRoll = gameBoard.rollDice();
    // delay for dice roll.

    new Timer().schedule(
        new TimerTask() {
            @Override
            public void run() {
                Platform.runLater(new Runnable() {
                    @Override
                    public void run() {
                        ////////////////////////////////////////////////////////////////////////////

                        gameGUI.indicateDiceRoll(diceRoll);
                        int newIndex = getPlayerIndexAfterRoll(diceRoll);
                        move(newIndex);
                        System.out.println("change turns");
                        swapTurns();
                        System.out.println(isComputerTurn());
                        gameGUI.updateCurrentTurnLabel();


                        if (newIndex == GameBoard.WIN_POINT) {
                            boolean restartGame = gameBoard.playAgainOrExit();

                            if (restartGame) {
                                Player winner = gameBoard.getCurrentPlayer();
                                gameGUI.updateScore(winner);
                                gameGUI.playAgain();
                            } else {
                                System.exit(0);
                            }
                        }

                        ////////////////////////////////////////////////////////////////////////////
                    }
                });
            }
        }, GameBoard.DICE_ROLL_DELAY
    );

    // try to recursively call this method again for computer turn.
}


public void move(int currentIndex) {
    int[] newCoordinates = gameBoard.getBoardCoordinates(GameBoard.NUMBER_OF_TILES - currentIndex);

    gameBoard.getCurrentPlayer().getPlayerPiece().setPosition(currentIndex);
    gameGUI.movePieceImages(newCoordinates[0], newCoordinates[1]);

    if (gameBoard.getTile(currentIndex).containsLadderOrSnake()) {
        // delay for moving to second tile.

        new Timer().schedule(
            new TimerTask() {
                @Override
                public void run() {
                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {

                            int updatedIndex = gameBoard.getUpdatedPosition(currentIndex);
                            move(updatedIndex);


                        }
                    });
                }
            }, GameBoard.SECOND_MOVE_DELAY *2
        );

        return;             // we need to return 'cause of recursion. Swap turns will be executed twice, one time for the initial call and the other time on above line.
    }
}

2 个答案:

答案 0 :(得分:1)

您可以使用java.util.concurrent包中的ScheduledThreadPoolExecutor类的调度方法

  

进度表(可运行命令,长时间延迟,TimeUnit单位)创建并   执行一次操作,在指定的延迟后启用。

在那之后,您可以检查Future对象是否完成任务。

public void rollTheDiceAndMove() {
    int diceRoll = gameBoard.rollDice();
    // delay for dice roll.
    ScheduledFuture<Void> scheduledFuture = Executors.newScheduledThreadPool(1).schedule(new TimerTask() {
        @Override
        public void run() {
            Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    ////////////////////////////////////////////////////////////////////////////

                    gameGUI.indicateDiceRoll(diceRoll);
                    int newIndex = getPlayerIndexAfterRoll(diceRoll);
                    move(newIndex);
                    System.out.println("change turns");
                    swapTurns();
                    System.out.println(isComputerTurn());
                    gameGUI.updateCurrentTurnLabel();


                    if (newIndex == GameBoard.WIN_POINT) {
                        boolean restartGame = gameBoard.playAgainOrExit();

                        if (restartGame) {
                            Player winner = gameBoard.getCurrentPlayer();
                            gameGUI.updateScore(winner);
                            gameGUI.playAgain();
                        } else {
                            System.exit(0);
                        }
                    }

                    ////////////////////////////////////////////////////////////////////////////
                }
            });
        }
    }, GameBoard.DICE_ROLL_DELAY, TimeUnit.SECONDS);

    // here we wait and don't go to next actions until run() method of TimerTask is finished.
    // we can specify wait timeout value if needed.
    scheduledFuture.get();


    // try to r

另一个问题是Platform.runLater调用也是异步的,您将无法获得任何结果。在Java FX Task中可以用来实现相同的目的:

Platform.runLater and Task in JavaFX

竞争示例如下:

public void rollTheDiceAndMove() {
    int diceRoll = gameBoard.rollDice();
    // delay for dice roll.
    ScheduledFuture<Void> scheduledFuture = Executors.newScheduledThreadPool(1).schedule(
            new Task<Void>() {
                        @Override
                        public Void call() {
                            ////////////////////////////////////////////////////////////////////////////
                            gameGUI.indicateDiceRoll(diceRoll);
                            int newIndex = getPlayerIndexAfterRoll(diceRoll);
                            ScheduledFuture<Void> moveScheduledFuture = move(newIndex);
                            if(moveScheduledFuture != null) {
                                moveScheduledFuture.get();
                            }

                            System.out.println("change turns");
                            swapTurns();
                            System.out.println(isComputerTurn());
                            gameGUI.updateCurrentTurnLabel();


                            if (newIndex == GameBoard.WIN_POINT) {
                                boolean restartGame = gameBoard.playAgainOrExit();

                                if (restartGame) {
                                    Player winner = gameBoard.getCurrentPlayer();
                                    gameGUI.updateScore(winner);
                                    gameGUI.playAgain();
                                } else {
                                    System.exit(0);
                                }
                            }

                            ////////////////////////////////////////////////////////////////////////////
                            return null;
                        }
            }, GameBoard.DICE_ROLL_DELAY, TimeUnit.SECONDS);

    scheduledFuture.get();
    // try to recursively call this method again for computer turn.
}


public ScheduledFuture<Void> move(int currentIndex) {
    int[] newCoordinates = gameBoard.getBoardCoordinates(GameBoard.NUMBER_OF_TILES - currentIndex);

    gameBoard.getCurrentPlayer().getPlayerPiece().setPosition(currentIndex);
    gameGUI.movePieceImages(newCoordinates[0], newCoordinates[1]);

    if (gameBoard.getTile(currentIndex).containsLadderOrSnake()) {
        // delay for moving to second tile.

      return   Executors.newScheduledThreadPool(1).schedule(
                new Task<Void>() {
                    @Override
                    public Void call() {
                                int updatedIndex = gameBoard.getUpdatedPosition(currentIndex);
                                move(updatedIndex);

                    }
                }, GameBoard.SECOND_MOVE_DELAY *2, TimeUnit.SECONDS);

        // we need to return 'cause of recursion. Swap turns will be executed twice, one time for the initial call and the other time on above line.
    }
    return null;
}

答案 1 :(得分:1)

创建项目的副本,然后尝试使用PauseTransition

public void rollTheDiceAndMove() 
{
    int diceRoll = gameBoard.rollDice();
    System.out.println("Player: rolling the dice");

    PauseTransition pause = new PauseTransition(Duration.seconds(1));
    pause.setOnFinished(event ->{
        System.out.println("1 second after rolling the dice");
        gameGUI.indicateDiceRoll(diceRoll);
        int newIndex = getPlayerIndexAfterRoll(diceRoll);
        playerMove(newIndex);
        if(checkWin(Player))
        {
            System.out.println("Player won!");                
        }
        else
        {
            System.out.println("change turns");
            swapTurns();
            System.out.println(isComputerTurn());
            gameGUI.updateCurrentTurnLabel();
            computerRollDiceAndMove();
        }






    });
    pause.play();
}


public void computerRollDiceAndMove()
{
    int diceRoll = gameBoard.rollDice();
    System.out.println("Computer: rolling the dice");

    PauseTransition pause = new PauseTransition(Duration.seconds(1));
    pause.setOnFinished(event ->{
        System.out.println("1 second after rolling the dice");
        gameGUI.indicateDiceRoll(diceRoll);
        int newIndex = getComputerIndexAfterRoll(diceRoll);
        computerMove(newIndex);
        if(checkWin(computer))
        {
            System.out.println("Computer won!");
        }
        else{
            System.out.println(isComputerTurn());
            gameGUI.updateCurrentTurnLabel();
        }
    });
    pause.play();   
}