Making Tic Tac Toe for Android

Live on my phone

In my last blog post I showed a little cheating application I made for the Android which is sort of related to games (word games to be precise) so today in this post I thought I’d explain how I made a simple Tic Tac Toe Application for the Android phone (that’s Noughts and Crosses for us Brits).

Setting Up

First of all you create a new Android project in whatever IDE you are using, I am using IntelliJ Idea so I went to File|New Project:

I have it in it's Dark Theme

I have it in it’s Dark Theme

In Eclipse you would go to File|New|Android Application Project:

I quite like the configuration options you get here.

I quite like the configuration options you get here.

I have a few SDKs installed on my machine including the latest, the one my phone runs on and the one just below what my old phone ran on (2.2) so to make sure this worked for the most devices I opted for an SDK versions in the 2′s (I ended up using 2.3, Gingerbread).

Next I set up a few things in the files, nothing to major to note about, I did make a mistake in my Project name that I just corrected in one of the xml files but decided not to change it at an actual project level (partly to do with the fact I had already created and pushed a GitHub page under the name).

The Layout

The next thing I did was design the application layout. The file in my case was generated and called main.xml and was located in the res folder under the layout subfolder, it may of been called something else in an Eclipse project but it should be the only file located in that subdirectory.

This was relatively easy as Idea has a very nice UI designing tool, as does Eclipse. I settled on this:

DesignIdea

That’s:

  • A TextView with my name and the title of the game in it.
  • A Button with the words New Game in it.
  • A TableLayout containing within a Button in the 1st, 2nd and 3rd cell of 3 different rows.

I have modified each item to look how I would like them to look:

  • The TextView has had it’s layout:gravity set to centre it horizontally.
  • The Button has also had it’s layout:gravity set to centre it horizontally. And has also had it’s layout:width set to fill the parent.
  • The TableLayout has had it’s layout:gravity set to centre both horizontally and vertically.
  • Each Button within the TableLayout have had their width and height attributes set to 100dp so they appear square.

I won’t show you the actual xml file for this in it’s pure form as I think it’s better you experiment yourself.

I also modified the AndroidManifest.xml file (located at the root of your project) to prevent the application being rotated into landscape by adding:

android:screenOrientation="portrait"

To the activity tag.

Onto the Code

Now finally the code!

When you begin a new Android project you are probably presented with a java file similar to this (minus the comments and typo):

package com.example.NaughtsAndCrosses;

import android.app.Activity;
import android.os.Bundle;

/**
 * Tic Tac Toe Game
 * ---
 * 
 * Code by Lyndon Armitage
 * For learning purposes
 *
 * @author Lyndon Armitage
 */
public class MainActivity extends Activity {
	/**
	 * Called when the activity is first created.
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	}
}

Our first port of order is deciding how we are going to represent the game state. So to do this we need to establish some facts namely;
there are only 2 players (X and O) and the board is laid out in a 3 by 3 grid of either Xs, Os or blanks.

From these facts I decided to go with:

	// Representing the game state:
	private boolean noughtsTurn = false; // Who's turn is it? false=X true=O
	private char board[][] = new char[3][3]; // for now we will represent the board as an array of characters

An alternative to using the char array is using an array of an Enum but a simple char array will do for now. Likewise I could of also used an Enum for determining who’s turn it was.

Now we know how we are going to represent the game state we need to figure out how we are going to interact with it. Technically I already decided this, by using Buttons in a TableLayout and a button outside it to start a new game.

The first thing I decided to get working was interacting with each button in the layout; changing what they have written on them and what they do when clicked. This was actually more complicated to code than I expected. Originally I thought there would be a simple call to the TableLayout to get the element in a certain position, something like getViewAt(int x, int y) but there was not. This is because the TableLayout can contain data not in rows and columns, e.g. it can contain an EditText Element below or in between it’s normal TableRows. Example:

Good come in handy actually

Could come in handy actually

When you think about it this makes sense in designing a layout, it means you can have heading for different parts of the grid.

So in order to get the position of each button we have to look at each of the TableRow objects contained within it and use their positions as the y coordinate and the Buttons position within them as the x coordinate:

	/**
	 * This will add the OnClickListener to each button inside out TableLayout
	 */
	private void setupOnClickListeners() {
		TableLayout T = (TableLayout) findViewById(R.id.tableLayout);
		for(int y = 0; y < T.getChildCount(); y ++) {
			if(T.getChildAt(y) instanceof TableRow) {
				TableRow R = (TableRow) T.getChildAt(y);
				for(int x = 0; x < R.getChildCount(); x ++) {
					View V = R.getChildAt(x); // In our case this will be each button on the grid
					V.setOnClickListener(new PlayOnClick(x, y));
				}
			}
		}
	}

I will explain what PlayOnClick is in a moment. What that code does is it grabs the tableLayout and loops through each of it’s children (making sure each one is a TableRow) and then loops through each child’s children and sets up what they do upon a click. I had to edit my TableLayout and give it an ID to it in order to find it using findViewById() I simply set up it’s android:id attribute in the xml to:

android:id="@+id/tableLayout"

PlayOnClick is a custom OnClickListener I created for this program. I could of instead created 9 different methods (one for each button) and set each button to call one each using the UI designer but instead opted to create an OnClickListener and dynamically set each button to use one with it’s unique coordinates.
An implementation of this for our game looks like this (it’s an inner class of my MainActivity class):

	/**
	 * Custom OnClickListener for Noughts and Crosses
	 * Each Button for Noughts and Crosses has a position we need to take into account
	 * @author Lyndon Armitage
	 */
	private class PlayOnClick implements View.OnClickListener {

		private int x = 0;
		private int y = 0;

		public PlayOnClick(int x, int y) {
			this.x = x;
			this.y = y;
		}

		@Override
		public void onClick(View view) {
			if(view instanceof Button) {
				Button B = (Button) view;
				board[x][y] =  noughtsTurn ? 'O' : 'X';
				B.setText(noughtsTurn ? "O" : "X");
				B.setEnabled(false);
				noughtsTurn = !noughtsTurn;
			}
		}
	}

Now if you were to run this as it was it would be a playable version of Tic Tac Toe, albeit without any score tracking and win checking. Not only that but, the New Game Button does nothing, so let’s change that.

	/**
	 * Called when you press new game.
	 * @param view the New Game Button
	 */
	public void newGame(View view) {
		noughtsTurn = false;
		board = new char[3][3];
		resetButtons();
	}

	/**
	 * Reset each button in the grid to be blank and enabled.
	 */
	private void resetButtons() {
		TableLayout T = (TableLayout) findViewById(R.id.tableLayout);
		for (int y = 0; y < T.getChildCount(); y++) {
			if (T.getChildAt(y) instanceof TableRow) {
				TableRow R = (TableRow) T.getChildAt(y);
				for (int x = 0; x < R.getChildCount(); x++) {
					if(R.getChildAt(x) instanceof Button) {
						Button B = (Button) R.getChildAt(x);
						B.setText("");
						B.setEnabled(true);
					}
				}
			}
		}
	}

I set the New Game button to call the corresponding method using my UI editor and now when I click it I clear the grid. I also added a call resetButtons() into the onCreate() method to make sure all the buttons are blank.

Now what about checking for a win? Well I know that whenever 3 of the items in a line match that specific player has won so let’s go about coding a method that works this out and appropriately responds.

Below is my implementation of a method that can check if a specific player has won at a game of tic tac toe for any size board, it could probably be improved and simplifed into only one loop but that may be harder to understand:

	/**
	 * This is a generic algorithm for checking if a specific player has won on a tic tac toe board of any size.
	 *
	 * @param board  the board itself
	 * @param size   the width and height of the board
	 * @param player the player, 'X' or 'O'
	 * @return true if the specified player has won
	 */
	private boolean checkWinner(char[][] board, int size, char player) {
		// check each column
		for (int x = 0; x < size; x++) {
			int total = 0;
			for (int y = 0; y < size; y++) {
				if (board[x][y] == player) {
					total++;
				}
			}
			if (total >= size) {
				return true; // they win
			}
		}

		// check each row
		for (int y = 0; y < size; y++) {
			int total = 0;
			for (int x = 0; x < size; x++) {
				if (board[x][y] == player) {
					total++;
				}
			}
			if (total >= size) {
				return true; // they win
			}
		}

		// forward diag
		int total = 0;
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				if (x == y && board[x][y] == player) {
					total++;
				}
			}
		}
		if (total >= size) {
			return true; // they win
		}

		// backward diag
		total = 0;
		for (int x = 0; x < size; x++) {
			for (int y = 0; y < size; y++) {
				if (x + y == size - 1 && board[x][y] == player) {
					total++;
				}
			}
		}
		if (total >= size) {
			return true; // they win
		}

		return false; // nobody won
	}

I call the above method within another that handles what to do if a player has won:

	/**
	 * Method that returns true when someone has won and false when nobody has.
	 * It also display the winner on screen.
	 *
	 * @return
	 */
	private boolean checkWin() {

		char winner = '\0';
		if (checkWinner(board, 3, 'X')) {
			winner = 'X';
		} else if (checkWinner(board, 3, 'O')) {
			winner = 'O';
		}

		if (winner == '\0') {
			return false; // nobody won
		} else {
			// display winner
			TextView T = (TextView) findViewById(R.id.titleText);
			T.setText(winner + " wins");
			return true;
		}
	}

The TextView I describe there is the same one that has my name in it when you look back to the design, this way the players can see who has won.

Now we simply need to edit the onClick method of our PlayOnClick class to utilise this method correctly:

		public void onClick(View view) {
			if (view instanceof Button) {
				Button B = (Button) view;
				board[x][y] = noughtsTurn ? 'O' : 'X';
				B.setText(noughtsTurn ? "O" : "X");
				B.setEnabled(false);
				noughtsTurn = !noughtsTurn;

				// check if anyone has won
				if (checkWin()) {
					disableButtons();
				}
			}
		}

The method disableButtons() simply disables all the buttons within the grid to stop you playing after a win.

And that’s it! Tic Tac Toe on Android step by step!

Live on my phone

Live on my phone

I have a GitHub Repository with all this code available here if you want to see the finished code.

Possible improvements include;

  • Score keeping.
  • Bigger grids.
  • Online play.
  • An AI to play against.
  • Pretty Colours.
  • Optimisations.

If you want to use the code feel free, provided you aren’t making money off of it or calling it your own (it took me time and effort to make it after all).

Happy Coding!

5 Comments

  1. [...] 我手机上的截图 本文教程最终代码点此下载 source lyndonarmitage. [...]

  2. AndroidChamp says:

    Thanks for such a good explanation.
    It helped me completing my first app in android. :)

  3. samikrazy says:

    cant import this project:-(

  4. Prerna says:

    I am pursuing a course in Wireless and Mobile Communications. I’ve been asked to prepare a project in Android. I would like to know if tic tac toe would be a good topic to pick up. thanks.

Leave a Reply