Kotlin on Androidでじゃんけんアプリ
こちらの記事と以前の記事を参考に、KotlinでAndroidのじゃんけんアプリを書きました。
IDEはAndroid 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.xml
にWidgetを配置し、MainActivity.kt
でWidgetのリソース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
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の実行結果
うまくいけば、じゃんけんで暇が潰せます。
開発環境
- OSX 10.13.4 High Sierra
- IDE: Android Studio 3.1
- Android Virtual Device: Android 6.0(Google APIs) API level 23 - Kotlin 1.2.31
- ビルドシステム: Gradle 4.4
関連記事
参考記事
*1:相手はランダムに手を選びます