Snakes And Ladders - 在电脑转动和掷骰子时添加延迟
Snakes And Ladders - Add delay on computer turn and on dice roll
我正在制作蛇梯游戏。我用的是可以和电脑对战的游戏模式
当人类玩家掷骰子时,会调用 rollTheDiceAndMove
方法。我们等待 1 秒(骰子正在滚动......)。然后我们调用 move
函数实际将棋子移动到指定的图块。如果一条蛇或梯子被击中,我想再等 1 秒再去最后的瓷砖。例如。我等了 1 秒,然后掷出 5,我走到前面的 my_current_pos + dice_roll
个方块,然后移动棋子。如果蛇或梯子撞到:再次延迟并再次递归移动。
最后,如果选择"Against Computer"模式,当人类玩家移动时,我想再等一秒钟,然后计算机自动掷骰子。正如您在下面看到的,我正在使用 Timer
和 TimerTask
类 但它非常复杂,因为 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.
}
}
您可以使用 java.util.concurrent 包
中的 ScheduledThreadPoolExecutor class 的调度方法
schedule(Runnable command, long delay, TimeUnit unit) Creates and
executes a one-shot action that becomes enabled after the given delay.
之后您可以检查 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;
}
创建项目的副本并尝试使用 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();
}
我正在制作蛇梯游戏。我用的是可以和电脑对战的游戏模式
当人类玩家掷骰子时,会调用 rollTheDiceAndMove
方法。我们等待 1 秒(骰子正在滚动......)。然后我们调用 move
函数实际将棋子移动到指定的图块。如果一条蛇或梯子被击中,我想再等 1 秒再去最后的瓷砖。例如。我等了 1 秒,然后掷出 5,我走到前面的 my_current_pos + dice_roll
个方块,然后移动棋子。如果蛇或梯子撞到:再次延迟并再次递归移动。
最后,如果选择"Against Computer"模式,当人类玩家移动时,我想再等一秒钟,然后计算机自动掷骰子。正如您在下面看到的,我正在使用 Timer
和 TimerTask
类 但它非常复杂,因为 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.
}
}
您可以使用 java.util.concurrent 包
中的 ScheduledThreadPoolExecutor class 的调度方法schedule(Runnable command, long delay, TimeUnit unit) Creates and executes a one-shot action that becomes enabled after the given delay.
之后您可以检查 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;
}
创建项目的副本并尝试使用 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();
}