【kotlin/Android】三目並べを作ってみよう！

学生時代では、Java + eclipse環境で、RPGのAndroidアプリを作成した経験がありますが、
最近のAndroidプログラミング言語はKorlin、開発環境はAndroid Studioが主流になっているみたいです。
スマホアプリ作りたくなったので、言語と環境を覚えるために、Kotlinでサンプルの三目並べゲームを作ってみました。

##activity_main.xml
アプリの画面のレイアウトを記載する場所です。
![activity_main.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561175/63d67520-de7b-c478-bfea-42c71d24b13a.jpeg)

赤いエリア　　　　→　palette。部品を選択するところです。
水色のエリア　　　→  Component Tree。画面に設置した部品の関係ツリーを表示します。
緑のエリア　　　　→　スマホの画面。ここに部品を配置します。
オレンジのエリア　→　緑色のエリアで選択している部品のプロパティが表示されます。

今回はTable LayoutにTable Rowを配置してその中にbuttonを配置して、三目並べの形を作りました！
それで、それぞれのbuttonに、onClickイベントがあるので、ここで呼び出すfunction名を書き込むと、
MainActivity.kt側のfunctionを呼び出すことができるようになります。

![onclick.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561175/f76bd654-b4e5-b3fe-aab2-6e5879d2658d.jpeg)

コードはこちら

```xml
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/whiteColorBackground"
    android:gravity="center"
    tools:context=".MainActivity">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:layout_marginTop="3px">

        <Button
            android:id="@+id/bu1"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />

        <Button
            android:id="@+id/bu2"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />

        <Button
            android:id="@+id/bu3"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />
    </TableRow>


    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:layout_marginTop="3px">

        <Button
            android:id="@+id/bu4"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />

        <Button
            android:id="@+id/bu5"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />

        <Button
            android:id="@+id/bu6"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:layout_marginTop="3px">

        <Button
            android:id="@+id/bu7"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />

        <Button
            android:id="@+id/bu8"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />

        <Button
            android:id="@+id/bu9"
            android:layout_width="40pt"
            android:layout_height="40pt"
            android:layout_marginLeft="3pt"
            android:background="@color/whiteBu"
            android:onClick="buClick" />
    </TableRow>

</TableLayout>
```

##colors.xml
先程の、activity_main.xmlでbackgroundに色を指定しているのですが、その色は直接色コードを指定する他に、
名前をつけて定義することもできます。
こちらのほうが変更するときに後々楽なので定義します。
![backglound.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561175/1d11a6ca-d2da-ee6f-78db-c45c30e47a72.png)


```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="whiteColorBackground">#D3D3D3</color>
    <color name="whiteBu">#F9F9F9</color>
    <color name="blue">#FF33B5E5</color>
    <color name="darkGreen">#FF669900</color>
</resources>
```

##MainActivity.kt
実行コードです。

ボタンを押されたとき、buClickイベントが実行されてゲームが進みます。

```kotlin
package com.example.tictactoeapp

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.Toast
import kotlinx.android.synthetic.main.activity_main.*
import java.util.Random

class MainActivity : AppCompatActivity() {

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

    fun buClick(view: View) {
        val buSelected =  view as Button

        var cellId = 0
        when(buSelected.id){
            R.id.bu1 -> cellId = 1
            R.id.bu2 -> cellId = 2
            R.id.bu3 -> cellId = 3
            R.id.bu4 -> cellId = 4
            R.id.bu5 -> cellId = 5
            R.id.bu6 -> cellId = 6
            R.id.bu7 -> cellId = 7
            R.id.bu8 -> cellId = 8
            R.id.bu9 -> cellId = 9
        }
        //Log.d("buClick", buSelected.id.toString())
        //Log.d("buClick: cellId", cellId.toString())

        playGame(cellId, buSelected)
    }

    var activityPlayer = 1

    var player1 = ArrayList<Int>()
    var player2 = ArrayList<Int>()


    fun playGame(cellId:Int, buSelected:Button){

        if(activityPlayer == 1){
            buSelected.text = "X"
            buSelected.setBackgroundResource(R.color.blue)
            player1.add(cellId)
            activityPlayer = 2
            autoPlay()
        }else{
            buSelected.text = "O"
            buSelected.setBackgroundResource(R.color.darkGreen)
            player2.add(cellId)
            activityPlayer = 1
        }
        buSelected.isEnabled = false

        checkWinner()

    }

    fun checkWinner(){
        var winner = -1

        //row1
        if(player1.contains(1) && player1.contains(2) && player1.contains(3)) {
            winner = 1
        }

        if(player2.contains(1) && player2.contains(2) && player2.contains(3)){
            winner = 2
        }

        //row2
        if(player1.contains(4) && player1.contains(5) && player1.contains(6)) {
            winner = 1
        }

        if(player2.contains(4) && player2.contains(5) && player2.contains(6)){
            winner = 2
        }

        //row3
        if(player1.contains(7) && player1.contains(8) && player1.contains(9)) {
            winner = 1
        }

        if(player2.contains(7) && player2.contains(8) && player2.contains(9)){
            winner = 2
        }

        //col1
        if(player1.contains(1) && player1.contains(4) && player1.contains(7)) {
            winner = 1
        }

        if(player2.contains(1) && player2.contains(4) && player2.contains(7)){
            winner = 2
        }

        //col2
        if(player1.contains(2) && player1.contains(5) && player1.contains(8)) {
            winner = 1
        }

        if(player2.contains(2) && player2.contains(5) && player2.contains(8)){
            winner = 2
        }

        //col3
        if(player1.contains(3) && player1.contains(6) && player1.contains(9)) {
            winner = 1
        }

        if(player2.contains(3) && player2.contains(6) && player2.contains(9)){
            winner = 2
        }

        //cross1
        if(player1.contains(1) && player1.contains(5) && player1.contains(9)) {
            winner = 1
        }

        if(player2.contains(1) && player2.contains(5) && player2.contains(9)){
            winner = 2
        }

        //cross2
        if(player1.contains(3) && player1.contains(5) && player1.contains(7)) {
            winner = 1
        }

        if(player2.contains(3) && player2.contains(5) && player2.contains(7)){
            winner = 2
        }


        if(winner == 1){
            player1WinnerCount += 1
            Toast.makeText(this, "Player 1 win the game", Toast.LENGTH_LONG).show()
            restartGame()
        }else if(winner == 2){
            player2WinnerCount += 1
            Toast.makeText(this, "Player 2 win the game", Toast.LENGTH_LONG).show()
            restartGame()

        }
    }

    fun autoPlay(){
        var emptyCells = ArrayList<Int>()

        for(cellId in 1..9){
            if(!(player1.contains(cellId) || player2.contains(cellId))){
                emptyCells.add(cellId)
            }
        }

        if(emptyCells.size == 0){
            restartGame()
        }

        val r = Random()
        val randIndex = r.nextInt(emptyCells.size)
        val cellId = emptyCells[randIndex]

        var buSelected:Button?
        buSelected = when(cellId){
            1 -> bu1
            2 -> bu2
            3 -> bu3
            4 -> bu4
            5 -> bu5
            6 -> bu6
            7 -> bu7
            8 -> bu8
            9 -> bu9
            else -> {bu1}
        }

        playGame(cellId, buSelected)
    }

    var player1WinnerCount = 0
    var player2WinnerCount = 0

    fun restartGame(){
        activityPlayer = 1
        player1.clear()
        player2.clear()

        for(index in 1..9){
            val buSelected:Button
            buSelected = when(index){
                1 -> bu1
                2 -> bu2
                3 -> bu3
                4 -> bu4
                5 -> bu5
                6 -> bu6
                7 -> bu7
                8 -> bu8
                9 -> bu9
                else -> {bu1}
            }
            buSelected!!.text = ""
            buSelected!!.setBackgroundResource(R.color.whiteBu)
            buSelected!!.isEnabled = true
        }

        Toast.makeText(this, "Player1: $player1WinnerCount ,Player2: $player2WinnerCount", Toast.LENGTH_LONG).show()
    }
}
```

##実行結果
エミュレーターで実行するとこんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561175/14f98a8c-4547-e959-5a97-82590ca8872d.png)


##感想
AndroidStudioが登場したことで、Java+eclipseの時代よりも、簡単に開発環境の構築と
コーディングできるようになっていると思います。
kotlinについてはJavaのライブラリも最新のkotlinのライブラリも使えつつ、現代的なコードなので生産性の向上が期待できると思います。
もっと多くのアプリを作ってみたいところです。