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.