【Kotlin】確認問題3-☆2:丁半賭博ゲームを作ろう

記事内に商品プロモーションを含む場合があります

この記事の練習問題で使用する知識:
基礎文法(レッスン1)比較演算子と論理演算子if文による分岐処理when文による分岐処理while文による繰り返し処理繰り返しの制御関数の定義と呼出し関数の戻り値

Kotlinのゲームコード一覧はこちら

<<前のページ Kotlin記事一覧 次のページ>>

確認問題:丁半賭博ゲームを作ろう




「丁半賭博ゲーム」を作成しましょう。

このゲームではコンピュータがサイコロを2つ振り、その結果を元に「丁」か「半」を予想します。

予想が当たった場合、賭け金が2倍になって返ってきますが、外れた場合は賭け金を没収されます。

ゲームは以下の手順で進行します:

  1. 初期所持金は1000円です。
  2. プレイヤーは所持金の中から賭け金を決定します。
  3. サイコロの目の合計が偶数なら「丁」、奇数なら「半」です。
  4. 勝敗結果に応じて所持金が増減します。
  5. ゲームを続けるか終了するかを選択できます。

正確に動作するゲームを完成させてください。

この問題の要件

以下の要件に従ってプログラムを作成してください。

  1. プレイヤーの初期所持金を1000円とすること。
  2. 以下の各機能を別々の関数として実装すること:
    • 賭け金を入力する関数 (getBet)
    • 「丁」または「半」を選択する関数 (getChoice)
    • サイコロを2つ振る関数 (rollDice)
    • ゲームを続けるかどうか確認する関数 (askContinue)
  3. サイコロの目をランダムに生成する際、Random.nextInt を使用すること。
  4. 賭け金が所持金を超える場合や不正な入力がある場合、エラーメッセージを表示して再入力させること。
  5. ゲーム終了時に最終的な所持金を表示すること。

ただし、以下のような実行結果となること。

----- ↓出力される結果の例↓ -----

丁半賭博ゲームを始めます!
プレイヤーの所持金: 1000円
いくらかけますか? ⇒ 300
丁か半か?(丁:0,半:1) ⇒ 0
サイコロの目: 4, 2 ⇒ 丁
あなたの勝ち!賞金は300円
続けますか?(はい:0,いいえ:1) ⇒ 0

プレイヤーの所持金: 1300円
いくらかけますか? ⇒ 1500
無効な入力です!所持金以内の正しい金額を入力してください。
いくらかけますか? ⇒ 500
丁か半か?(丁:0,半:1) ⇒ 1
サイコロの目: 1, 6 ⇒ 半
あなたの負け!500円没収!
続けますか?(はい:0,いいえ:1) ⇒ 1

最終所持金は800円でした。
丁半賭博ゲームを終わります。

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1:Randomモジュールをインポート
2:main関数の定義
  □ 「丁半賭博ゲームを始めます!」と出力
  □ 変数moneyに1000を代入
  □ while文を開始(moneyが0より大きい間繰り返す)
  □ □ プレイヤーの所持金を出力(文字列埋め込みを使用)
  □ □ 変数betにgetBet関数の戻り値を代入
  □ □ 変数choiceにgetChoice関数の戻り値を代入
  □ □ 変数dice1に1から6までのランダムな整数を代入
  □ □ 変数dice2に1から6までのランダムな整数を代入
  □ □ 変数sumにdice1とdice2の和を代入
  □ □ if文を使用してsumの偶奇判定を行い、resultに「丁」または「半」を代入
  □ □ サイコロの目と結果を出力
  □ □ if文にてプレイヤーの勝敗を判定
  □ □ □ 勝利時、「あなたの勝ち!」と出力し、moneyにbetを加算
  □ □ □ 敗北時、「あなたの負け!」と出力し、moneyからbetを減算
  □ □ if文にてゲーム継続確認
  □ □ □ askContinue関数の結果がfalseの場合、最終所持金を出力してbreak
  □ □ else文(所持金が0になった場合)
  □ □ □ 「所持金がなくなりました。」と出力
  □ 最終所持金を出力し、ゲーム終了を通知
3:getBet関数の定義
  □ while文を開始(無限ループ)
  □ □ 「いくらかけますか?」と出力
  □ □ ユーザー入力を数値に変換して変数inputに代入
  □ □ if文にてinputの値を確認し、所持金以内の場合inputを返す
  □ □ 「無効な入力です!」と出力
4:getChoice関数の定義
  □ while文を開始(無限ループ)
  □ □ 「丁か半か?」と出力
  □ □ ユーザー入力を数値に変換して変数inputに代入
  □ □ if文にてinputが0または1かを確認し、該当する場合inputを返す
  □ □ 「無効な入力です!」と出力
5:askContinue関数の定義
  □ while文を開始(無限ループ)
  □ □ 「続けますか?」と出力
  □ □ ユーザー入力を数値に変換して変数inputに代入
  □ □ if文にてinputが0の場合trueを返す
  □ □ if文にてinputが1の場合falseを返す
  □ □ 「無効な入力です!」と出力

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

import kotlin.random.Random

fun main() {
    println("丁半賭博ゲームを始めます!")
    var money = 1000

    while (money > 0) {
        println("プレイヤーの所持金: ${money}円")

        /*
        【穴埋め問題1】ここでgetBet関数を呼び出し、所持金moneyを引数として渡して、結果を変数betに代入してください。
        */

        /*
        【穴埋め問題2】ここでgetChoice関数を呼び出し、結果を変数choiceに代入してください。
        */

        val dice1 = Random.nextInt(1, 7)
        val dice2 = Random.nextInt(1, 7)
        val sum = dice1 + dice2
        val result = if (sum % 2 == 0) "丁" else "半"

        println("サイコロの目: $dice1, $dice2 ⇒ $result")

        /*
        【穴埋め問題3】ここでif文を使い、resultとchoiceを比較して勝敗を判定するコードを書いてください。
          勝利時は賞金をmoneyに加算し、敗北時はmoneyから減算してください。
        */

        if (money > 0) {
            /*【穴埋め問題4】
            ここでaskContinue関数を呼び出し、falseの場合breakするコードを書いてください。
            */
        } else {
            println("所持金がなくなりました。ゲームを終了します。")
        }
    }

    println("最終所持金は${money}円でした。丁半賭博ゲームを終わります。")
}

fun getBet(money: Int): Int {
    while (true) {
        print("いくらかけますか? ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input != null && input > 0 && input <= money) {
            return input
        }
        println("無効な入力です!所持金以内の正しい金額を入力してください。")
    }
}

fun getChoice(): Int {
    while (true) {
        print("丁か半か?(丁:0,半:1) ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input == 0 || input == 1) {
            return input
        }
        println("無効な入力です!0か1を入力してください。")
    }
}

/*【穴埋め問題5】
ここでゲーム継続の確認をする関数askContinueを定義し、次の条件を満たすコードを書いてください:
1. 無限ループを開始してください。
2. 「続けますか?(はい:0,いいえ:1)」と出力してください。
3. ユーザーからの入力を数値に変換し、0ならtrue、1ならfalseを返してください。
4. 無効な入力時にはエラーメッセージを出力してください。
*/

この問題の穴埋めコードは以上です。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

丁半賭博ゲームの正解コードと解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

import kotlin.random.Random

fun main() {
    println("丁半賭博ゲームを始めます!")
    var money = 1000

    while (money > 0) {
        println("プレイヤーの所持金: ${money}円")

        val bet = getBet(money)
        val choice = getChoice()

        val dice1 = Random.nextInt(1, 7)
        val dice2 = Random.nextInt(1, 7)
        val sum = dice1 + dice2
        val result = if (sum % 2 == 0) "丁" else "半"

        println("サイコロの目: $dice1, $dice2 ⇒ $result")

        if ((result == "丁" && choice == 0) || (result == "半" && choice == 1)) {
            println("あなたの勝ち!賞金は${bet}円")
            money += bet
        } else {
            println("あなたの負け!${bet}円没収!")
            money -= bet
        }

        if (money > 0) {
            if (!askContinue()) {
                println("最終所持金は${money}円でした。")
                break
            }
        } else {
            println("所持金がなくなりました。ゲームを終了します。")
        }
    }

    println("最終所持金は${money}円でした。丁半賭博ゲームを終わります。")
}

fun getBet(money: Int): Int {
    while (true) {
        print("いくらかけますか? ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input != null && input > 0 && input <= money) {
            return input
        }
        println("無効な入力です!所持金以内の正しい金額を入力してください。")
    }
}

fun getChoice(): Int {
    while (true) {
        print("丁か半か?(丁:0,半:1) ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input == 0 || input == 1) {
            return input
        }
        println("無効な入力です!0か1を入力してください。")
    }
}

fun askContinue(): Boolean {
    while (true) {
        print("続けますか?(はい:0,いいえ:1) ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input == 0) return true
        if (input == 1) return false
        println("無効な入力です!0か1を入力してください。")
    }
}

正解コードの解説

この解説では「丁半賭博ゲーム」のKotlinコードをブロックごとに分け、それぞれの文法や役割を説明します。

プログラムの動作を理解しながらKotlinの基礎を学んでいきましょう。

インポートとメイン関数の開始

import kotlin.random.Random

fun main() {
    println("丁半賭博ゲームを始めます!")
    var money = 1000
  • import kotlin.random.Random: ランダムな数値を生成するためにKotlin標準ライブラリのRandomクラスをインポートしています。サイコロの目をランダムに決定するのに使います。
  • fun main(): Kotlinプログラムのエントリーポイント(開始地点)です。
  • println: メッセージをコンソールに表示します。ここでは、ゲーム開始の挨拶を表示しています。
  • var money = 1000: プレイヤーの所持金を表す変数を定義しています。最初の所持金は1000円です。

賭け金を入力する関数

fun getBet(money: Int): Int {
    while (true) {
        print("いくらかけますか? ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input != null && input > 0 && input <= money) {
            return input
        }
        println("無効な入力です!所持金以内の正しい金額を入力してください。")
    }
}
  • fun getBet: 賭け金を入力する関数を定義しています。この関数はユーザーから正しい賭け金を受け取る役割を持ちます。
  • while (true): 無限ループを開始します。ユーザーが正しい賭け金を入力するまで繰り返します。
  • readLine()?.toIntOrNull(): 入力された値を整数に変換します。不正な値の場合はnullを返します。
  • if (input != null && input > 0 && input <= money): 入力値が正しい範囲内であるかを確認します。

「丁」または「半」を選択する関数

fun getChoice(): Int {
    while (true) {
        print("丁か半か?(丁:0,半:1) ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input == 0 || input == 1) {
            return input
        }
        println("無効な入力です!0か1を入力してください。")
    }
}
  • fun getChoice: プレイヤーが「丁」または「半」を選択するための関数です。
  • input == 0 || input == 1: 入力値が「0」または「1」の場合のみ受け付けます。

サイコロを振る関数

fun rollDice(): Pair<Int, Int> {
    val dice1 = Random.nextInt(1, 7)
    val dice2 = Random.nextInt(1, 7)
    return Pair(dice1, dice2)
}
  • Random.nextInt(1, 7): サイコロの目をランダムに生成します。ここでは1~6の間でランダムな整数を作成しています。
  • Pair: 2つのサイコロの結果を1つのペアとして返します。

ゲームを続けるか確認する関数

fun askContinue(): Boolean {
    while (true) {
        print("続けますか?(はい:0,いいえ:1) ⇒ ")
        val input = readLine()?.toIntOrNull()
        if (input == 0) return true
        if (input == 1) return false
        println("無効な入力です!0か1を入力してください。")
    }
}
  • fun askContinue: ゲームを続行するか終了するかを確認します。
  • input == 0: 「はい」を選択した場合、ゲームを続行します。
  • input == 1: 「いいえ」を選択した場合、ゲームを終了します。

メインゲームロジック

while (money > 0) {
    println("プレイヤーの所持金: ${money}円")
    val bet = getBet(money)
    val choice = getChoice()
    val (dice1, dice2) = rollDice()
    val sum = dice1 + dice2
    val result = if (sum % 2 == 0) "丁" else "半"

    println("サイコロの目: $dice1, $dice2 ⇒ $result")

    if ((result == "丁" && choice == 0) || (result == "半" && choice == 1)) {
        println("あなたの勝ち!賞金は${bet}円")
        money += bet
    } else {
        println("あなたの負け!${bet}円没収!")
        money -= bet
    }

    if (money > 0 && !askContinue()) {
        println("最終所持金は${money}円でした。")
        break
    }
}
println("最終所持金は${money}円でした。丁半賭博ゲームを終わります。")
  • while (money > 0): プレイヤーの所持金が0になるまでゲームを繰り返します。
  • val (dice1, dice2) = rollDice(): サイコロの目を取得します。
  • if ((result == "丁" && choice == 0) || (result == "半" && choice == 1)): プレイヤーの予想が当たったかを判定します。
  • money += bet: 勝った場合は賭け金を増やします。
  • money -= bet: 負けた場合は賭け金を減らします。

まとめ

この「丁半賭博ゲーム」は、Kotlinの基本的な文法(関数、条件分岐、ループ、入力処理、ランダム数生成)を総合的に活用したプログラムです。

初心者でも理解しやすく、ゲームを通してプログラミングの楽しさを体験できます。

ぜひコードを実際に動かしてみて、改良やアレンジを試してみてください!

Kotlinのゲームコード一覧はこちら

<<前のページ Kotlin記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Kotlinテキスト&問題集へ戻る
    トップページへ戻る