Welcome to part-4 of this Tic Tac Toe Android Kotlin beginner tutorial series where we will be making a fun Tic Tac Toe game app. To go to part 1 of this series, click here.
In the previous tutorial, we added onClickListeners to each of the buttons but we just made a little Toast message appear on click telling us what button was clicked. Now it is time we finally turn all that boring clicking into the Tic Tac Toe game that was promised. Here’s what we will have once we are done with this part.
Video Tutorial
If you would rather watch a video then read all the way, you can check out this. For this article, please watch it from 4:15.
The video is a quick walkthrough. For detailed tutorial, please consider reading this article. If you choose to watch the video and find it useful, please give it a thumbsup and subscribe to the channel. Thank you. Lets continue.
Modify GameBoard buttons onClickListener
Previously, in our initButton()
function which initializes the gameboard buttons, we were just displaying a toast message when clicked with the code below.
Toast.makeText(
applicationContext,
"button $r$c clicked",
Toast.LENGTH_SHORT).show()
Change the above code to the code below.
onBtnClick(btn)
Now our initButton()
function looks like this.
private fun initButton(r: Int, c: Int): Button {
val btn: Button =
findViewById(resources.getIdentifier("btn$r$c", "id", packageName))
btn.setOnClickListener{
onBtnClick(btn)
}
return btn
}
Next, we define the onBtnClick()
function. In this, we want to put “X” or “O” on a GameBoard Button
only if it is empty i.e. hasn’t already been clicked. If we’ve already clicked it i.e. btn.text
is not an empty string, we don’t want to do anything.
Then we’re incrementing the roundCount
variable here. On each click, we’re checking if somebody has won with the checkForWin()
function. If it returns true
, then depending on which player’s turn it is, we can decide who has won and then can run the winning routine with win()
function.
If the number of rounds is 9, that means all the 3×3 buttons have been clicked and there is no winner so we say it is a draw()
.
And finally, if nobody has won and it is not even a draw yet that means the game is still going and we just switch the player turn.
private fun onBtnClick(btn: Button) {
if(btn.text != "") return
if(player1Turn){
btn.text = "X"
}else{
btn.text = "O"
}
roundCount++
if(checkForWin()){
if(player1Turn) win(1) else win(2)
}else if(roundCount == 9){
draw()
}else{
player1Turn = !player1Turn
}
}
The CheckForWin() Function
We get a win when all the buttons on any of the lines shown below have either all “X”es or all “O”s. The winning logic is mostly from the tutorial I was following on youtube from the channel CodingInFlow. You can check that out here.

The fields
variable in the code below is a 3×3 array where we populate the array cell with the corresponding button text on the gameboard. Basically a one on one map of the “X”es and “O”s which is easier for us to work with. Then we check for win as per the image above.
private fun checkForWin(): Boolean {
val fields = Array(3){r->
Array(3){c->
buttons[r][c].text
}
}
for(i in 0..2){
if((fields[i][0] == fields[i][1])&&
(fields[i][0] == fields[i][2])&&
(fields[i][0] != "")
)return true
}
for(i in 0..2){
if(
(fields[0][i] == fields[1][i])&&
(fields[0][i] == fields[2][i])&&
(fields[0][i] != "")
)return true
}
if(
(fields[0][0] == fields[1][1])&&
(fields[0][0] == fields[2][2])&&
(fields[0][0] != "")
) return true
if(
(fields[0][2] == fields[1][1])&&
(fields[0][2] == fields[2][0])&&
(fields[0][2] != "")
) return true
return false
}
We Have A Winner
The win function takes an integer argument which tells it which player has won. As per that, we increment the winner’s points and then display a small winning Toast
message.
Then we update the scores of each players with updateScore()
function and clear up the gameboard with clearBoard()
function.
private fun win(player:Int){
if(player == 1) player1Points++ else player2Points++
Toast.makeText(
applicationContext,
"Player $player Won!",
Toast.LENGTH_SHORT).show()
updateScore()
clearBoard()
}
Oh It is a Draw!
We display a simple Toast
message telling user that it is a draw and then clear up the gameboard with clearBoard()
function.
private fun draw(){
Toast.makeText(
applicationContext,
"Match Draw!",
Toast.LENGTH_SHORT).show()
clearBoard()
}
Clear The Board And Update The Score
In the clearBoard()
function, we set all the button texts to empty strings, reset rounds to 0 and set player1Turn
to true
.
private fun clearBoard() {
for (i in 0..2){
for(j in 0..2){
buttons[i][j].text = ""
}
}
roundCount = 0
player1Turn = true
}
In the updateScore()
function, we just update the test in Player 1 and Player 2 TextView
s with the updated scores.
private fun updateScore() {
textViewPlayer1.text = "Player 1: $player1Points"
textViewPlayer2.text = "Player 2: $player2Points"
}
The Reset Game Button
Set all game variables to their default values.
btnReset.setOnClickListener{
player1Points = 0
player2Points = 0
updateScore()
clearBoard()
}
In the next and final part of this Tic Tac Toe Android Kotlin tutorial series, we’ll turn this simple looking game into the beauty that i promised. Stay tuned.