Creating Simple Tic-tac-toe Game for Android

The Tic-tac-toe game is really a simple application that can be easily implemented in Android. We will start the implementation of this application by creating the welcome screen with 4 buttons: "Normal Mode", "Ultimate Mode", "About" and "Exit" buttons. In this article you can read about the developing of a classic Tic-tac-toe game, that can be played by pressing the "Normal Mode" button. When you create an Android application in Eclipse, you can specify the option of creating a blank activity which will be show on the start up of your application. In this activity I added 4 buttons:
  1. android:id="@+id/normalMode"
  2. android:layout_width="match_parent"
  3. android:layout_height="wrap_content"
  4. android:layout_alignParentTop="true"
  5. android:layout_centerHorizontal="true"
  6. android:layout_marginTop="51dp"
  7. android:background="@color/button"
  8. android:onClick="@string/normal"
  9. android:text="@string/normalText" />
  10.  
  11. android:id="@+id/UltimateMode"
  12. android:layout_width="match_parent"
  13. android:layout_height="wrap_content"
  14. android:layout_alignLeft="@+id/normalMode"
  15. android:layout_below="@+id/normalMode"
  16. android:layout_marginTop="41dp"
  17. android:background="@color/button"
  18. android:onClick="@string/ultimate"
  19. android:text="@string/ultimateText" />
  20.  
  21. android:id="@+id/AboutBtn"
  22. android:layout_width="match_parent"
  23. android:layout_height="wrap_content"
  24. android:layout_alignLeft="@+id/UltimateMode"
  25. android:layout_below="@+id/UltimateMode"
  26. android:layout_marginTop="42dp"
  27. android:background="@color/button"
  28. android:onClick="@string/about"
  29. android:text="@string/aboutText" />
  30.  
  31. android:id="@+id/Exit"
  32. android:layout_width="match_parent"
  33. android:layout_height="wrap_content"
  34. android:layout_alignLeft="@+id/AboutBtn"
  35. android:layout_below="@+id/AboutBtn"
  36. android:layout_marginTop="41dp"
  37. android:background="@color/button"
  38. android:onClick="@string/exit"
  39. android:text="@string/exitText" />
Now, let's take a look on some attributes of the each button: android:id - is an unique identifier for each element. android:layout_width - the width of the button android:layout_height - the height of the button android:onClick - this attribute specifies which method in the activity java file will handle the click on the button. For example, if we specify this attribute in the next way: android:onClick="@string/exit" a method with the name, specified in the string resource file with tag "exit" will handle the click event. This entry in the resource file is:
  1. <string name="exit">exit_click</string>
The next step is to write handlers for all the buttons we created. The "Normal Mode" button will start a new classic Tic-tac-toe game by launching new Activity, called NormalActivity:
  1. public void normal_click(View v)
  2. {
  3. Intent myIntent = new Intent(MainActivity.this,NormalActivity.class);
  4. MainActivity.this.startActivity(myIntent);
  5. }
The "Ultimate Mode" button will show a message, that this feature is under construction and it will be available later:
  1. public void ultimate_click(View v)
  2. {
  3. AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
  4.  
  5. dlgAlert.setMessage("Under construction");
  6. dlgAlert.setTitle("comming soon");
  7.  
  8. dlgAlert.setCancelable(true);
  9.  
  10. dlgAlert.create().show();
  11. }
"About" button will show the information about the author of this application:
  1. public void about_click(View v)
  2. {
  3. Intent myIntent = new Intent(MainActivity.this, About.class);
  4. MainActivity.this.startActivity(myIntent);
  5. }
The "Exit" button will show another dialog window, but it will have an "OK" button for confirming the exit:
  1. public void exit_click(View v)
  2. {
  3. AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
  4.  
  5. dlgAlert.setMessage("Do you really want to exit");
  6. dlgAlert.setTitle("Exit");
  7.  
  8. dlgAlert.setCancelable(true);
  9. dlgAlert.setPositiveButton("Ok",
  10. new DialogInterface.OnClickListener() {
  11. public void onClick(DialogInterface dialog, int which) {
  12. finish();
  13. System.exit(0);
  14. }
  15. });
  16. dlgAlert.create().show();
  17. }
The "OK" button and handle for it is set by the next lines of code:
  1. dlgAlert.setPositiveButton("Ok",
  2. new DialogInterface.OnClickListener() {
  3. public void onClick(DialogInterface dialog, int which) {
  4. finish();
  5. System.exit(0);
  6. }
  7. });
The whole game logic is encapsulated in NormalActivity class. This class has the following data members for representing Tic-tac-toe game board and the player's turn:
  1. private int[][] table;
  2. private boolean xMove;
The layout of this activity is represented by a 3x3 grid of buttons that represent the state of the Tic-tac-toe board:
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:layout_marginLeft="0dp"
  6. android:background="@color/background"
  7. android:gravity="center_horizontal"
  8. android:label="@string/normal_activity_label"
  9. android:paddingBottom="@dimen/activity_vertical_margin"
  10. android:paddingLeft="@dimen/activity_horizontal_margin"
  11. android:paddingRight="@dimen/activity_horizontal_margin"
  12. android:paddingTop="@dimen/activity_vertical_margin"
  13. tools:context=".NormalActivity" >
  14.  
  15. <TextView
  16. android:id="@+id/moveTextView"
  17. android:layout_width="match_parent"
  18. android:layout_height="wrap_content"
  19. android:layout_alignParentTop="true"
  20. android:layout_marginLeft="34dp"
  21. android:layout_marginTop="18dp"
  22. android:gravity="center_horizontal"
  23. android:text="@string/x_move"
  24. android:textAppearance="?android:attr/textAppearanceLarge" />
  25.  
  26. <TableLayout
  27. android:id="@+id/tableLayout1"
  28. android:layout_width="match_parent"
  29. android:layout_height="wrap_content"
  30.  
  31. android:layout_below="@+id/moveTextView"
  32. android:layout_marginTop="32dp"
  33. android:gravity="center_vertical|center_horizontal" >
  34.  
  35. <TableRow
  36. android:id="@+id/tableRow1"
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content" >
  39.  
  40. android:id="@+id/button1"
  41. android:layout_width="match_parent"
  42. android:layout_height="wrap_content"
  43. android:height="100dp"
  44. android:onClick="@string/makeMove"
  45. android:text="@string/empty"
  46. android:width="100dp" />
  47.  
  48. android:id="@+id/button2"
  49. android:layout_width="match_parent"
  50. android:layout_height="wrap_content"
  51. android:onClick="@string/makeMove"
  52. android:text="@string/empty"
  53. android:height="100dp"
  54. android:width="100dp" />
  55.  
  56. android:id="@+id/button3"
  57. android:layout_width="match_parent"
  58. android:layout_height="wrap_content"
  59. android:onClick="@string/makeMove"
  60. android:text="@string/empty"
  61. android:height="100dp"
  62. android:width="100dp"/>
  63. </TableRow>
  64.  
  65. <TableRow
  66. android:id="@+id/tableRow2"
  67. android:layout_width="wrap_content"
  68. android:layout_height="wrap_content" >
  69.  
  70. android:id="@+id/button4"
  71. android:layout_width="wrap_content"
  72. android:layout_height="wrap_content"
  73. android:onClick="@string/makeMove"
  74. android:text="@string/empty"
  75. android:height="100dp"
  76. android:width="100dp" />
  77.  
  78. android:id="@+id/button5"
  79. android:layout_width="wrap_content"
  80. android:layout_height="wrap_content"
  81. android:onClick="@string/makeMove"
  82. android:text="@string/empty"
  83. android:height="100dp"
  84. android:width="100dp" />
  85. android:id="@+id/button6"
  86. android:layout_width="match_parent"
  87. android:layout_height="wrap_content"
  88. android:onClick="@string/makeMove"
  89. android:text="@string/empty"
  90. android:height="100dp"
  91. android:width="100dp"/>
  92. </TableRow>
  93. <TableRow>
  94. android:id="@+id/button7"
  95. android:layout_width="match_parent"
  96. android:layout_height="wrap_content"
  97. android:onClick="@string/makeMove"
  98. android:text="@string/empty"
  99. android:height="100dp"
  100. android:width="100dp" />
  101. android:id="@+id/button8"
  102. android:layout_width="match_parent"
  103. android:layout_height="wrap_content"
  104. android:onClick="@string/makeMove"
  105. android:text="@string/empty"
  106. android:height="100dp"
  107. android:width="100dp" />
  108. android:id="@+id/button9"
  109. android:layout_width="match_parent"
  110. android:layout_height="wrap_content"
  111. android:onClick="@string/makeMove"
  112. android:text="@string/empty"
  113. android:height="100dp"
  114. android:width="100dp"/>
  115. </TableRow>
  116. </TableLayout>
  117.  
  118.  
  119. </RelativeLayout>
For this case a Table Layout is used inside of Relative layout. NormalActivity Every press of the cell is handled by makeMove method from NormalActivity.java. This method gets the id of the button that is checked, check if this cell is empty. In the case the cell is empty, a record is added to board and after this the check for result is performed. We have to check all horizontal, vertical and diagonal lines from the board:
  1. private void checkResult() {
  2. boolean empty = false;
  3. AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
  4. for (int i = 0; i != 3; ++i)
  5. {
  6. for (int j = 0; j != 3; ++j)
  7. {
  8. if (table[i][j]==0)
  9. {
  10. empty = true;
  11. break;
  12. }
  13. }
  14. }
  15. if (!empty)
  16. {
  17. dlgAlert.setMessage("Draw!");
  18. dlgAlert.setTitle("Draw");
  19. dlgAlert.setCancelable(true);
  20. dlgAlert.setPositiveButton("Ok",
  21. new DialogInterface.OnClickListener() {
  22. public void onClick(DialogInterface dialog, int which) {
  23. finish();
  24.  
  25. }
  26. });
  27. dlgAlert.create().show();
  28.  
  29. }
  30. //check horizontal lines
  31. for (int i = 0; i != 3; ++i)
  32. {
  33. if (table[i][0] == 1 && table[i][1] == 1 && table[i][2] == 1)
  34. {
  35. dlgAlert.setMessage("O Player wins!");
  36. dlgAlert.setTitle("congratulations");
  37. dlgAlert.setCancelable(true);
  38. dlgAlert.setPositiveButton("Ok",
  39. new DialogInterface.OnClickListener() {
  40. public void onClick(DialogInterface dialog, int which) {
  41. finish();
  42. }
  43. });
  44. dlgAlert.create().show();
  45.  
  46. }
  47. if (table[i][0] == 2 && table[i][1] == 2 && table[i][2] == 2)
  48. {
  49. dlgAlert.setMessage("X Player wins!");
  50. dlgAlert.setTitle("congratulations");
  51. dlgAlert.setCancelable(true);
  52. dlgAlert.setPositiveButton("Ok",
  53. new DialogInterface.OnClickListener() {
  54. public void onClick(DialogInterface dialog, int which) {
  55. finish();
  56. }
  57. });
  58. dlgAlert.create().show();
  59.  
  60. }
  61. }
  62. //check vertical lines
  63. for (int i = 0; i != 3; ++i)
  64. {
  65. if (table[0][i] == 1 && table[1][i] == 1 && table[2][i] == 1)
  66. {
  67. dlgAlert.setMessage("O Player wins!");
  68. dlgAlert.setTitle("congratulations");
  69. dlgAlert.setCancelable(true);
  70. dlgAlert.setPositiveButton("Ok",
  71. new DialogInterface.OnClickListener() {
  72. public void onClick(DialogInterface dialog, int which) {
  73. finish();
  74. }
  75. });
  76. dlgAlert.create().show();
  77.  
  78. }
  79. if (table[0][i] == 2 && table[1][i] == 2 && table[2][i] == 2)
  80. {
  81. dlgAlert.setMessage("X Player wins!");
  82. dlgAlert.setTitle("congratulations");
  83. dlgAlert.setCancelable(true);
  84. dlgAlert.setPositiveButton("Ok",
  85. new DialogInterface.OnClickListener() {
  86. public void onClick(DialogInterface dialog, int which) {
  87. finish();
  88. }
  89. });
  90. dlgAlert.create().show();
  91.  
  92. }
  93. }
  94. //check diagonals
  95. if (table[0][0] == 1 && table[1][1] == 1 && table[2][2] == 1)
  96. {
  97. dlgAlert.setMessage("O Player wins!");
  98. dlgAlert.setTitle("congratulations");
  99. dlgAlert.setCancelable(true);
  100. dlgAlert.setPositiveButton("Ok",
  101. new DialogInterface.OnClickListener() {
  102. public void onClick(DialogInterface dialog, int which) {
  103. finish();
  104. }
  105. });
  106. dlgAlert.create().show();
  107.  
  108. }
  109. if (table[0][0] == 2 && table[1][1] == 2 && table[2][2] == 2)
  110. {
  111. dlgAlert.setMessage("X Player wins!");
  112. dlgAlert.setTitle("congratulations");
  113. dlgAlert.setCancelable(true);
  114. dlgAlert.setPositiveButton("Ok",
  115. new DialogInterface.OnClickListener() {
  116. public void onClick(DialogInterface dialog, int which) {
  117. finish();
  118. }
  119. });
  120. dlgAlert.create().show();
  121.  
  122. }
  123. if (table[0][2] == 1 && table[1][1] == 1 && table[2][0] == 1)
  124. {
  125. dlgAlert.setMessage("O Player wins!");
  126. dlgAlert.setTitle("congratulations");
  127. dlgAlert.setCancelable(true);
  128. dlgAlert.setPositiveButton("Ok",
  129. new DialogInterface.OnClickListener() {
  130. public void onClick(DialogInterface dialog, int which) {
  131. finish();
  132. }
  133. });
  134. dlgAlert.create().show();
  135.  
  136. }
  137. if (table[0][2] == 2 && table[1][1] == 2 && table[2][0] == 2)
  138. {
  139. dlgAlert.setMessage("X Player wins!");
  140. dlgAlert.setTitle("congratulations");
  141. dlgAlert.setCancelable(true);
  142. dlgAlert.setPositiveButton("Ok",
  143. new DialogInterface.OnClickListener() {
  144. public void onClick(DialogInterface dialog, int which) {
  145. finish();
  146. }
  147. });
  148. dlgAlert.create().show();
  149.  
  150. }
  151. }
If a player fills the line - a congratulation message is shown in the Dialog. Win The congratulation dialog has an" "OK" button and after a player presses this button, the game is returned to the main Activity and a new game can be started. You can find the complete Eclipse project attached to this tutorial. In the case you have any questions, you can ask me in comment and you will get an answer.

Comments

Submitted byconnor (not verified)on Thu, 01/22/2015 - 01:01

doesn't work. tried playing it. x goes first then nothing happens. 0 doesn't move. click anywhere and it says space is not empty.

Submitted byTeimoor (not verified)on Thu, 09/22/2016 - 15:31

I want to learn programming in AIDE please wrote the tic tac toe in AIDE . i have this errors even in hello world example: error parsing xml:no document element Plz reply in my email: [email protected]
Submitted bytanimax (not verified)on Wed, 12/28/2016 - 01:38

thanks for this tuto but when i try it doesnt work. I got a error 0 doesn't move i got this error This cell is not empty
Submitted byKeithH (not verified)on Wed, 05/03/2017 - 03:52

The problem people are seeing is that the original programmer used magic numbers for the getId to identify which button got pressed. To fix it, replace the case statement in NormalActivity.java with: switch(id) { case R.id.button1: break; case R.id.button2: x = 0; y = 1; break; case R.id.button3: x = 0; y = 2; break; case R.id.button4: x = 1; y = 0; break; case R.id.button5: x = 1; y = 1; break; case R.id.button6: x = 1; y = 2; break; case R.id.button7: x = 2; y = 0; break; case R.id.button8: x = 2; y = 1; break; case R.id.button9: x = 2; y = 2; break; }
Submitted byDanish Alam (not verified)on Wed, 06/07/2017 - 02:58

Greetings...! I'm developing tic tac toe game on android studio. Major task is multi-player mode, where application is install on two android phones. Both player first make connection and then play game turn by turn. What are the techniques should I used ?
Submitted byKishantiwari (not verified)on Tue, 03/22/2022 - 10:27

No mor comment

Add new comment