First of all: M-VC
Separate Game from GUI - a suitable approach might be M-VC (Model-View/Controller). If you do it right, there should be NO REFERENCE on the game towards the controller, but the controller knows about the game. Doing it that way you can create controllers for any GUI you want (Android, JavaFX, TCP/IP) without ever changing the game.
Listener vs Polling
since you have a turn-based application you don't need neither nor. It is sufficient to get GUI-updates only when some action is performed. Actions are performed, when you press a button on your GUI (e.g. when you push with your mouse on the draw card button). To react on such an event you usually add action Listeners on the according buttons and delegate this action to the model, wich itself returns an animation. The controller is now responsible to draw this animation in a fancy way
AI-Turn
so what to do when a Player is an AI player? Your Model should already provide methods for the human player, e.g. Animation drawCard() that executes an action and returns an animation. When a computer player now performs its turn it does the same as a human player, but it returns a bulk of action for it's whole turn see List<Animation> Player.playAiTurn() where all the actions from the ai player are performed and accumulated. The ai turn starts immediately after the human player ended its turn. Again the controller is responsible for drawing these animations in a fancy way.
AI vs. AI
same applies as by AI vs. human
example snippets
AI vs. AI turn is controlled in the controller:
private final Game game;
public Controller(Game game){
this.game = game;
}
public void startGame(){
do {
Player current = game.getCurrentPlayer();
if(player.isAI()){
List<Animation> animations = playercurrent.performAiTurn();
drawAnimations(animations); //in a fancy way
game.endTurn();
}
//else wait for human player to end its turn via button
}while(!game.isGameOver());
}
