【发布时间】:2016-09-08 16:20:54
【问题描述】:
我试图打破使此代码递归的特殊情况。
我有一个 Javafx 游戏,其中有人类和计算机玩家在轮到他的时候玩,并且可能有很多轮。
计算机应该自动播放并立即移动到下一个播放器,并且不会直接向 UI 显示任何指示(但可以查看它之后的操作)。
问题是在只有电脑玩家的情况下,我们会在加载currentBoardPane的那一刻来到这里,进入所有玩家都是电脑的条件,设置下一个玩家的棋盘,然后没有完成调用,再次调用相同的函数:
currentBoardPane.addListener((e) -> {
if(gameManager.checkIfCurrentPlayerIsComputer()){
gameManager.playAutoMovesForCurrentPlayer();
gameManager.setNextPlayer(); // it does current player property = next player
//update board on scene
currentBoardPaneIndex = ((currentBoardPaneIndex + 1) % gameManager.getPlayers().size());
currentBoardPane.setValue(boardPanes.get((currentBoardPaneIndex))); //this is a recursive call
}
});
如果我订阅了GameManager 中的currentPlayer 属性的侦听器,那么我仍然需要从该侦听器调用setNextPlayer(),而这又是递归的。
如果所有玩家都是计算机,我可以做一个特殊情况,然后从 while(true){} 运行游戏而不是侦听器和绑定,但必须有更好的方法来打破这种递归。
有没有办法在仍然有侦听器和绑定的同时不进入递归?
注意事项:
currentBoardPane 表示屏幕上的当前游戏板,它是ObjectProperty。
【问题讨论】:
-
如果
playAutoMovesForCurrentPlayer()方法花费了很长时间(例如,您正在下棋,或其他需要大量计算移动的游戏),那么您将调用playAutoMovesForCurrentPlayer()一个Task,在后台线程上执行它,并在onSucceeded处理程序中执行剩余的代码(setNextPlayer(),更新索引和窗格)。这会破坏递归,因为您的处理程序不会直接调用更改。如果您知道移动接近瞬时,这可能不是一个理想的解决方案,但它会解决问题。 -
这是一个简单的游戏,“AI”只是随机选择,所以它是即时的。
-
是的,但它仍然可以解决问题。如果我理解正确,每个动作都会更新 UI,对吗?因此,如果您使用了您提出的解决方案 (
while (true) { doMoves(); }),则必须将其放在后台线程中并使用Platform.runLater(...)更新 UI,否则您将看不到 UI 更改(直到循环完成,看起来像它永远不会发生)。因此,无论哪种方式,您都需要使用后台线程。 -
while 循环将调用使用事件或侦听器更新 UI 的方法,但它仍然会阻塞 javafx 主线程直到它完成?那么我可能更喜欢使用你的第一个建议。
-
如果它在 FX 应用程序线程上运行,那么是的,它将阻塞该线程直到它完成。 (如果不是,你已经在创建一个后台线程,所以无论哪种方式你都在使用线程。)
标签: java recursion javafx java-8 javafx-8