¿Cómo construir un juego de Tic Tac Toe con modo fuera de línea y en línea en Android?

En este artículo, vamos a crear un juego de tres en raya que tiene modos en línea y fuera de línea. Entonces, para este proyecto, vamos a usar Kotlin y XML . Tic-Tac-Toe es un juego de dos jugadores. Cada jugador tiene X u O . Tanto el jugador juega uno por uno simultáneamente. En un movimiento, los jugadores deben seleccionar una posición en la cuadrícula de 3×3 y poner su marca en ese lugar. El juego se ejecuta de forma continua hasta que uno puede ganar. En el artículo anterior, creamos un juego de tres en raya simple en Android , pero en este artículo, tenemos las siguientes características adicionales dentro de la aplicación:

  • Un solo jugador
  • Multijugador
    • Juego en linea
      • Crea y únete ingresando el código del juego
    • Juego fuera de línea

qué

Terminologías básicas

  • XML: Su forma completa es un lenguaje de marcado extensible y es un conjunto de códigos y etiquetas.
  • Kotlin: es un lenguaje de programación gratuito y de código abierto desarrollado por JetBrains.
  • Android Studio: Android Studio es el entorno de desarrollo integrado oficial para el desarrollo de aplicaciones de Android.
  • Firebase: Es un servicio backend proporcionado por Google.

Implementación paso a paso

Paso 1: Crear un nuevo proyecto

Para crear un nuevo proyecto en Android Studio, consulte Cómo crear/iniciar un nuevo proyecto en Android Studio . Tenga en cuenta que seleccione Kotlin como lenguaje de programación. 

Paso 2: trabajar con el archivo activity_main.xml

Vaya a la aplicación > res > diseño > actividad_principal.xml y agregue el siguiente código a ese archivo. A continuación se muestra el código para el archivo  activity_main.xml .

XML

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFEB3B"
    android:gravity="center"
    tools:context=".MainActivity">
     
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="20dp"
        android:layout_margin="10dp"
        android:gravity="center">
 
        <TextView
            android:id="@+id/textView"
            android:layout_width="110dp"
            android:layout_height="30dp"
            android:layout_marginLeft="40dp"
            android:text="Player1 : 0"
            android:textColor="#000000"
            android:textSize="18dp" />
 
        <TextView
            android:id="@+id/textView2"
            android:layout_width="110dp"
            android:layout_height="30dp"
            android:layout_marginLeft="30dp"
            android:text="Player2 : 0"
            android:textColor="#000000"
            android:textSize="18dp" />
    </LinearLayout>
 
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:gravity="center">
 
        <Button
            android:id="@+id/button"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button2"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button3"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
    </TableRow>
 
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">
 
        <Button
            android:id="@+id/button4"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button5"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button6"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
    </TableRow>
 
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">
 
        <Button
            android:id="@+id/button7"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button8"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button9"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
         
    </TableRow>
 
    <LinearLayout
        android:layout_marginTop="15dp"
        android:gravity="center">
 
        <Button
            android:id="@+id/button10"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Reset" />
    </LinearLayout>
     
</TableLayout>

Después de escribir tanto código, la interfaz de usuario se ve así: 

Paso 3: trabajar con el archivo MainActivity.kt 

Vaya al archivo MainActivity.kt y consulte el siguiente código. A continuación se muestra el código del archivo MainActivity.kt . Se agregan comentarios dentro del código para comprender el código con más detalle. Aquí vamos a agregar funcionalidad a nuestra aplicación. 

Kotlin

class MainActivity : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
         
        // reset button listener
        button10.setOnClickListener {
            reset()
 
        }
    }
     
    // player winning count
    var player1Count = 0
    var player2Count = 0
   
      // this function handle the click event on the board.
    fun clickfun(view:View)
    {
        if(playerTurn) {
            val but = view as Button
            var cellID = 0
            when (but.id) {
                R.id.button -> cellID = 1
                R.id.button2 -> cellID = 2
                R.id.button3 -> cellID = 3
                R.id.button4 -> cellID = 4
                R.id.button5 -> cellID = 5
                R.id.button6 -> cellID = 6
                R.id.button7 -> cellID = 7
                R.id.button8 -> cellID = 8
                R.id.button9 -> cellID = 9
            }
            playerTurn = false;
            Handler().postDelayed(Runnable { playerTurn = true } , 600)
            playnow(but, cellID)
        }
    }
    var player1 = ArrayList<Int>()
    var player2 = ArrayList<Int>()
    var emptyCells = ArrayList<Int>()
    var activeUser = 1
   
      // this function update update the game board after every move.
    fun playnow(buttonSelected:Button , currCell:Int)
    {   val audio = MediaPlayer.create(this , R.raw.poutch)
        if(activeUser == 1)
        {
            buttonSelected.text = "X"
            buttonSelected.setTextColor(Color.parseColor("#EC0C0C"))
            player1.add(currCell)
            emptyCells.add(currCell)
            audio.start()
            buttonSelected.isEnabled = false
            Handler().postDelayed(Runnable { audio.release() } , 200)
            val checkWinner = checkwinner()
            if(checkWinner == 1){
                Handler().postDelayed(Runnable { reset() } , 2000)
            }
            else if(singleUser){
                Handler().postDelayed(Runnable { robot() } , 500)
            }
            else
                activeUser = 2
        }
        else
        {
            buttonSelected.text = "O"
            audio.start()
            buttonSelected.setTextColor(Color.parseColor("#D22BB804"))
            activeUser = 1
            player2.add(currCell)
            emptyCells.add(currCell)
            Handler().postDelayed(Runnable { audio.release() } , 200)
            buttonSelected.isEnabled = false
            val checkWinner  = checkwinner()
            if(checkWinner == 1)
                Handler().postDelayed(Runnable { reset() } , 4000)
        }
    }
     
    // this function resets the game.
    fun reset()
    {
        player1.clear()
        player2.clear()
        emptyCells.clear()
        activeUser = 1;
        for(i in 1..9)
        {
            var buttonselected : Button?
            buttonselected = when(i){
                1 -> button
                2 -> button2
                3 -> button3
                4 -> button4
                5 -> button5
                6 -> button6
                7 -> button7
                8 -> button8
                9 -> button9
                else -> {button}
            }
            buttonselected.isEnabled = true
            buttonselected.text = ""
            textView.text = "Player1 : $player1Count"
            textView2.text = "Player2 : $player2Count"
        }
    }
     
    // this function disable all the button on the board for a while.
       fun disableReset()
    {
        button10.isEnabled = false
        Handler().postDelayed(Runnable { button10.isEnabled = true } , 2200)
    }
}

Después de escribir tanto código, nuestra aplicación está lista con la funcionalidad básica. Ahora agreguemos la funcionalidad de robot para el modo de un jugador:

Kotlin

// This function automatically make a move at a random position.
fun robot()
    {
        val rnd = (1..9).random()
        if(emptyCells.contains(rnd))
            robot()
        else {
                val buttonselected : Button?
                buttonselected = when(rnd) {
                    1 -> button
                    2 -> button2
                    3 -> button3
                    4 -> button4
                    5 -> button5
                    6 -> button6
                    7 -> button7
                    8 -> button8
                    9 -> button9
                    else -> {button}
                }
            emptyCells.add(rnd);
              // move audio
            val audio = MediaPlayer.create(this , R.raw.poutch)
            audio.start()
            Handler().postDelayed(Runnable { audio.release() } , 500)
            buttonselected.text = "O"
            buttonselected.setTextColor(Color.parseColor("#D22BB804"))
            player2.add(rnd)
            buttonselected.isEnabled = false
            var checkWinner = checkwinner()
            if(checkWinner == 1)
                Handler().postDelayed(Runnable { reset() } , 2000)
     }
}

Intentemos jugar en modo único: 

Paso 4: ahora implementemos la característica principal de nuestra aplicación, es decir, el modo en línea 

Aquí vamos a usar firebase para nuestra funcionalidad de backend. Entonces, lo que estamos haciendo aquí es escuchar en una base de datos de códigos en particular y, si hay algún cambio en la base de datos, ejecutar un evento en el lado del cliente para actualizar el movimiento realizado por el oponente.

Kotlin

// Here we are using firebase method addChildEventListener to listen the database for events.
FirebaseDatabase.getInstance().reference.child("data").child(code).addChildEventListener(object : ChildEventListener{
            override fun onCancelled(error: DatabaseError) {
                TODO("Not yet implemented")
            }
 
            override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {
                TODO("Not yet implemented")
            }
 
            override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {
                TODO("Not yet implemented")
            }
            // this event happens when a new data added to a database.
            override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
                var data = snapshot.value
                if(isMyMove==true){
                    isMyMove = false
                    moveonline(data.toString() , isMyMove)
                }
                else{
                    isMyMove = true
                    moveonline(data.toString() , isMyMove)
                }
 
            }
            // this will happen when any player click on the reset button
            override fun onChildRemoved(snapshot: DataSnapshot) {
                reset()
                errorMsg("Game Reset")
            }
     })
}

Paso 5: crea 4 nuevas actividades vacías

Consulte este artículo Cómo crear una nueva actividad en Android Studio usando accesos directos y cree 4 nuevas actividades vacías y nombre la actividad como Firstpage, SecondPage, ThirdPage y CodeActivity. A continuación se muestra el código de este archivo de actividad para los archivos XML y Kotlin, respectivamente.

XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".Firstpage">
 
    <TextView
        android:id="@+id/textView3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Tic Tac Toe"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="25dp" />
 
    <Button
        android:id="@+id/button11"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="90dp"
        android:background="#B2BCF8"
        android:gravity="center"
        android:text="Single Player" />
 
    <Button
        android:id="@+id/button12"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:background="#B2BCF8"
        android:gravity="center"
        android:text="Multi Player" />
     
</LinearLayout>

Kotlin

package com.example.tictactoeapp
 
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import kotlinx.android.synthetic.main.activity_firstpage.*
 
var singleUser = false
 
class Firstpage : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_firstpage)
 
        button11.setOnClickListener {
            startActivity(Intent(this, MainActivity::class.java))
            singleUser = true;
        }
        button12.setOnClickListener {
            startActivity(Intent(this, SecondPage::class.java))
            singleUser = false;
        }
    }
 
    override fun onBackPressed() {
        ActivityCompat.finishAffinity(this)
    }
}

XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".Firstpage">
 
    <TextView
        android:id="@+id/textView3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Tic Tac Toe"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="25dp" />
 
    <Button
        android:id="@+id/buttonOnline"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="90dp"
        android:background="#B2BCF8"
        android:gravity="center"
        android:text="Online Game" />
 
    <Button
        android:id="@+id/buttonOffline"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:background="#B2BCF8"
        android:gravity="center"
        android:text="Offline Game" />
     
</LinearLayout>

Kotlin

package com.example.tictactoeapp
 
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_second_page.*
 
var Online = true;
 
class SecondPage : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_second_page)
        buttonOnline.setOnClickListener {
            startActivity(Intent(this, CodeActivity::class.java))
            singleUser = true;
            Online = true;
        }
        buttonOffline.setOnClickListener {
            startActivity(Intent(this, MainActivity::class.java))
            singleUser = false;
            Online = false;
        }
    }
}

XML

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFEB3B"
    android:gravity="center"
    tools:context=".MainActivity">
     
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="20dp"
        android:layout_margin="10dp"
        android:gravity="center">
 
        <TextView
            android:id="@+id/textView3"
            android:layout_width="132dp"
            android:layout_height="30dp"
            android:layout_marginLeft="40dp"
            android:text="Turn : Player 1"
            android:textColor="#000000"
            android:textSize="18dp" />
 
        <TextView
            android:id="@+id/textView"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_marginLeft="40dp"
            android:text="Player1 : 0"
            android:textColor="#000000"
            android:textSize="18dp" />
 
        <TextView
            android:id="@+id/textView2"
            android:layout_width="110dp"
            android:layout_height="30dp"
            android:layout_marginLeft="30dp"
            android:text="Player2 : 0"
            android:textColor="#000000"
            android:textSize="18dp" />
    </LinearLayout>
 
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:gravity="center">
 
        <Button
            android:id="@+id/button11"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button12"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button13"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
    </TableRow>
 
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">
 
        <Button
            android:id="@+id/button14"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button15"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button16"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
    </TableRow>
 
    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center">
 
        <Button
            android:id="@+id/button17"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button18"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
        <Button
            android:id="@+id/button19"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginLeft="5dp"
            android:layout_marginTop="5dp"
            android:background="#FFFFFF"
            android:onClick="clickfun"
            android:textColor="#000000"
            android:textSize="60dp" />
 
 
    </TableRow>
 
    <LinearLayout
        android:layout_marginTop="15dp"
        android:gravity="center">
 
        <Button
            android:id="@+id/button110"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Reset" />
    </LinearLayout>
     
</TableLayout>

Kotlin

package com.example.tictactoeapp
 
import android.graphics.Color
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.database.ChildEventListener
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import kotlinx.android.synthetic.main.activity_third_page.*
import kotlin.system.exitProcess
 
var isMyMove = isCodeMaker;
 
class ThirdPage : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_third_page)
        button110.setOnClickListener {
            reset()
        }
        FirebaseDatabase.getInstance().reference.child("data").child(code)
            .addChildEventListener(object : ChildEventListener {
                override fun onCancelled(error: DatabaseError) {
                    TODO("Not yet implemented")
                }
 
                override fun onChildMoved(snapshot: DataSnapshot, previousChildName: String?) {
                    TODO("Not yet implemented")
                }
 
                override fun onChildChanged(snapshot: DataSnapshot, previousChildName: String?) {
                    TODO("Not yet implemented")
                }
 
                override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
                    var data = snapshot.value
                    if (isMyMove == true) {
                        isMyMove = false
                        moveonline(data.toString(), isMyMove)
                    } else {
                        isMyMove = true
                        moveonline(data.toString(), isMyMove)
                    }
 
 
                }
 
                override fun onChildRemoved(snapshot: DataSnapshot) {
                    reset()
                    errorMsg("Game Reset")
                }
 
            })
    }
 
    var player1Count = 0
    var player2Count = 0
    fun clickfun(view: View) {
        if (isMyMove) {
            val but = view as Button
            var cellOnline = 0
            when (but.id) {
                R.id.button11 -> cellOnline = 1
                R.id.button12 -> cellOnline = 2
                R.id.button13 -> cellOnline = 3
                R.id.button14 -> cellOnline = 4
                R.id.button15 -> cellOnline = 5
                R.id.button16 -> cellOnline = 6
                R.id.button17 -> cellOnline = 7
                R.id.button18 -> cellOnline = 8
                R.id.button19 -> cellOnline = 9
                else -> {
                    cellOnline = 0
                }
 
            }
            playerTurn = false;
            Handler().postDelayed(Runnable { playerTurn = true }, 600)
            playnow(but, cellOnline)
            updateDatabase(cellOnline);
 
        } else {
            Toast.makeText(this, "Wait for your turn", Toast.LENGTH_LONG).show()
        }
    }
 
    var player1 = ArrayList<Int>()
    var player2 = ArrayList<Int>()
    var emptyCells = ArrayList<Int>()
    var activeUser = 1
    fun playnow(buttonSelected: Button, currCell: Int) {
        val audio = MediaPlayer.create(this, R.raw.poutch)
 
        buttonSelected.text = "X"
        emptyCells.remove(currCell)
        textView3.text = "Turn : Player 2"
        buttonSelected.setTextColor(Color.parseColor("#EC0C0C"))
        player1.add(currCell)
        emptyCells.add(currCell)
        audio.start()
        //Handler().postDelayed(Runnable { audio.pause() } , 500)
        buttonSelected.isEnabled = false
        Handler().postDelayed(Runnable { audio.release() }, 200)
        checkwinner()
        /*val checkWinner = checkwinner()
        if(checkWinner == 1) {
            Handler().postDelayed(Runnable { reset() }, 2000)
        }*/
 
        /*else
        {
            buttonSelected.text = "O"
            audio.start()
            buttonSelected.setTextColor(Color.parseColor("#D22BB804"))
            //Handler().postDelayed(Runnable { audio.pause() } , 500)
            activeUser = 1
            player2.add(currCell)
            emptyCells.add(currCell)
            Handler().postDelayed(Runnable { audio.release() } , 200)
            buttonSelected.isEnabled = false
            val checkWinner  = checkwinner()
            if(checkWinner == 1)
                Handler().postDelayed(Runnable { reset() } , 4000)
        }*/
 
    }
 
    fun moveonline(data: String, move: Boolean) {
        val audio = MediaPlayer.create(this, R.raw.poutch)
 
        if (move) {
            var buttonselected: Button?
            buttonselected = when (data.toInt()) {
                1 -> button11
                2 -> button12
                3 -> button13
                4 -> button14
                5 -> button15
                6 -> button16
                7 -> button17
                8 -> button18
                9 -> button19
                else -> {
                    button11
                }
            }
            buttonselected.text = "O"
            textView3.text = "Turn : Player 1"
            buttonselected.setTextColor(Color.parseColor("#D22BB804"))
            player2.add(data.toInt())
            emptyCells.add(data.toInt())
            audio.start()
            //Handler().postDelayed(Runnable { audio.pause() } , 500)
            Handler().postDelayed(Runnable { audio.release() }, 200)
            buttonselected.isEnabled = false
            checkwinner()
        }
    }
 
    fun updateDatabase(cellId: Int) {
        FirebaseDatabase.getInstance().reference.child("data").child(code).push().setValue(cellId);
    }
 
    fun checkwinner(): Int {
        val audio = MediaPlayer.create(this, R.raw.success)
        if ((player1.contains(1) && player1.contains(2) && player1.contains(3)) || (player1.contains(
                1
            ) && player1.contains(4) && player1.contains(7)) ||
            (player1.contains(3) && player1.contains(6) && player1.contains(9)) || (player1.contains(
                7
            ) && player1.contains(8) && player1.contains(9)) ||
            (player1.contains(4) && player1.contains(5) && player1.contains(6)) || (player1.contains(
                1
            ) && player1.contains(5) && player1.contains(9)) ||
            player1.contains(3) && player1.contains(5) && player1.contains(7) || (player1.contains(2) && player1.contains(
                5
            ) && player1.contains(8))
        ) {
            player1Count += 1
            buttonDisable()
            audio.start()
            disableReset()
            Handler().postDelayed(Runnable { audio.release() }, 4000)
            val build = AlertDialog.Builder(this)
            build.setTitle("Game Over")
            build.setMessage("Player 1 Wins!!" + "\n\n" + "Do you want to play again")
            build.setPositiveButton("Ok") { dialog, which ->
                reset()
                audio.release()
            }
            build.setNegativeButton("Exit") { dialog, which ->
                audio.release()
                removeCode()
                exitProcess(1)
 
            }
            Handler().postDelayed(Runnable { build.show() }, 2000)
            return 1
 
 
        } else if ((player2.contains(1) && player2.contains(2) && player2.contains(3)) || (player2.contains(
                1
            ) && player2.contains(4) && player2.contains(7)) ||
            (player2.contains(3) && player2.contains(6) && player2.contains(9)) || (player2.contains(
                7
            ) && player2.contains(8) && player2.contains(9)) ||
            (player2.contains(4) && player2.contains(5) && player2.contains(6)) || (player2.contains(
                1
            ) && player2.contains(5) && player2.contains(9)) ||
            player2.contains(3) && player2.contains(5) && player2.contains(7) || (player2.contains(2) && player2.contains(
                5
            ) && player2.contains(8))
        ) {
            player2Count += 1
            audio.start()
            buttonDisable()
            disableReset()
            Handler().postDelayed(Runnable { audio.release() }, 4000)
            val build = AlertDialog.Builder(this)
            build.setTitle("Game Over")
            build.setMessage("Player 2 Wins!!" + "\n\n" + "Do you want to play again")
            build.setPositiveButton("Ok") { dialog, which ->
                reset()
                audio.release()
            }
            build.setNegativeButton("Exit") { dialog, which ->
                audio.release()
                removeCode()
                exitProcess(1)
            }
            Handler().postDelayed(Runnable { build.show() }, 2000)
            return 1
        } else if (emptyCells.contains(1) && emptyCells.contains(2) && emptyCells.contains(3) && emptyCells.contains(
                4
            ) && emptyCells.contains(5) && emptyCells.contains(6) && emptyCells.contains(7) &&
            emptyCells.contains(8) && emptyCells.contains(9)
        ) {
 
            val build = AlertDialog.Builder(this)
            build.setTitle("Game Draw")
            build.setMessage("Nobody Wins" + "\n\n" + "Do you want to play again")
            build.setPositiveButton("Ok") { dialog, which ->
                audio.release()
                reset()
            }
            build.setNegativeButton("Exit") { dialog, which ->
                audio.release()
                exitProcess(1)
                removeCode()
            }
            build.show()
            return 1
 
        }
        return 0
    }
 
    fun reset() {
        player1.clear()
        player2.clear()
        emptyCells.clear()
        activeUser = 1;
        for (i in 1..9) {
            var buttonselected: Button?
            buttonselected = when (i) {
                1 -> button11
                2 -> button12
                3 -> button13
                4 -> button14
                5 -> button15
                6 -> button16
                7 -> button17
                8 -> button18
                9 -> button19
                else -> {
                    button11
                }
            }
            buttonselected.isEnabled = true
            buttonselected.text = ""
            textView.text = "Player1 : $player1Count"
            textView2.text = "Player2 : $player2Count"
            isMyMove = isCodeMaker
            //startActivity(Intent(this,ThirdPage::class.java))
            if (isCodeMaker) {
                FirebaseDatabase.getInstance().reference.child("data").child(code).removeValue()
            }
 
 
        }
    }
 
    fun buttonDisable() {
        for (i in 1..9) {
            val buttonSelected = when (i) {
                1 -> button11
                2 -> button12
                3 -> button13
                4 -> button14
                5 -> button15
                6 -> button16
                7 -> button17
                8 -> button18
                9 -> button19
                else -> {
                    button11
                }
 
            }
            if (buttonSelected.isEnabled == true)
                buttonSelected.isEnabled = false
        }
    }
 
    fun buttoncelldisable() {
        emptyCells.forEach {
            val buttonSelected = when (it) {
                1 -> button11
                2 -> button12
                3 -> button13
                4 -> button14
                5 -> button15
                6 -> button16
                7 -> button17
                8 -> button18
                9 -> button19
                else -> {
                    button11
                }
 
            }
            if (buttonSelected.isEnabled == true)
                buttonSelected.isEnabled = false;
        }
    }
 
    fun removeCode() {
        if (isCodeMaker) {
            FirebaseDatabase.getInstance().reference.child("codes").child(keyValue).removeValue()
        }
    }
 
    fun errorMsg(value: String) {
        Toast.makeText(this, value, Toast.LENGTH_SHORT).show()
    }
 
    fun disableReset() {
        button110.isEnabled = false
        Handler().postDelayed(Runnable { button110.isEnabled = true }, 2200)
    }
 
    override fun onBackPressed() {
        removeCode()
        if (isCodeMaker) {
            FirebaseDatabase.getInstance().reference.child("data").child(code).removeValue()
        }
        exitProcess(0)
    }
}

XML

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".CodeActivity">
 
    <TextView
        android:id="@+id/textView4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="130dp"
        android:gravity="center"
        android:text="Tic Tac Toe"
        android:textColor="@color/colorPrimaryDark"
 
        android:textSize="25dp" />
 
    <EditText
        android:id="@+id/GameCode"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="25dp"
        android:gravity="center"
        android:hint="Enter Game Code"
        android:inputType="textPersonName" />
 
    <Button
        android:id="@+id/Create"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="30dp"
        android:background="#B2BCF8"
        android:text="Create" />
 
    <Button
        android:id="@+id/Join"
        android:layout_width="150dp"
        android:layout_height="wrap_content"
        android:background="#B2BCF8"
        android:text="Join" />
 
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone" />
     
</LinearLayout>

Kotlin

package com.example.tictactoeapp
 
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import kotlinx.android.synthetic.main.activity_code.*
 
var isCodeMaker = true;
var code = "null";
var codeFound = false
var checkTemp = true
var keyValue: String = "null"
 
class CodeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_code)
        Create.setOnClickListener {
            code = "null";
            codeFound = false
            checkTemp = true
            keyValue = "null"
            code = GameCode.text.toString()
            Create.visibility = View.GONE
            Join.visibility = View.GONE
            GameCode.visibility = View.GONE
            textView4.visibility = View.GONE
            progressBar.visibility = View.VISIBLE
            if (code != "null" && code != null && code != "") {
 
                isCodeMaker = true;
                FirebaseDatabase.getInstance().reference.child("codes")
                    .addValueEventListener(object : ValueEventListener {
                        override fun onCancelled(error: DatabaseError) {
                            TODO("Not yet implemented")
                        }
 
                        override fun onDataChange(snapshot: DataSnapshot) {
                            var check = isValueAvailable(snapshot, code)
 
                            Handler().postDelayed({
                                if (check == true) {
                                    Create.visibility = View.VISIBLE
                                    Join.visibility = View.VISIBLE
                                    GameCode.visibility = View.VISIBLE
                                    textView4.visibility = View.VISIBLE
                                    progressBar.visibility = View.GONE
 
                                } else {
                                    FirebaseDatabase.getInstance().reference.child("codes").push()
                                        .setValue(code)
                                    isValueAvailable(snapshot, code)
                                    checkTemp = false
                                    Handler().postDelayed({
                                        accepted()
                                        errorMsg("Please don't go back")
                                    }, 300)
 
                                }
                            }, 2000)
 
 
                        }
 
                    })
            } else {
                Create.visibility = View.VISIBLE
                Join.visibility = View.VISIBLE
                GameCode.visibility = View.VISIBLE
                textView4.visibility = View.VISIBLE
                progressBar.visibility = View.GONE
                errorMsg("Enter Code Properly")
            }
        }
        Join.setOnClickListener {
            code = "null";
            codeFound = false
            checkTemp = true
            keyValue = "null"
            code = GameCode.text.toString()
            if (code != "null" && code != null && code != "") {
                Create.visibility = View.GONE
                Join.visibility = View.GONE
                GameCode.visibility = View.GONE
                textView4.visibility = View.GONE
                progressBar.visibility = View.VISIBLE
                isCodeMaker = false;
                FirebaseDatabase.getInstance().reference.child("codes")
                    .addValueEventListener(object : ValueEventListener {
                        override fun onCancelled(error: DatabaseError) {
                            TODO("Not yet implemented")
                        }
 
                        override fun onDataChange(snapshot: DataSnapshot) {
                            var data: Boolean = isValueAvailable(snapshot, code)
 
                            Handler().postDelayed({
                                if (data == true) {
                                    codeFound = true
                                    accepted()
                                    Create.visibility = View.VISIBLE
                                    Join.visibility = View.VISIBLE
                                    GameCode.visibility = View.VISIBLE
                                    textView4.visibility = View.VISIBLE
                                    progressBar.visibility = View.GONE
                                } else {
                                    Create.visibility = View.VISIBLE
                                    Join.visibility = View.VISIBLE
                                    GameCode.visibility = View.VISIBLE
                                    textView4.visibility = View.VISIBLE
                                    progressBar.visibility = View.GONE
                                    errorMsg("Invalid Code")
                                }
                            }, 2000)
 
 
                        }
 
 
                    })
 
            } else {
                errorMsg("Enter Code Properly")
            }
        }
 
    }
 
    fun accepted() {
        startActivity(Intent(this, ThirdPage::class.java));
        Create.visibility = View.VISIBLE
        Join.visibility = View.VISIBLE
        GameCode.visibility = View.VISIBLE
        textView4.visibility = View.VISIBLE
        progressBar.visibility = View.GONE
 
    }
 
    fun errorMsg(value: String) {
        Toast.makeText(this, value, Toast.LENGTH_SHORT).show()
    }
 
    fun isValueAvailable(snapshot: DataSnapshot, code: String): Boolean {
        var data = snapshot.children
        data.forEach {
            var value = it.getValue().toString()
            if (value == code) {
                keyValue = it.key.toString()
                return true;
            }
        }
        return false
    }
}

A continuación se muestra el código completo del archivo MainActivity.kt

Kotlin

package com.example.tictactoeapp
 
import android.graphics.Color
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Handler
import android.view.View
import android.widget.Button
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlin.system.exitProcess
 
var playerTurn = true
 
class MainActivity : AppCompatActivity() {
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        button10.setOnClickListener {
            reset()
 
        }
    }
 
    var player1Count = 0
    var player2Count = 0
    fun clickfun(view: View) {
        if (playerTurn) {
            val but = view as Button
            var cellID = 0
            //Toast.makeText(this,but.id.toString() , Toast.LENGTH_SHORT).show();
            when (but.id) {
                R.id.button -> cellID = 1
                R.id.button2 -> cellID = 2
                R.id.button3 -> cellID = 3
                R.id.button4 -> cellID = 4
                R.id.button5 -> cellID = 5
                R.id.button6 -> cellID = 6
                R.id.button7 -> cellID = 7
                R.id.button8 -> cellID = 8
                R.id.button9 -> cellID = 9
 
            }
            playerTurn = false;
            Handler().postDelayed(Runnable { playerTurn = true }, 600)
            playnow(but, cellID)
 
        }
    }
 
    var player1 = ArrayList<Int>()
    var player2 = ArrayList<Int>()
    var emptyCells = ArrayList<Int>()
    var activeUser = 1
    fun playnow(buttonSelected: Button, currCell: Int) {
        val audio = MediaPlayer.create(this, R.raw.poutch)
        if (activeUser == 1) {
            buttonSelected.text = "X"
            buttonSelected.setTextColor(Color.parseColor("#EC0C0C"))
            player1.add(currCell)
            emptyCells.add(currCell)
            audio.start()
            //Handler().postDelayed(Runnable { audio.pause() } , 500)
            buttonSelected.isEnabled = false
            Handler().postDelayed(Runnable { audio.release() }, 200)
            val checkWinner = checkwinner()
            if (checkWinner == 1) {
                Handler().postDelayed(Runnable { reset() }, 2000)
            } else if (singleUser) {
                Handler().postDelayed(Runnable { robot() }, 500)
                //Toast.makeText(this , "Calling Robot" , Toast.LENGTH_SHORT).show()
            } else
                activeUser = 2
 
        } else {
            buttonSelected.text = "O"
            audio.start()
            buttonSelected.setTextColor(Color.parseColor("#D22BB804"))
            //Handler().postDelayed(Runnable { audio.pause() } , 500)
            activeUser = 1
            player2.add(currCell)
            emptyCells.add(currCell)
            Handler().postDelayed(Runnable { audio.release() }, 200)
            buttonSelected.isEnabled = false
            val checkWinner = checkwinner()
            if (checkWinner == 1)
                Handler().postDelayed(Runnable { reset() }, 4000)
        }
 
    }
 
    fun checkwinner(): Int {
        val audio = MediaPlayer.create(this, R.raw.success)
        if ((player1.contains(1) && player1.contains(2) && player1.contains(3)) || (player1.contains(
                1
            ) && player1.contains(4) && player1.contains(7)) ||
            (player1.contains(3) && player1.contains(6) && player1.contains(9)) || (player1.contains(
                7
            ) && player1.contains(8) && player1.contains(9)) ||
            (player1.contains(4) && player1.contains(5) && player1.contains(6)) || (player1.contains(
                1
            ) && player1.contains(5) && player1.contains(9)) ||
            player1.contains(3) && player1.contains(5) && player1.contains(7) || (player1.contains(2) && player1.contains(
                5
            ) && player1.contains(8))
        ) {
            player1Count += 1
            buttonDisable()
            audio.start()
            disableReset()
            Handler().postDelayed(Runnable { audio.release() }, 4000)
            val build = AlertDialog.Builder(this)
            build.setTitle("Game Over")
            build.setMessage("You have won the game.."+"\n\n"+"Do you want to play again")
            build.setPositiveButton("Ok") { dialog, which ->
                reset()
                audio.release()
            }
            build.setNegativeButton("Exit") { dialog, which ->
                audio.release()
                exitProcess(1)
 
            }
            Handler().postDelayed(Runnable { build.show() }, 2000)
            return 1
 
 
        } else if ((player2.contains(1) && player2.contains(2) && player2.contains(3)) || (player2.contains(
                1
            ) && player2.contains(4) && player2.contains(7)) ||
            (player2.contains(3) && player2.contains(6) && player2.contains(9)) || (player2.contains(
                7
            ) && player2.contains(8) && player2.contains(9)) ||
            (player2.contains(4) && player2.contains(5) && player2.contains(6)) || (player2.contains(
                1
            ) && player2.contains(5) && player2.contains(9)) ||
            player2.contains(3) && player2.contains(5) && player2.contains(7) || (player2.contains(2) && player2.contains(
                5
            ) && player2.contains(8))
        ) {
            player2Count += 1
            audio.start()
            buttonDisable()
            disableReset()
            Handler().postDelayed(Runnable { audio.release() }, 4000)
            val build = AlertDialog.Builder(this)
            build.setTitle("Game Over")
            build.setMessage("Opponent have won the game"+"\n\n"+"Do you want to play again")
            build.setPositiveButton("Ok") { dialog, which ->
                reset()
                audio.release()
            }
            build.setNegativeButton("Exit") { dialog, which ->
                audio.release()
                exitProcess(1)
            }
            Handler().postDelayed(Runnable { build.show() }, 2000)
            return 1
        } else if (emptyCells.contains(1) && emptyCells.contains(2) && emptyCells.contains(3) && emptyCells.contains(
                4
            ) && emptyCells.contains(5) && emptyCells.contains(6) && emptyCells.contains(7) &&
            emptyCells.contains(8) && emptyCells.contains(9)
        ) {
 
            val build = AlertDialog.Builder(this)
            build.setTitle("Game Draw")
            build.setMessage("Nobody Wins" + "\n\n" + "Do you want to play again")
            build.setPositiveButton("Ok") { dialog, which ->
                reset()
            }
            build.setNegativeButton("Exit") { dialog, which ->
                exitProcess(1)
            }
            build.show()
            return 1
 
        }
        return 0
    }
 
    fun reset() {
        player1.clear()
        player2.clear()
        emptyCells.clear()
        activeUser = 1;
        for (i in 1..9) {
            var buttonselected: Button?
            buttonselected = when (i) {
                1 -> button
                2 -> button2
                3 -> button3
                4 -> button4
                5 -> button5
                6 -> button6
                7 -> button7
                8 -> button8
                9 -> button9
                else -> {
                    button
                }
            }
            buttonselected.isEnabled = true
            buttonselected.text = ""
            textView.text = "Player1 : $player1Count"
            textView2.text = "Player2 : $player2Count"
        }
    }
 
    fun robot() {
        val rnd = (1..9).random()
        if (emptyCells.contains(rnd))
            robot()
        else {
            val buttonselected: Button?
            buttonselected = when (rnd) {
                1 -> button
                2 -> button2
                3 -> button3
                4 -> button4
                5 -> button5
                6 -> button6
                7 -> button7
                8 -> button8
                9 -> button9
                else -> {
                    button
                }
            }
            emptyCells.add(rnd);
            val audio = MediaPlayer.create(this, R.raw.poutch)
            audio.start()
            Handler().postDelayed(Runnable { audio.release() }, 500)
            buttonselected.text = "O"
            buttonselected.setTextColor(Color.parseColor("#D22BB804"))
            player2.add(rnd)
            buttonselected.isEnabled = false
            var checkWinner = checkwinner()
            if (checkWinner == 1)
                Handler().postDelayed(Runnable { reset() }, 2000)
 
        }
    }
 
    fun buttonDisable() {
        for (i in 1..9) {
            val buttonSelected = when (i) {
                1 -> button
                2 -> button2
                3 -> button3
                4 -> button4
                5 -> button5
                6 -> button6
                7 -> button7
                8 -> button8
                9 -> button9
                else -> {
                    button
                }
 
            }
            if (buttonSelected.isEnabled == true)
                buttonSelected.isEnabled = false
        }
    }
 
    fun disableReset() {
        button10.isEnabled = false
        Handler().postDelayed(Runnable { button10.isEnabled = true }, 2200)
    }
}

Ahora, después de implementar la funcionalidad del modo en línea, hemos terminado con nuestros proyectos de tres en raya.

Producción:

Para obtener el código fuente completo, haga clic aquí .

Publicación traducida automáticamente

Artículo escrito por iamabhishekkalra y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *