You are on page 1of 33

Introduction

We will now see how to create a simple multi-player Tic-Tac-Toe game.


Note
If you have Studio installed, you may quicly create a new project and try to
make this app along with the tutorials. Otherwise, you can go through these
tutorials and try to understand each code and what it does. You can
implement this code later when you wish to. We have provided download
links for both the app itself as well as its source code.
The following video shows how the game works
Designing UI

In this section, you will learn about designing a simple UI for Tic Tac Toe game. We
are using a tablelayout (3 x 3) for game UI.
Let's create a Tic Tac Toe UI. We are adding 2 textviews (one for title & other for
displaying the turn), 1 button (for starting new game) and 1 tablelayout (on which
we will play our game).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" //It will fill the whole screen
android:layout_height="fill_parent" //It will fill the whole screen
android:orientation="vertical">

<TextView
android:id="@+id/titleText" //Defines the 'id' used to refer this element in
activity class.
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" //It aligns the text at center
horizontally
android:text="@string/title" />

<Button
android:id="@+id/newGameBtn"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_column="0"
android:layout_gravity="center_horizontal"
android:onClick="newGame"
android:text="New Game" />

<TableLayout
android:id="@+id/tableLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center">

//First Row:
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">

//First Column (R1C1)


<Button
android:id="@+id/topLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:width="100dp"
android:height="100dp"
android:text="O" />

//Second Column (R1C2)


<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:width="100dp"
android:height="100dp"
android:text="O" />

//Third Column (R1C3)


<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="3"
android:width="100dp"
android:height="100dp"
android:text="O" />
</TableRow>

//Second Row
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">

//First Column (R2C1)


<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:width="100dp"
android:height="100dp"
android:text="O" />

//Second Column (R2C2)


<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:width="100dp"
android:height="100dp"
android:text="O" />

//Third Column (R2C3)


<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="3"
android:width="100dp"
android:height="100dp"
android:text="O" />
</TableRow>

//Third Row
<TableRow
android:layout_width="fill_parent"
android:layout_height="fill_parent">
//First Column (R3C1)
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="1"
android:width="100dp"
android:height="100dp"
android:text="O" />

//Second Column (R3C2)


<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="2"
android:width="100dp"
android:height="100dp"
android:text="O" />

//Third Column (R3C3)


<Button
android:id="@+id/button7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_column="3"
android:width="100dp"
android:height="100dp"
android:text="O" />
</TableRow>
</TableLayout>

//Textview for display the turn


<TextView
android:id="@+id/nextTurn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:gravity="center"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="X's Turn" />
</LinearLayout>
Adding Game Logic
In this section, you will learn about creating a logic for Tic Tac Toe game. We
are writing a very simple logic for making a Tic Tac Toe game.
Our logic for checking the winner is very simple. We will traverse all rows
first, then all columns, then forward diagonal and finally backward diagonal
for checking the winner. Please refer the image (given at last) for more
details.
package com.internshala.app.is_tictactoe;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.TableLayout;

import android.widget.TableRow;

import android.widget.TextView;

import android.widget.Toast;

/**

* Created by aseem on 1/18/2016.

*/

public class GameActivity extends Activity {

// Representing the game state:

private boolean is_O_turn = false; // Who's turn is it? false=X true=O

// for now we will represent the gameBoard as an array of characters

private char gameBoard[][] = new char[3][3];

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.game);
setupOnClickListeners();

resetButtons();

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is


present.

getMenuInflater().inflate(R.menu.menu_main, menu);

return true;

@Override

public boolean onOptionsItemSelected(MenuItem item) {

int id = item.getItemId();

//noinspection SimplifiableIfStatement

if (id == R.id.action_settings) {

return true;

return super.onOptionsItemSelected(item);

/**

* Called when you press new game.

* @param view the New Game Button

*/

public void newGame(View view) {

is_O_turn = false;

gameBoard = 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);

TextView t = (TextView) findViewById(R.id.titleText);

t.setText(R.string.title);

TextView nextTurnView = (TextView) findViewById(R.id.nextTurn);

nextTurnView.setText("X's Turn");

/**

* This method that returns true when someone has won and false when
nobody has

* If someone has won the game, it will also displays that in form of
Toast.

*
* @return

*/

private boolean checkWin() {

char winner = '\0';

if (checkWinner(gameBoard, 3, 'X')) {

winner = 'X';

} else if (checkWinner(gameBoard, 3, 'O')) {

winner = 'O';

if (winner == '\0') {

return false; // nobody won

} else {

// display winner

Toast.makeText(this, winner + " wins", Toast.LENGTH_LONG).show();

return true;

/**

* This is a main algorithm for checking if a specific player has won.

* @return true if the specified player has won

* Kindly have a look at the image (given after this section) for more
details on this scction.

*/

private boolean checkWinner(char[][] board, int size, char player) {

//First we check all rows

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;

//Then we check all the columns

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;

/*

* This part is checking diagonals (forward)

* i.e. starting x & y from 0 and compare when x & y are same.

*/

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;

/*

* This part is checking diagonals (forward)

* i.e. starting x & y from 0 and compare when x + y = boardsize - 1


(x=0, y=2 | x=0, y=1 | x=2, y=0).

*/

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;

return false;

/**

* Disables all the buttons.

*/

private void disableGameButtons() {

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.setEnabled(false);

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 PlayButtonOnClick(x, y));

/**

* Handles click event on the buttons

*/

private class PlayButtonOnClick implements View.OnClickListener {

private int x = 0;

private int y = 0;

public PlayButtonOnClick(int x, int y) {

this.x = x;
this.y = y;

@Override

public void onClick(View view) {

if (view instanceof Button) {

Button B = (Button) view;

gameBoard[x][y] = is_O_turn ? 'O' : 'X';

B.setText(is_O_turn ? "O" : "X");

B.setEnabled(false);

is_O_turn = !is_O_turn;

TextView nextTurnView = (TextView)


findViewById(R.id.nextTurn);

nextTurnView.setText(is_O_turn ? "O's Turn" : "X's Turn");

// check if anyone has won

if (checkWin()) {

disableGameButtons();

nextTurnView.setText("X's Turn");

Image that explains the logic for checkWinner() function:


Styling Our Game

In this section, you will learn about making the UI more inttractive and
beautiful.
Note
Only the changes to the existing files (that we have discussed in above
tutorials) have been highlighted.
Let's style our button, textview & tablelayout. We'll give blue color to button,
white color to tablelayout & red text color to textview text. We'll also add
some margin to our input fields.
<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="wrap_content">

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical">

<TextView

android:id="@+id/titleText"

android:layout_width="match_parent"

android:layout_height="wrap_content"
android:gravity="center"

android:paddingTop="10dp"

android:paddingBottom="10dp"

android:background="@color/colorWhite"

android:textColor="@color/colorRed"

android:text="@string/title" />

<Button

android:id="@+id/newGameBtn"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:layout_column="0"

android:layout_gravity="center_horizontal"

android:onClick="newGame"

android:background="@color/colorPrimary"

android:textColor="@color/colorWhite"

android:layout_marginBottom="10dp"

android:text="New Game" />

<TableLayout

android:id="@+id/tableLayout"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center">

<TableRow

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<Button

android:id="@+id/topLeft"

android:layout_width="wrap_content"
android:layout_height="wrap_content"

android:layout_column="1"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

<Button

android:id="@+id/button"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="2"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

<Button

android:id="@+id/button1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="3"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

</TableRow>

<TableRow
android:layout_width="fill_parent"

android:layout_height="fill_parent">

<Button

android:id="@+id/button2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="1"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

<Button

android:id="@+id/button3"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="2"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

<Button

android:id="@+id/button4"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="3"

android:width="100dp"

android:height="100dp"
android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

</TableRow>

<TableRow

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<Button

android:id="@+id/button5"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="1"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

<Button

android:id="@+id/button6"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="2"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

<Button
android:id="@+id/button7"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="3"

android:width="100dp"

android:height="100dp"

android:layout_margin="5dp"

android:background="@color/colorWhite"

android:text="O" />

</TableRow>

</TableLayout>

<TextView

android:id="@+id/nextTurn"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:gravity="center"

android:paddingTop="10dp"

android:paddingBottom="10dp"

android:background="@color/colorWhite"

android:textColor="@color/colorRed"

android:text="X's Turn" />

</LinearLayout>

</ScrollView>
Adding colors to 'X' & 'O':
package com.internshala.app.is_tictactoe;

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

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.TableLayout;

import android.widget.TableRow;

import android.widget.TextView;

import android.widget.Toast;

/**

* Created by aseem on 1/18/2016.

*/

public class GameActivity extends Activity {

// Representing the game state:

private boolean is_O_turn = false; // Who's turn is it? false=X true=O

// for now we will represent the gameBoard as an array of characters

private char gameBoard[][] = new char[3][3];

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.game);

setupOnClickListeners();

resetButtons();

@Override

public boolean onCreateOptionsMenu(Menu menu) {


// Inflate the menu; this adds items to the action bar if it is
present.

getMenuInflater().inflate(R.menu.menu_main, menu);

return true;

@Override

public boolean onOptionsItemSelected(MenuItem item) {

int id = item.getItemId();

//noinspection SimplifiableIfStatement

if (id == R.id.action_settings) {

return true;

return super.onOptionsItemSelected(item);

/**

* Called when you press new game.

* @param view the New Game Button

*/

public void newGame(View view) {

is_O_turn = false;

gameBoard = 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);

TextView t = (TextView) findViewById(R.id.titleText);

t.setText(R.string.title);

TextView nextTurnView = (TextView) findViewById(R.id.nextTurn);

nextTurnView.setText("X's Turn");

/**

* This method that returns true when someone has won and false when
nobody has

* If someone has won the game, it will also displays that in form of
Toast.

* @return

*/

private boolean checkWin() {

char winner = '\0';

if (checkWinner(gameBoard, 3, 'X')) {

winner = 'X';

} else if (checkWinner(gameBoard, 3, 'O')) {


winner = 'O';

if (winner == '\0') {

return false; // nobody won

} else {

// display winner

Toast.makeText(this, winner + " wins", Toast.LENGTH_LONG).show();

return true;

/**

* This is a main algorithm for checking if a specific player has won.

* @return true if the specified player has won

* Kindly have a look at the image (given in previous section section)

* for more details on this scction.

*/

private boolean checkWinner(char[][] board, int size, char player) {

//First we check all rows

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;

}
//Then we check all the columns

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;

/*

* This part is checking diagonals (forward)

* i.e. starting x & y from 0 and compare when x & y are same.

*/

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;

/*

* This part is checking diagonals (forward)


* i.e. starting x & y from 0 and compare when x + y = boardsize - 1

* (x=0, y=2 | x=0, y=1 | x=2, y=0).

*/

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;

return false;

/**

* Disables all the buttons.

*/

private void disableGameButtons() {

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.setEnabled(false);

}
}

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 PlayButtonOnClick(x, y));

/**

* Handles click event on the buttons

*/

private class PlayButtonOnClick implements View.OnClickListener {

private int x = 0;

private int y = 0;

public PlayButtonOnClick(int x, int y) {

this.x = x;

this.y = y;

@Override

public void onClick(View view) {


if (view instanceof Button) {

Button B = (Button) view;

gameBoard[x][y] = is_O_turn ? 'O' : 'X';

B.setText(is_O_turn ? "O" : "X");

B.setTextColor(is_O_turn ?

getResources().getColor(R.color.colorPrimary) :

getResources().getColor(R.color.colorRed));

B.setTextSize(20);

B.setEnabled(false);

is_O_turn = !is_O_turn;

TextView nextTurnView = (TextView)


findViewById(R.id.nextTurn);

nextTurnView.setText(is_O_turn ? "O's Turn" : "X's Turn");

// check if anyone has won

if (checkWin()) {

disableGameButtons();

nextTurnView.setText("X's Turn");

}
We need to add colors.xml under values directory.
<?xml version="1.0" encoding="utf-8"?>

<resources>

<color name="colorPrimary">#1295c9</color>
<color name="colorWhite">#FFFFFF</color>

<color name="colorBlack">#000000</color>

<color name="colorRed">#db2a3b</color>

</resources>

We need to add few values in strings.xml under values directory.


<resources>

<string name="app_name">IS-TicTacToe</string>

<string name="hello_world">Hello world!</string>

<string name="action_settings">Settings</string>

<string name="title">Internshala - Tic Tac Toe</string>

</resources>

You might also like