Assignment 7: Third Time’s a Charm – Three Trios, part 3
1 Purpose
2 Preparation:   cleaning up prior code
3 Thinking about control-flow
3.1 Wait, how many controllers?
3.2 Listening and reacting to events
4 Designing players
5 Designing the controller
6 Running your game
6.1 Showing two views
6.2 Configuring the game
7 What to do
8 What to submit
9 Grading standards
10 Submission
8.9

Assignment 7: Third Time’s a Charm – Three Trios, part 3

Due dates:

1 Purpose

In this portion of the project, you will be building a controller for your game, listeners for various features interfaces to connect the components, and ultimately building a playable, complete game. Read through the entirety of this assignment before diving into coding, as the suggested designs here may influence how you structure your work.

2 Preparation: cleaning up prior code

You should likely have received design feedback about your model and/or view implementations. Incorporate that feedback, as well as complete any missing functionality from the prior assignments.

In the previous assignment, you implemented selecting grid cells via mouse-clicks, and players could indicate what card they wanted to play by click on the card in their hand. Nothing in particular needed to happen in response to those choices yet, but in this assignment we need to connect those choices to the controller. If you have not done so already, design a features interface describing those player actions, and enhance your view with the ability to add listeners for those actions. (Again, review Lecture 13: GUI Basics for more details on this approach.)

3 Thinking about control-flow

As discussed in class, GUI controllers are asynchronous: they respond to events that may arrive at any time. However, the game-play of Three Trios is synchronous: like Solo Red or TicTacToe, the rules of the game enforce turn-based play. These two facts are in conflict with each other, so we need to design a way to reconcile them.

Think about the strategies you implemented on the previous assignment, or for TicTacToe in class: ultimately, they were simple functions from State of the game -> Choice of move. This approach works well for synchronous games, since another player strategy cannot move while the first one is computing its result. So conceivably, the model could call the player strategies directly, to get their choice of move. But this has two design problems. First, it gives the model too much controller-like power, by bypassing the views and controllers and talking to players directly. Second, and equally importantly, we want to be able to have games with any mix of human and machine players: humans take a while to choose their next move, while machines compute much more quickly. In particular, there is no obvious way to implement “a human strategy” as a function, since while that function is executing, the GUI is unresponsive to input — but the GUI is how the human would produce the desired answer for the strategy! Ultimately, we need a way for the model to tell the players “it’s your turn”, and then wait for the players to choose a move (by means of their respective strategies and controllers). We need to separate the two steps of notifying players of their turn, and waiting for their responses.

3.1 Wait, how many controllers?

In single-player games, it makes sense to have a single controller. In single-user applications, likewise it makes sense to have a single controller. But in multi-player games, where players can act independently, it makes more sense for each player to have their own controller dedicated to that player. Think of each controller as interacting with the rest of the system on behalf of that one player.

3.2 Listening and reacting to events

Making your controllers work will require thinking carefully about features interfaces. You have already considered what high-level events the view can publish, that the controller should listen for and respond to. These likely consisted of at least two events: player choosing a card to play, or player choosing a position to play the chosen card to. We needed these high-level events because they could happen at any time, so the controller had to wait for them to occur before it could respond.

Now think about what notifications the model can publish, that would be of interest to its players. At minimum, the notification that “it’s your turn” could come at any time, since the other player could be arbitrarily slow in choosing a move. (There may be other notifications you think the model can send out as well.) Accordingly, design a features interface for your model, and augment it with the ability to add listeners for those events too.

Your controller should now subscribe itself as a listener for both features interfaces: since it needs to coordinate between the model and the view, it needs to know when the view has actively chosen something and when the model notifies that the current player has changed.

A subtle note: If the model is responsible for notifying players when it is their turn, then you need to be very careful that the very first player gets notified. This requires that all the players (or the players’ controllers) are registered as listeners before the first “it’s your turn!” notification is sent. This implies that you should have a startGame method on your model, to ensure that there is a clear distinction between “setting everything up” and “actually playing the game”.

4 Designing players

There are clearly two implementations of players needed: human players and machine players. Machine players need a strategy in order to compute their next move; human players wait for the human to interact with the view to choose their next move. By abstracting out “what can a player do?” as a player-actions interface, we have a very clean opportunity to reconcile human and machine players:

5 Designing the controller

You may find it helpful to set the title of the views to their respective players and whether they are playing out their turn or waiting for their turn.

6 Running your game

6.1 Showing two views

In the previous assignment, we built a placeholder main() method that simply created a view for the model. Now, we need to create two views, one for each player — and we need to create two players and two controllers, as well.

package cs3500.threetrios;

public final class ThreeTrios {
  public static void main(String[] args) {
    YourModel model = ...create an example model...
    YourView viewPlayer1 = new YourView(model);
    YourView viewPlayer2 = new YourView(model);
    YourPlayer player1 = new YourHumanPlayer(model);
    YourPlayer player2 = new YourHumanPlayer(model);
    YourController controller1 = new YourController(model, player1, viewPlayer1);
    YourController controller2 = new YourController(model, player2, viewPlayer2);
    model.startGame();
  }
}

(It is entirely possible that when your program starts, you only see one window appear. That may be an illusion because the two JFrames overlap each other completely; try moving the windows around to ensure they’re not covering each other, before assuming that there truly only is one window appearing...)

6.2 Configuring the game

As with Solo Red, we would like to be able to configure our Three Trios game with different combinations of players.

Your command-line here does not have to be particularly elaborate: at minimum, it should expect two string arguments describing each of the players and their strategies, for example, "human", "strategy1", "strategy2", and "strategy3". Document whatever command-line arguments you choose. Augment the scaffold code above for main() to take into account the command-line and cleanly configure the players accordingly.

Review instructions from Solo Red on configuring IntelliJ to run your program with command-line arguments

7 What to do

  1. Attempt an initial design for the player-action and model-status interfaces. (They should be fairly small interfaces, with very few methods.) Make sure you have clearly documented the purposes of those interfaces and their methods, to guide you in the next implementation stages. Implement the ability for your views to add player-action listeners, and for your model to add model-status listeners.

  2. Design a controller that takes in a model, which player they are working for, and a view for that player. It should register itself as a listener for both features interfaces, and should mediate between the view and the model on behalf of that player.

  3. Update your main() method as described above.

  4. Update your README file to include explanations of all the new classes you’ve designed. Be sure to include a “Changes for part 3” section documenting what you changed from your initial design or from the previous assignment.

8 What to submit

9 Grading standards

For this assignment, you will be graded on

10 Submission

Please submit your homework to https://handins.ccs.neu.edu/ by the above deadline. Then be sure to complete your self evaluation by its due date.