Sunday, June 5, 2011

Android Tic Tac Toe Game Logic - Part 1 Interfaces

This post describes the game logic behind making an Android version of Tic Tac Toe and the interfaces used to accomplish this. The goal is to separate the game logic as much as possible from the display logic.

Representing the Game Board

In this tutorial, we are going to think of the game board as being made up of nine separate tiles. Each tile will draw a different border depending on the location of the tile. A tile will also be drawn different based on what its state is set as.

Valid states are:
  • Empty
  • X
  • O
These states will be defined in a separate class that we create to hold Constants relating to the game.


TicTacToeDrawable Interface

Let's create an interface for the TicTacToeDrawable. The actual implementation of the object will be done later, when we start adding the Android specific components to the project. Remember, we are trying to separate the game logic as much as possible from the Android/Drawing logic.

The TicTacToeDrawable interface is going to be fairly simple.

GetCurrentState
We need to be able to get the state of each tile so we can check to see if a player can play there, or if someone won, or if the game has ended in  a tie.

SetCurrentState
We need to be able to set the state of a tile to show that an X or an O has been played, or to reset the tile to state of Empty if a new game has started.

GetRow
Get the row that the tile is located in.

GetCol
Get the column that the tile is located in.

We don't include setters for the row and column because we want these values to be set once in the constructor. There is no reason a tile should be changing rows or columns once the game board has been set up.

The complete code for the interface is pasted below

package com.dreamdom.tictactoe.gamedriver;

public interface TicTacToeDrawable {
 
 /**
  * Set the state for the tile
  * @param state An integer value representing the current state (empty, x, or o)
  */
 public void setState(int state);
 
 /**
  * Returns the current state of the tile
  * @return the state of the tile
  */
 public int getState();
 
 /**
  * Get the row the tile resides in
  * @return the row value for the tile
  */
 public int getRow();
 
 /**
  * Get the column the tile resides in
  * @return the column value for the tile
  */
 public int getCol();

}

The GameManager Interface

The goal of the GameManager is to track the overall state of the game determining who should play, if someone has won, if the game has ended in a tie, and resetting the game.

Determining the state of the game depends on the state of all the tiles. Therefore, the GameManager needs to maintain a list of all the tiles.

setTileList
Set the total list of tiles for the board

getAvailableTiles
Returns a list of the available tiles for playing. This is a helper method for the AI.

reset
Resets the game manager for a new game.

The game manager also needs to handle updating the values of tiles.

playerClickedTile
Called when the player clicks a tile.

changeTileValue
Called to manually change a tile value. Will be called by the AI.

The GameManager also tracks the state of the game and some settings

getGameState
Returns a value to the corresponding state of the game (player win, AI win, tie, ongoing...)

setStartingTurn
Used to determine if the player of if the AI should start the game.

Other Methods

checkWin
This is a utility method that can be used to check if a certain play causes a win. The AI can use this to block the player, or win the game itself. This method can also be used to determine the overall state of the game. It is important to note that this method only checks, it does not change the state of any of the tiles.

setGameAI
This method sets the AI for the game. The AI is handled in a separate class.

The complete code for the interface is pasted below.

package com.dreamdom.tictactoe.gamedriver;

import java.util.ArrayList;

public interface GameManager {
 
 /**
  * Set the total list of tiles for the board
  * @param tileList
  */
 public void setTileList(ArrayList<TicTacToeDrawable> tileList);
 
 /**
  * Get a list of the available tiles for playing
  * @return An ArrayList of available tiles on the board
  */
 public ArrayList<TicTacToeDrawable> getAvailableTiles();
 
 /**
  * Resets the game manager
  */
 public void reset();
 
 /**
  * Set the GameAI to be used in the game
  * @param gameAI the AI to use
  */
 public void setGameAI(GameAI gameAI);
 
 /**
  * Called when a player clicks a tile
  * @param tile the tile clicked
  */
 public void playerClickedTile(TicTacToeDrawable tile);
 
 /**
  * Called when you want a tile to change value
  * @param tile
  */
 public void changeTileValue(TicTacToeDrawable tile, int value);
 
 /**
  * Set to determine who starts
  * @param nextTurn who starts the game
  */
 public void setStartingTurn(int startTurn);
 
 
 /**
  * Check to see if setting a tile would cause a win for that tile
  * @param tilePiece the piece that would be set
  * @param row the row to place the tile
  * @param col the column to place the tile
  * @return true if it would be a win, false if otherwise
  */
 public boolean checkWin(int tilePiece, int row, int col);
 
 /**
  * Get the current state of the game
  * @return An integer value representing the current state of the game
  */
 public int getGameState();
}

The GameAI Interface

The GameAI is abstracted out into an interface as well. This will make it easy to provide different AI implentations. In this tutorial series we will do this, creating an "easy" AI that plays randomly, and a "hard" AI that tries a little harder to win.

The GameAI interface is very straightforward. There is only one method, to play a piece. This method takes the GameManager as an argument,  so that it can check the status of the board and update the value of the tile that it plays.

The GameAI interface is pasted below.

package com.dreamdom.tictactoe.gamedriver;

public interface GameAI {
 
 public TicTacToeDrawable playPiece(GameManager gameManager);

}

The Constants

As I mentioned earlier in the post, we have a separate class that just holds some constants. This class is pasted below.

package com.dreamdom.tictactoe.gamedriver;

public class TicTacToeConstants {
 
 // Constants
 public static final int TILE_STATE_EMPTY = 0;
 public static final int TILE_STATE_X = 1;
 public static final int TILE_STATE_O = 2;

 public static final int GAME_STATE_READY = 0;
 public static final int GAME_STATE_PLAYING = 1;
 public static final int GAME_STATE_CATS_GAME = 2;
 public static final int GAME_STATE_PLAYER_WINS = 3;
 public static final int GAME_STATE_COMPUTER_WINS = 4;
 
 public static final int TURN_PLAYER = 0;
 public static final int TURN_COMPUTER = 1;

}

Next in the Tutorial Series

Not that we have defined the interfaces, in the next step of the tutorial series we will implement the GameManager and GameAI interfaces.

4 comments:

  1. Hangs
    can you share the code project?
    hangsbreaker@gmail.com

    ReplyDelete
  2. ! You should have finished this tutorial :( I was going along all psyched to get to the implementation... :/

    ReplyDelete
  3. DooD! Complete iT!!

    ReplyDelete
  4. do you have the code project ? can you share it to me ?
    my email is arturorb91@gmail.com

    thanks bro

    ReplyDelete