あかんわ

ブログで日誌でも書くようにすれば多少はやる気が出るかと思ったんです

Kotlin on Androidでじゃんけんアプリ

こちらの記事以前の記事を参考に、KotlinでAndroidのじゃんけんアプリを書きました。

IDEAndroid Studio 3.1で、ビルドツールはGradle 4.4を使っています。
動作確認は、API level 23のAndroidエミュレータで実施しました。

目次

Kotlin on Androidでじゃんけんアプリ

手の画像を配置したImageButtonを押すと、相手*1とじゃんけんができるだけのアプリです。

プロジェクトディレクトリの構成
~/app(RockPaperScissorsKotlin)
    |                                    
    |- manifests                               
    |    |- AndroidManifest.xml        // アプリに関する情報を記述するマニフェストファイル
    |                                    
    |- /java                                    
    |    |- /com.b0npu.kotlinrpsgame 
    |         |- MainActivity.kt       // アプリのメインファイル
    |                                    
    |- /res                         
         |- /drawable                  // 画像を配置するディレクトリ
         |    |- rock.png              // じゃんけんのぐーの画像
         |    |- scissor.png           // じゃんけんのちょきの画像
         |    |- paper.png             // じゃんけんのぱーの画像
         |                                    
         |- /layout                    // レイアウトの定義ファイルを配置するディレクトリ
         |    |- activity_main.xml     // 画面レイアウトの定義ファイル
         |                                    
         |- /mipmap                    // アイコン画像を配置するディレクトリ
         |    |- /ic_launcher          // Normalのアイコン画像を配置するディレクトリ
         |    |    |- ic_launcher.png  // アプリのアイコン画像
         |    |                                
         |    |- /ic_launcher_round    // Roundのアイコン画像を配置するディレクトリ
         |                                    
         |- /values                    // 配色や文字の定義ファイルを配置するディレクトリ
              |- string.xml            // 文字の定義ファイル
主なソースコード

Empty Activityテンプレートのactivity_main.xmlWidgetを配置し、MainActivity.ktWidgetリソースIDを取得して操作しています。

activity_main.xml
  • Text
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
    tools:context="com.b0npu.kotlinrpsgame.MainActivity">

    <ImageButton
        android:id="@+id/rockButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="60dp"
        android:minHeight="96dp"
        android:minWidth="96dp"
        android:scaleType="fitXY"
        android:src="@drawable/rock" />

    <ImageButton
        android:id="@+id/scissorButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/rockButton"
        android:layout_centerHorizontal="true"
        android:minHeight="96dp"
        android:minWidth="96dp"
        android:scaleType="fitXY"
        android:src="@drawable/scissor" />

    <ImageButton
        android:id="@+id/paperButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignTop="@+id/scissorButton"
        android:minHeight="96dp"
        android:minWidth="96dp"
        android:scaleType="fitXY"
        android:src="@drawable/paper" />

    <ImageView
        android:id="@+id/playerMove"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/resultText"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:minHeight="96dp"
        android:minWidth="96dp"
        android:src="@drawable/rock" />

    <ImageView
        android:id="@+id/enemyMove"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignStart="@+id/playerMove"
        android:layout_marginTop="40dp"
        android:minHeight="96dp"
        android:minWidth="96dp"
        android:src="@drawable/rock" />

    <TextView
        android:id="@+id/resultText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/enemyMove"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="40dp"
        android:gravity="center"
        android:text="Rock Paper Scissors 1 2 3..."
        android:textSize="24sp" />
</RelativeLayout>
  • Design

f:id:b0npu:20180430231541p:plain

MainActivity.kt
package com.b0npu.kotlinrpsgame

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.TextView
import java.util.Random

class MainActivity : AppCompatActivity() {

    /**
     * プロパティの宣言
     *
     * レイアウトに設置したwidgetのidを格納する変数とじゃんけんで使う定数を宣言する
     * widgetのidを格納する変数はonCreateで初期化するのでlateinitで宣言
     */
    private lateinit var rockButton: ImageButton
    private lateinit var scissorButton: ImageButton
    private lateinit var paperButton: ImageButton
    private lateinit var playerMove: ImageView
    private lateinit var enemyMove: ImageView
    private lateinit var resultText: TextView

    private val handSigns = mapOf(
            "Rock" to R.drawable.rock,
            "Scissor" to R.drawable.scissor,
            "Paper" to R.drawable.paper
    )
    private val handsList = handSigns.keys.toList()

    /**
     * アプリの画面を生成
     *
     * アプリを起動するとonCreateが呼ばれてActivityが初期化され
     * setContentViewでレイアウトビューに表示される
     */
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /**
         * widgetのidを取得
         *
         * レイアウトに設置したwidgetのidを変数に格納する
         */
        rockButton = findViewById(R.id.rockButton)
        scissorButton = findViewById(R.id.scissorButton)
        paperButton = findViewById(R.id.paperButton)
        playerMove = findViewById(R.id.playerMove)
        enemyMove = findViewById(R.id.enemyMove)
        resultText = findViewById(R.id.resultText)

        /**
         * ButtonをClickしてじゃんけん
         *
         * ClickしたButtonのImageをRPSGameメソッドに渡してじゃんけんする
         */
        rockButton.setOnClickListener {
            playRPSGame(handsList.indexOf("Rock"))
        }
        scissorButton.setOnClickListener {
            playRPSGame(handsList.indexOf("Scissor"))
        }
        paperButton.setOnClickListener {
            playRPSGame(handsList.indexOf("Paper"))
        }
    }

    /**
     * じゃんけんのメソッド
     *
     * 引数でplayerのhandSignを受け取ってRandomでenemyのhandSignを決める
     * handSignはRock: 0, Scissor: 1, Paper: 2の数字を割り当てているので
     * ((playerSign - enemySign) + 3 ) % 3の結果で勝敗が決まる
     * 0: Draw, 1: Lose, 2: Win
     */
    private fun playRPSGame(playerSign: Int) {
        val gameResult = mapOf(
                0 to "Draw",
                1 to "Oh Your Lose..",
                2 to "You Win!!"
        )
        val enemySign: Int = Random().nextInt(3)
        val result = (playerSign - enemySign + 3) % 3

        // MapのhandSignsはNullableTypeのInt?を返すので!!演算子でNon-nullTypeのIntに変換
        playerMove.setImageResource(handSigns[handsList[playerSign]]!!)
        enemyMove.setImageResource(handSigns[handsList[enemySign]]!!)
        resultText.text = gameResult[result]
    }
}
res/values/strings.xml
<resources>
    <string name="app_name">KTじゃんけん</string>
</resources>
Run/Debugの実行結果

うまくいけば、じゃんけんで暇が潰せます。

f:id:b0npu:20180504110437g:plain

開発環境

関連記事

参考記事

blog.xsota.com

*1:相手はランダムに手を選びます