• Post author:
  • Post category:Android
  • Reading time:10 mins read

Welcome to part-3 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 this tutorial, we will add click listeners (do something when a button is clicked) to all the buttons in the layout created in the previous tutorial. We’ll set up all the variables we need for our app and we’ll display a toast message on button clicks telling us what button was clicked. We’ll finalize the functionality in the next tutorial.
This is what we will have at the end of this tutorial.

Button Click Listeners added

Video Tutorial

If you would rather watch a video then read all the way, you can check out this.

part 3 + part 4 youtube video

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.

Alright, now open the MainActivity.kt file. It looks something like this:

package com.example.tictactoe

//bunch of import statements
import ...

class MainActivity : AppCompatActivity() {

    //TODO() 1: declare class variables here

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //TODO() 2: initialize player 1 and player 2 textviews
        //TODO() 3: initialize 3x3 buttons
        //TODO() 5: initialize resetbutton
        //TODO() 6: set reset button onclick listener

    }
        //TODO() 4: declare initButton() function to initialize and set onClickListener to each button in 3x3 array.
}

TO-DOs:

  1. Declare class variables
  2. Initialize Player 1 and Player 2 TextViews
  3. Initialize 3×3 GameBoard Buttons
  4. Define initButton() function
  5. Initialize Reset Button
  6. Set Reset button onClickListener

Note:

Please take a note of the TODO() comments in the above code block to know where the following code snippets go.

1. Declare Class Variables

We declare these variables here as we will be accessing them throught the MainActivity Class.

lateinit var buttons: Array<Array<Button>>
lateinit var textViewPlayer1: TextView
lateinit var textViewPlayer2: TextView

private var player1Turn: Boolean = true
private var roundCount: Int = 0
private var player1Points: Int = 0
private var player2Points: Int = 0

Lateinit

In Kotlin, you must initialize an object’s properties when declaring the object. This implies that when you obtain an instance of a class, you can immediately reference any of its accessible properties. The View objects in a Fragment, however, aren’t ready to be inflated until calling Fragment#onCreateView, so you need a way to defer property initialization for a View.

https://developer.android.com/kotlin/common-patterns

Basically, you want to use lateinit when you have to declare a variable but you can’t initialize it then and there and can only initialize it later. Hence, the term lateinit. In our case, we want to declare the View variables outside the onCreate() function so that we can use them all over the MainActivity class. But the View Objects aren’t ready until the onCreate has been called. So we declare them here and initialize them inside onCreate.

Var v/s Val

Every variable in Kotlin must be declared.

We use var when the variable we declare is going to change or be reassigned a value. Note that we have to use var with lateinit since we will need to initialize the lateinit variables later i.e. reassign them a value.

We use val when the variable we are declaring isn’t going to change and need to be initialized just once i.e. for Read-Only or immutable variables.

Visibility Modifier: Private

The variables declared with a private visibility modifier are visible only inside the class (including all its members) where they are declared.

2. Initialize Player 1 and Player 2 textView variables

textViewPlayer1 = findViewById(R.id.player1TextView)
textViewPlayer2 = findViewById(R.id.player2TextView)

findViewById returns a reference to an instance of View. And with R.id.player1TextView, we are asking findViewById to give us an Android Resource(R) with an id of player1TextView.

2. Initialize 2D buttons array

buttons = Array(3){r->
            Array(3){c->
                initButton(r, c)
            }
        }

3. Define initButton() function

private fun initButton(r: Int, c: Int): Button {
        val btn: Button =
            findViewById(resources.getIdentifier("btn$r$c", "id", packageName))
        btn.setOnClickListener{
            Toast.makeText(
                applicationContext, 
                "button $r$c clicked", 
                Toast.LENGTH_SHORT).show()
        }
        return btn
    }

resources.getIndentifier() returns a resource identifier for the given resource name. For more on this, check out this link.

4. Initialize Reset button

val btnReset: Button = findViewById(R.id.btnReset)

5. Set Reset button OnClickListener

btnReset.setOnClickListener{
            Toast.makeText(
                applicationContext, 
                "Reset game button clicked!", 
                Toast.LENGTH_SHORT).show()
        }

Final Code

Finally, here is all the code put together.

package com.example.tictactoe

import android.graphics.drawable.Drawable
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageButton
import android.widget.TextView
import android.widget.Toast
import androidx.core.content.res.ResourcesCompat

class MainActivity : AppCompatActivity() {

    lateinit var buttons: Array<Array<Button>>
    lateinit var textViewPlayer1: TextView
    lateinit var textViewPlayer2: TextView

    private var player1Turn: Boolean = true
    private var roundCount: Int = 0
    private var player1Points: Int = 0
    private var player2Points: Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        textViewPlayer1 = findViewById(R.id.player1TextView)
        textViewPlayer2 = findViewById(R.id.player2TextView)

        buttons = Array(3){r->
            Array(3){c->
                initButton(r, c)
            }
        }

        val btnReset: Button = findViewById(R.id.btnReset)
        btnReset.setOnClickListener{
            Toast.makeText(
                applicationContext, 
                "Reset game button clicked!", 
                Toast.LENGTH_SHORT).show()
        }

    }

    private fun initButton(r: Int, c: Int): Button {
        val btn: Button =
            findViewById(resources.getIdentifier("btn$r$c", "id", packageName))
        btn.setOnClickListener{
            Toast.makeText(
                applicationContext, 
                "button $r$c clicked", 
                Toast.LENGTH_SHORT).show()
        }
        return btn
    }

}

Alright. This was fun and all but in the next one, we’ll really get our hands dirty and turn all this clicking into a proper tic tac toe game. Let’s move on to part-4 of this series.

This Post Has One Comment

Comments are closed.