打破听众的递归

我试图打破一个使这段代码递归的特殊情况。

我有一个Javafx游戏,其中有人和计算机玩家在轮到他的时候玩,并且可以有很多回合。

计算机应该自动播放并立即移动到下一个播放器并且不向UI显示任何直接指示(但是可以查看它之后做了什么)。

问题是在只有电脑玩家的情况下,我们会在当前装载电脑的时候来到这里,输入条件,因为所有玩家都是电脑,设置下一个播放器的电路板,然后无需完成通话,请拨打此电话同样的function:

  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 } }); 

取而代之的是,如果我在GameManagercurrentPlayer属性订阅一个监听器,那么我仍然需要从该监听器调用setNextPlayer() ,这又是递归的。

如果所有玩家都是计算机,我可以制作一个特例,然后从一段while(true){}而不是听众和绑定运行游戏,但必须有更好的方法来打破这种递归。

还有一种方法是在没有听众和绑定的情况下不进入递归吗?

笔记:

currentBoardPane表示屏幕上的当前游戏板,它是一个ObjectProperty

对您的代码做出以下假设:

  1. 目前一切都在FX应用程序线程上运行
  2. currentBoardPane.setValue(...)导致UI更新(因此每次移动都会更新UI)

那么“快速而肮脏”的方法是:

 currentBoardPane.addListener((e) -> { if(gameManager.checkIfCurrentPlayerIsComputer()){ gameManager.playAutoMovesForCurrentPlayer(); //update board on scene Platform.runLater(() -> { gameManager.setNextPlayer(); // it does current player property = next player currentBoardPaneIndex = ((currentBoardPaneIndex + 1) % gameManager.getPlayers().size()); currentBoardPane.setValue(boardPanes.get((currentBoardPaneIndex))); //this is a recursive call }); } }); 

这会将更新委托给新的Runnable ,可以在FX Application Thread上执行的计划,并立即退出处理程序。 因此,对currentBoardPane.setValue(...)的调用稍后执行,不再递归。

事实上,如果你做了一点工作:

 private final Executor aiExecutor = Executors.newSingleThreadExecutor(); // ... currentBoardPane.addListener((e) -> { if(gameManager.checkIfCurrentPlayerIsComputer()){ Task makeMoveTask = new Task() { @Override protected Void call() { gameManager.playAutoMovesForCurrentPlayer(); return null ; } }; makeMoveTask.setOnSucceeded(e -> { //update board on scene gameManager.setNextPlayer(); // it does current player property = next player currentBoardPaneIndex = ((currentBoardPaneIndex + 1) % gameManager.getPlayers().size()); currentBoardPane.setValue(boardPanes.get((currentBoardPaneIndex))); //this is a recursive call }); aiExecutor.execute(makeMoveTask); } }); 

那么这就是你要使用的代码,如果计算移动花了足够的时间来阻止UI发生时是不可接受的。 (如果计算移动只需要很少的时间,这仍然可以正常工作。)这假设playAutoMovesForCurrentPlayer()不会更新UI。