【Android Studio】High and Lowゲーム


#はじめに
翔泳社 作ればわかる! Androidプログラミング で学習したことのアウトプットです。
Android Studioを使用して簡単なアプリを作成します。

#High and Lowゲーム
コンピューターのカードに対してプレイヤーのカードが大きい（High）か小さい（Low）かを予想するゲーム。
予想が当たれば「あたり」がカウントされ、外れれば「はずれ」がカウントされる。
「あたり」が５回に達すればプレイヤーの勝ち、「はずれ」が５回に達すればコンピューターの勝ちとなる。

#学んだこと
・TextView, Button, ImageViewの扱い方。
・アプリのライフサイクル（onCreate, onResume）
・Kotlinの基本的な文法。

#プロジェクトの作成
Empty projectを選択。言語はKotlinを使用。
![NewProject.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471428/98f6b772-5330-f98e-4ca9-4ffd630ce8c8.png)

#インターフェイス
TextView, ImageView, Buttonを使用する。
上下左右のマージンは下記画像の通り。
各コンポーネントのidとtextの設定は下表の通り。

![layout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471428/66573589-a2f7-2b32-d9fe-93493496857c.png)

|番号|Palette  |id      |text|
|---|---|---|---|
|①   |TextView |hitText  |@string/hit_text |
|②   |TextView |loseText |@string/lose_text|
|③   |TextView |resultText |（なにも書かない）|
|④   |ImageView |yourCardImage |-|
|⑤   |ImageView |droidCardImage |-|
|⑥   |Button |nextBtn |@string/next_text|
|⑦   |Button |highBtn |@string/high_text|
|⑦   |Button |lowBtn |@string/low_text|

@string/low_textのようなtextの部分は、app->res->values->string.xml にてテキストを設定しておく。

![string.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2471428/afe6b6da-35a9-ea90-0094-bb98c07d44bd.png)

```xml:string.xml
<resources>
    <string name="app_name">HIgh and Low</string>
    <string name="hit_text">あたり</string>
    <string name="lose_text">はずれ</string>
    <string name="high_text">High</string>
    <string name="next_text">カードを引く</string>
    <string name="low_text">low</string>
</resources>
```
また、事前に下記URLにてトランプの画像をダウンロードした。
文字化けしているがページ中央付近のzipファイルをダウンロードし、解凍してからapp->res->drawableに全て格納した。

https://sozai.7gates.net/docs/trump/


#プログラム作成
　"onCreate"メソッド（①）にて初期化処理を行う。"setOnClickListener"メソッド（①-1, ①-2, ①-3） にて各ボタン（idを指定）をクリックしたときの処理を記述する。
　"onResume"メソッド（②）にてアクティビティがフォアグラウンドになったときの処理を行う。アクティビティとはこのアプリのこと、フォアグラウンドとはスマホの画面いっぱいで実行されたときのことを指す。"gameStart"を「true」にしてアクティビティが開始されたフラグを立てる。
　"カードを引く"ボタンが押される（①-3が実行される）と、"drawCard"関数（③）が実行される。同関数ではプレイヤーのカードの種類を決める。1～13までの乱数を発生させ、"showyourCard"関数（④）にてその数に応じた画像を挿入する。
　"HIGH" or "LOW" ののボタンが押される（①-1 or ①-2 が実行される）と、"highAndLow"関数（⑤）が実行される。同関数ではプレイヤーの勝ち負けを判定する。コンピューターのカードを表示した後（⑤-1）、プレイヤーのカードの番号と比較することで、"resultText", "hitText", "loseText" に表示するテキストを決定させる。また、あたりorはずれの回数に応じて、勝敗を判別する（⑤-3）。該当しない場合は"カードを引く"を再度クリックし（①-3が実行される）、次の勝負へ移行させる。


|変数名|役割|
|---|---|
|yourCard|プレイヤーのカードの番号|
|droidCard|コンピューターのカードの番号|
|hitCount|プレイヤーが予想を当てた回数|
|loseCount|プレイヤーが予想を外した回数|
|gameStart|ゲームが開始されたかを判定|
|answered|プレイヤーがhighかlowかの予測を行ったかを判定|


```kotlin:MainActivity.kt
package com.example.highandlow

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private var yourCard = 0
    private var droidCard = 0
    private var hitCount = 0
    private var loseCount = 0
    private var gameStart = false
    private var answered = false

    // ①初期化（アクティビティ生成時に１回だけ呼び出される）
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // ①-1 highボタンが押されたとき
        highBtn.setOnClickListener {
            if (gameStart && !answered){
                highAndLow('h')
                answered = true
            }
        }
        // ①-2 lowボタンが押されたとき
        lowBtn.setOnClickListener {
            if (gameStart && !answered) {
                highAndLow('l')
                answered = true
            }
        }
        // ①-3 nextBtnボタンが押されたとき
        nextBtn.setOnClickListener {
            if (gameStart) {
                drawCard()
                resultText.text = ""
                answered = false
            }
        }
    }

    // ②アクティビティがフォアグラウンドになったときの処理
    override fun onResume() {
        super.onResume()
        hitText.text = getString(R.string.hit_text)
        loseText.text = getString(R.string.lose_text)
        gameStart = true
    }

    // ③プレイヤーのカードを引く
    private fun drawCard(){
        // ③-1 初期化
        yourCardImage.setImageResource(R.drawable.z02)
        droidCardImage.setImageResource((R.drawable.z01))
        // ③-2 乱数発生 -> 自分のカードを表示
        yourCard = (1..13).random()
        showyourCard(yourCard)
    }

    // ⑤勝ち負けを判定
    private fun highAndLow(answer:Char){
        // ⑤-1 コンピューターの値を決める
        droidCard = (1..13).random()
        showdroidCard(droidCard)
        // ⑤-2 当たりはずれを判定
        val balance = yourCard - droidCard
        if (balance == 0){
            resultText.text = "引き分け"
        } else if (balance > 0 && answer == 'h') {
            resultText.text = "当たりです"
            hitCount++
            hitText.text = getString(R.string.hit_text) + hitCount
        } else if (balance < 0 && answer == 'l') {
            resultText.text = "当たりです"
            hitCount++
            hitText.text = getString(R.string.hit_text) + hitCount
        } else {
            resultText.text = "はずれです"
            loseCount++
            loseText.text = getString(R.string.lose_text) + loseCount
        }

        // ⑤-3 通算成績により勝ち負けを判定
        if (hitCount == 5) {
            resultText.text = "あなたの勝ちです"
            gameStart = false
        } else if (loseCount == 5) {
            resultText.text = "あなたの負けです"
            gameStart = false
        } else {
            // do nothing
        }
    }

    // ④プレイヤーのカードを表示
    private fun showyourCard(number:Int){
        when (number) {
            1 -> yourCardImage.setImageResource((R.drawable.d01))
            2 -> yourCardImage.setImageResource((R.drawable.d02))
            3 -> yourCardImage.setImageResource((R.drawable.d03))
            4 -> yourCardImage.setImageResource((R.drawable.d04))
            5 -> yourCardImage.setImageResource((R.drawable.d05))
            6 -> yourCardImage.setImageResource((R.drawable.d06))
            7 -> yourCardImage.setImageResource((R.drawable.d07))
            8 -> yourCardImage.setImageResource((R.drawable.d08))
            9 -> yourCardImage.setImageResource((R.drawable.d09))
            10 -> yourCardImage.setImageResource((R.drawable.d10))
            11 -> yourCardImage.setImageResource((R.drawable.d11))
            12 -> yourCardImage.setImageResource((R.drawable.d12))
            13 -> yourCardImage.setImageResource((R.drawable.d13))
        }
    }
    // ⑥コンピューターのカードを表示
    private fun showdroidCard(number:Int){
        when (number) {
            1 -> droidCardImage.setImageResource((R.drawable.c01))
            2 -> droidCardImage.setImageResource((R.drawable.c02))
            3 -> droidCardImage.setImageResource((R.drawable.c03))
            4 -> droidCardImage.setImageResource((R.drawable.c04))
            5 -> droidCardImage.setImageResource((R.drawable.c05))
            6 -> droidCardImage.setImageResource((R.drawable.c06))
            7 -> droidCardImage.setImageResource((R.drawable.c07))
            8 -> droidCardImage.setImageResource((R.drawable.c08))
            9 -> droidCardImage.setImageResource((R.drawable.c09))
            10 -> droidCardImage.setImageResource((R.drawable.c10))
            11 -> droidCardImage.setImageResource((R.drawable.c11))
            12 -> droidCardImage.setImageResource((R.drawable.c12))
            13 -> droidCardImage.setImageResource((R.drawable.c13))
        }
    }
}
```
#感想
基本的なレイアウトの書き方は全てここに詰まっている。
次はセンサーの値を拾ってきたときの処理方法について勉強したい。