You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Lab 11 - Games For Two

Introduction

The game of Tic-Tac-Toe is a often used as an example for two-person games where each player takes turn to place a game piece on a two dimensional game board. The discussion of such a game serves to illustrate the notion game trees, and in particular, the min-max principle: how to compute the values of the game tree nodes and select the best next move. Even though these algorithms are initially described in high-level abstract terms, this is not reflected in their standard implementations.

Traditional Tic-Tac-Toe code from

  • Sun Microsystems
  • Mark Allen Weiss in "Data Structures & Problem Solving Using Java, 2nd ed." Addison Wesley 2001.

As one can see from the above examples of Tic-Tac-Toe code, the algorithm code is intertwined with low-level game board implementation details. This not only obscures the essence of the solution, but also makes it impossible to re-use in different types of games. What essentially "throw-away" code.

To remedy this situation, we seek to design an OO model for two-person games that enables us to express all facets of the games at the highest level of abstraction. The result is a system of cooperating objects that possesses many of the essential qualities in software engineering: correctness, robustness, extensibility, flexibility, and reusability. The demo program below shows the what an OO game model can do.

The Best Little Tic-Tac-Toe Game in Texas

As one can see from the demo, the program is not really about playing Tic-Tac-Toe but is about using a 2-pesron game design as a vehicle to learn BIGGER concepts in computing:

  • Abstraction
  • Design Process
  • Fundamental Principles.

When a player wants to put his/her game piece at some position on the board, it needs a way to communicate to

  • the board model to make such a move,
  • the turn control manager for it to set up the next turn (halt the game, skip a turn, or proceed as usual),
  • the view administrator to announce the winner or the loser or a draw in case the game is in its final state.

To avoid such complicated maneuvering, the player simply talks to an interface called IRequestor passing it the appropriate information and let this requester do the rest of the work internally. In the design pattern language, IRequestor plays the role of a "facade".

Here are some relevant excerpts of code that illustrate how the player interacts with the IRequestor .

/** This class represents an abstract player of the game.
  * The players are represented as a circular linked list.
  */

public abstract class APlayer {
  private IRequestor requestor;
  private int player;
  private APlayer nextPlayer = this;

  /** The constructor for the class.
    * @param requestor The  requestor that the player uses to request moves of the board.
    * @param player The player number of this player.
    */
  public APlayer(IRequestor requestor, int player)  {
    this.requestor = requestor;
    this.player = player;
  }
  /** Tells this player to take its turn. */
  public abstract void takeTurn();

  /** other methods elided... */
}

/* This class represents a concrete computer player. */
public class ComputerPlayer extends APlayer {

  private INextMoveStrategy nextMoveStrategy;

  private IModel model;

  /** The constructor for the class.
    * @param requestor The requestor that this player will use to communicate with the model.
    * @param player This player's player number.
    * @param model A reference to the IModel.  Needed to call the getNextMove() method
    * of the INextMoveStrategy.
    * @param nextMoveStrategy The strategy used to calculate this player's next move.
    */

  public ComputerPlayer(IRequestor requestor, int player, IModel model, INextMoveStrategy nextMoveStrategy) {

    super(requestor, player);
    this.model = model;
    this.nextMoveStrategy = nextMoveStrategy;
    System.out.println("ComputerPlayer is using " + nextMoveStrategy);
  }

  /** Used by the TurnControl to tell this player to take its turn.
    * When the computer takes its turn, it will calculate its next move and
    * then request that move of  the model.
    * If the computer makes and invalid move, the computer will print an error
    * message to the screen and then  it will take its turn again.
    */
  public void takeTurn()  {
    System.out.print("Computer player "+ getPlayer() +" ("+ this +") takes turn...");
    final Point p = nextMoveStrategy.getNextMove(model, getPlayer());
    System.out.println("and moves to "+ p);
    getRequestor().setTokenAt (p.y, p.x, getPlayer(), new IRejectCommand() {
      // ANONYMOUS COMMAND!
      public void execute() {
        System.out.println("ComputerPlayer: The move at ("+p.x+", "+p.y+") is invalid.");
        takeTurn();
      }
    });
  }
}

When a player is instantiated, it is given an IRequestor to communicate with the model. As shown in ComputerPlayer.takeTurn() , the computer player gets the best next move from the next move strategy and then asks the requestor ( getRequestor() ) to set the game token at the best move's position, passing to the requestor an anonymous IRejectCommand , in case the move is illegal. This situation may happen if the next move strategy is a totally random move.

The IRejectCommand has only one method called execute()

/** A basic command that is executed when a move request has been rejected by the model.
  */
public interface IRejectCommand {
    /** This method is called by the model when a move is rejected. */
    public abstract void execute();
}

The IRequestor has only one method called setTokenAt(...)

/** This interface encapsulates the request mechanism used by an APlayer to try
  * to make a move to a given (row, col) by a given player.
  * This is the public (client) end of a "Facade" design pattern that hides the
  * internal workings of the model.
  */
public interface IRequestor {
    /** Requests to the model that a given player's token be placed on the
      * internal board at (row, col).
      *  An IRejectCommand is supplied that should be executed if the request is rejected.
      */
    public abstract void setTokenAt(int row, int col, int player, IRejectCommand rejectCommand);
}

A player gets its requestor at construction time. Who creates the concrete requestor and passes it to the player? The GameModel via its getPlayers() method! The GameModel has access to the board model, the turn control manager, and the view administrator. By creating an IRequestor as an anonymous inner class, the GameModel can thus set up the appropriate context for a player to make a request for a move without knowing anything about the board, the view, and the turn control!

In this lab you are to work with others to try to implement the IRequestor anonymous inner class that is stubbed out the GameModel code. This is part of the upcoming homework 11.

Download and extract the file hw11_12.zip . You should see the following files.

src : a subdirectory containing the source code of the Games program with a few stubbed out code for you to complete.
games.xml : a DrJava project file
P4M2.jar : the Java binary code of the game framework.
tttboard.jar : the Java binary code for the Tic-Tac-Toe gameboard.

Use DrJava to open the games.xml project file. Compile and run the project. You will discover that you cannot do much because the code for the Tic-Tac-Toe board ( model.board.TicTacToe.java=) and =model.GameModel.java have been stubbed out.
Open the Project Properties dialog and add P4M2.jar and tttboard.jar to the Extra Class Path. Now compile and run the project. Both the Tic-Tac-Toe game and the Othello game should work.
Now open the Project Properties dialog and remove P4M2.jar from the Extra Class Path. Open the file model.GameModel.java and edit the code for the anonymous inner class IRequestor to make the game program work again. Hint: review the documentation for IBoardModel , TurnControl and IViewAdmin . Click here for the complete Javadoc specification of the game framework.


Access Permissions: (Please don't edit)

  • Set ALLOWTOPICCHANGE = Main.TeachersComp211Group
  • hw11_12.zip: Source code and documentation in javadoc of the game framework
  • No labels