3
\$\begingroup\$

I'm developing the simple Tic Tac Toe game in Java and got stuck on the game loop architecture.

The game must support local, remote and automatic players. The graphical interface is based on JavaFX.

How can I best structure the game loop so that the game logic is as separate as possible from the graphic interface?

I have thought of two approaches to solve this problem

Approach 1 - wait/notify

The simplest approach I thought of is to develop classes for each type of player (remote, interactive and automatic) and implement the necessary code within the mark (Board) method. The update method iterates the players and for each one executes the mark method. In the case of the AI, no problem, but in the case of the interactive player I would find myself having to pause the current thread while waiting for input from the graphic interface thread. A solution that does not convince me.

public synchronized void mark(Board board) {
    nextMarkLocation = null;
    try {
        if(nextMarkLocation == null) {
            wait();
        }
    } catch (InterruptedException e) {
        // handling
    }

and

public synchronized void setNextMarkLocation(Location location) {
    nextMarkLocation = location;
    notify();
}

Approach 2 - expose methods

The second approach would be to implement the methods for setting the current player's action in the game class. In this case, at each execution of the update method the routine would be the following (pseudo code):

public void update() {
    var player = getCurrentPlayer();
    var location = player.getNextMarkLocation();
    var symbol = player.getSymbol();
    board.markCell(location, symbol);
    updateCurrentPlayer();
}

The GUI will take care of updating itself according to the update of the match and setting the action for the current player. Here a check should be placed on the GUI owner. If the current player is not the same as the GUI owner, the game must ignore the action.

But the problem would be the reverse: And the automatic players?

Do you have any suggestions? Thanks

\$\endgroup\$
  • \$\begingroup\$ polling vs. listener... sounds a bit off topic \$\endgroup\$ – Martin Frank Feb 18 at 7:11
2
\$\begingroup\$

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

enter image description here

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 = current.performAiTurn();
            drawAnimations(animations); //in a fancy way
            game.endTurn();
        }
        //else wait for human player to end its turn via button
    }while(!game.isGameOver());
}
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ excellent answer, thank you very much \$\endgroup\$ – Sebastiano Verdolini Feb 18 at 17:47
  • \$\begingroup\$ Thank you very much for your kind comment... happy coding! \$\endgroup\$ – Martin Frank Feb 18 at 18:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.