【Android Studio】Kotlinでつくるクイズアプリ講座 第5回「正解・不正解の判定」
前回クイズを表示することができたので、今回はクイズの正解・不正解を判定してみましょう。
正解・不正解の判定は解答ボタンが押されたときに呼ばれる checkAnswer 関数を使います。
ダイアログを使ってクイズの答えも表示してみましょう。
正解・不正解を判定する
1. クイズの出題数を設定する
まずはクイズを何問出題するかを決めます。
3~5行目を追加してください。
ここではクイズを5問出題するように設定しました。
出題したクイズは quizData リストから削除するので、出題数はリストの要素数を超えない範囲に設定してください。
2. checkAnswer 関数
checkAnswer関数にコードを追加します。
必要な import
ダイアログを使うために以下のimportが追加されます。
import com.google.android.material.dialog.MaterialAlertDialogBuilder
3・4行目:どの解答ボタンが押されたかを取得
val answerBtn: Button = findViewById(view.id)
val btnText = answerBtn.text.toString()
押された解答ボタンを見つけて、そのボタンのテキストを取得しています。
8~13行目:正解・不正解の判定
8行目では解答ボタンのテキストと rightAnswer が一致するかで正解・不正解を判定しています。
if (btnText == rightAnswer) {
alertTitle = "正解!"
rightAnswerCount++
} else {
alertTitle = "不正解…"
}
正解の場合は、このあと作成するダイアログのタイトルを「正解!」として、正解数をカウントする rightAnswerCount に1を加算します。
不正解の場合は、ダイアログのタイトルを「不正解…」とするだけです。
16行目〜:ダイアログを表示する
16行目からはダイアログを作成しています。
まずはタイトル・メッセージ・OKボタンを追加します。
19~21行目は OK ボタンが押された時に checkQuizCount 関数を呼び出す設定をしています。
22行目の setCancelable はダイアログの外側をタップしたときにダイアログを閉じるかどうかを指定しています。
false にしているので OK ボタンを押さないとダイアログを閉じることはできません。
ダイアログの表示には DialogFragment を使うべきですが、このクイズでは画面を固定すると想定していること、より簡単に実装することを理由にここでは使用していません。講座の完全版では DialogFragment を使う方法を紹介しています。
3. checkQuizCount 関数
ダイアログの OK ボタンが押されたら呼ばれる checkQuizCount 関数に以下のコードを書きます。
最初に設定した出題数 QUIZ_COUNT と quizCount が同じになったら結果画面に移動します。
QUIZ_COUNT に達していない場合は quizCount に1を足して、再び showNextQuiz メソッドを呼ぶことで、クイズを続けて出題できるようになります。
4. countLabel の更新
最後に「Q1」と表示している countLabel を更新しましょう。
showNextQuiz 関数に3行目を追加します。
クイズ画面を作成した時に strings.xml に
<string name="count_label">Q%d</string>
と書きました。
getString メソッドを使って strings.xml に定義したこの文字列を取得して、第2引数に %d の部分に入れる数値を指定しています。
5. アプリを実行する
エミュレータでアプリを実行してみましょう。
正解・不正解の判定が正しく行われ、クイズが連続して出題されるでしょうか?
もし上手く動かない場合は下にサンプルコードを貼ってあるのでご確認ください。
次に行うこと
これでメインのクイズ機能は完成です!
次回からは結果画面を作成していきましょう。
ここまでのコード
- MainActivity.kt
-
package com.example.quizapp import android.os.Bundle import android.view.View import android.widget.Button import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.core.view.ViewCompat import androidx.core.view.WindowInsetsCompat import com.example.quizapp.databinding.ActivityMainBinding import com.google.android.material.dialog.MaterialAlertDialogBuilder class MainActivity : AppCompatActivity() { companion object { const val QUIZ_COUNT = 5 } private lateinit var binding: ActivityMainBinding private var rightAnswer: String? = null private var rightAnswerCount = 0 private var quizCount = 1 private val quizData = mutableListOf( mutableListOf("北海道", "札幌市", "長崎市", "福島市", "前橋市"), mutableListOf("青森県", "青森市", "広島市", "甲府市", "岡山市"), mutableListOf("岩手県", "盛岡市", "大分市", "秋田市", "福岡市"), mutableListOf("宮城県", "仙台市", "水戸市", "岐阜市", "福井市"), mutableListOf("秋田県", "秋田市", "横浜市", "鳥取市", "仙台市"), mutableListOf("山形県", "山形市", "青森市", "山口市", "奈良市"), mutableListOf("福島県", "福島市", "盛岡市", "新宿区", "京都市"), mutableListOf("茨城県", "水戸市", "金沢市", "名古屋市", "奈良市"), mutableListOf("栃木県", "宇都宮市", "札幌市", "岡山市", "奈良市"), mutableListOf("群馬県", "前橋市", "福岡市", "松江市", "福井市") ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } binding.answerBtn1.setOnClickListener { checkAnswer(it) } binding.answerBtn2.setOnClickListener { checkAnswer(it) } binding.answerBtn3.setOnClickListener { checkAnswer(it) } binding.answerBtn4.setOnClickListener { checkAnswer(it) } quizData.shuffle() showNextQuiz() } // クイズを出題する private fun showNextQuiz() { // カウントラベルの更新 binding.countLabel.text = getString(R.string.count_label, quizCount) // クイズを1問取り出す val quiz = quizData[0] // 問題をセット binding.questionLabel.text = quiz[0] // 正解をセット rightAnswer = quiz[1] // 都道府県名を削除 quiz.removeAt(0) // 正解と選択肢3つをシャッフル quiz.shuffle() // 正解と選択肢をセット binding.answerBtn1.text = quiz[0] binding.answerBtn2.text = quiz[1] binding.answerBtn3.text = quiz[2] binding.answerBtn4.text = quiz[3] // 出題したクイズを削除する quizData.removeAt(0) } // 解答ボタンが押されたら呼ばれる private fun checkAnswer(view: View) { // どの解答ボタンが押されたか val answerBtn: Button = findViewById(view.id) val btnText = answerBtn.text.toString() // ダイアログのタイトルを作成 val alertTitle: String if (btnText == rightAnswer) { alertTitle = "正解!" rightAnswerCount++ } else { alertTitle = "不正解..." } // ダイアログを作成 MaterialAlertDialogBuilder(this) .setTitle(alertTitle) .setMessage("答え : $rightAnswer") .setPositiveButton("OK") { dialogInterface, i -> checkQuizCount() } .setCancelable(false) .show() } // 出題数をチェックする private fun checkQuizCount() { if (quizCount == QUIZ_COUNT) { // 結果画面を表示 } else { quizCount++ showNextQuiz() } } }
2. checkAnswer 関数
https://codeforfun.jp/android-studio-quiz-game-with-kotlin-5/
18行目のコードについての質問です
コードでは「$rightAnswer」になっていますが、
エラーになります。これは「rightAnswer」ではないでしょうか?
知識不足でしたらすみません。お忙しいこととは思いますが、
ご確認よろしくお願いいたします
当サイトを見つけていただきありがとうございます!
ご質問の箇所ですが、以下の部分でしょうか?
.setMessage("答え : $rightAnswer")
ここは変数 rightAnswer を表示するコードなので「$rightAnswer」が正しいコードになります。
.setMessage("答え : rightAnswer")
と書くと、ただの文字列になってしまいます。
他の箇所が原因でエラーになっているかと思いますので、再度ご確認頂ければと思います。
違う箇所でエラーになっていたようで、無事修正することができました。返信いただきましてありがとうございました。
無事解決したとのこと良かったです!
$rightAnswerについて質問させていただいたものです。
$がどういう意味なのかを調べようと「kotolin $ 使い方」「kotolin $ 意味」などで検索してみたのですがページがうまく探せませんでした。
何かヒントになるようなことでも構いません、ご教授いただけますと幸いです。
よろしくお願いいたします。
Kotlin の公式ドキュメントの該当箇所のリンクを貼っておきます。
英語ページですが日本語翻訳しても違和感なくお読みいただけると思いますので、参考にしてみてください。
https://kotlinlang.org/docs/strings.html#string-templates
いつもお返事ありがとうございます😭
こんなシンプルな記述で文字列に変数を埋め込めるんですね!
まだまだ知らないことだらけですが、
少しずつ学習を進めていきたいと思います。
今後もよろしくお願いいたします。
参考になったようで良かったです!
Kotlin はシンプルに書けて良いですよね。今後もぜひ当サイトをお役立ていただければ嬉しいです🙂