Kotlin練習問題2-☆1:ブラックジャックゲームを作ろう

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

Kotlinの初心者向け問題2-☆1:数字当てゲームを作ろう Part2

この問題を解くために必要な知識:
【レベル1の知識】
コメントの書き方、変数と定数、基本データ型、算術演算と論理演算、入力と出力、import文、配列、分岐処理(if、if~else、when)、繰り返し処理(for、while、do~while)、Null安全、スマートキャスト

【レベル2の知識】
関数の定義と呼び出し、関数の戻り値、関数のオーバーロード、ラベルとジャンプ、例外処理クラスの定義と使用インスタンスコンストラクタプロパティクラスの継承クラスの拡張

<<前の問題 問題集Top 次の問題>>

Kotlin練習問題2-☆1:ブラックジャックゲームを作ろう





ブラックジャックは、プレイヤーとディーラーが対戦するカードゲームです。この問題では、Kotlinを使って簡単なブラックジャックゲームを作成します。

プレイヤーは2枚のカードを引き、その合計値をもとにゲームを進めます。

合計値が21に近い方が勝者となりまが、21を超えると「バースト」となり、負けとなります。

今回は1から11までの数字のみを扱います。

この問題の要件

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

  1. ゲームの流れ:
    • プレイヤーとディーラーの双方が2枚のカードを引きます。
    • カードの合計が21を超えない限り、プレイヤーは「ヒット」(もう一枚引く)か「スタンド」(引かない)を選択できます。
    • プレイヤーがスタンドを選ぶと、ディーラーは17以上になるまでカードを引きます。
    • どちらかの合計が21を超えた場合、バーストして敗北となります。
    • プレイヤーとディーラーの手が決まった後、合計値が21に近い方が勝利します。
  2. カードの値:
    • カードの値はランダムに1から11の整数で決定します。
  3. 勝敗の判定:
    • 合計値が21を超えた場合はバーストして負け。
    • 合計値が21に最も近い方が勝者となります。

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

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

ブラックジャックゲームを開始します!
プレイヤーの引いたカード: 7
現在の合計: 7
ヒットしますか?(yes/no): yes
プレイヤーの引いたカード: 10
現在の合計: 17
ヒットしますか?(yes/no): no
ディーラーの引いたカード: 9
ディーラーの合計: 9
ディーラーの引いたカード: 8
ディーラーの合計: 17
プレイヤーの合計: 17
ディーラーの合計: 17
引き分けです。

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

この問題を解くヒント

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

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

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

1.import文
1-1. Randomクラスのインポート

2.関数の定義
2-1. drawCard関数の定義
2-1-1. 1から11の範囲でランダムな整数を返す処理

3.playerTurn関数の定義
3-1. プレイヤーのカード合計を保持する変数totalの初期化
3-2. whileループの開始(プレイヤーが「スタンド」を選択するまで継続)
3-2-1. 新しいカードを引いて合計値に加算
3-2-2. 合計値が21を超えた場合のバースト処理
3-2-3. ユーザー入力を受け付けて「ヒット」か「スタンド」を選択
3-2-4. ループ終了条件の判定(スタンド選択時)
3-3. プレイヤーの最終的な合計値を返す

4.dealerTurn関数の定義
4-1. ディーラーのカード合計を保持する変数totalの初期化
4-2. whileループの開始(ディーラーの合計が17未満の場合)
4-2-1. 新しいカードを引いて合計値に加算
4-2-2. ディーラーがバーストした場合の処理
4-3. ディーラーの最終的な合計値を返す

5.メイン関数の定義
5-1. ゲーム開始メッセージの表示
5-2. プレイヤーのターンを実行し、合計値を取得
5-3. ディーラーのターンを実行し、合計値を取得
5-4. プレイヤーとディーラーの合計値を比較して勝敗を判定

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

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

import kotlin.random.Random

// カードをランダムに生成する関数
fun drawCard(): Int {
    /* 【穴埋め問題1】
    ここに1から11のランダムな整数を返すコードを書いてください。
    */
}

// プレイヤーのターンを処理する関数
fun playerTurn(): Int {
    /* 【穴埋め問題2】
    ここにプレイヤーのカード合計を保持するための変数totalを宣言し、0に初期化するコードを書いてください。
    */

    while (true) {
        /* 【穴埋め問題3】
        ここに新しいカードを引いて合計値に加算するコードを書いてください。
        */

        println("プレイヤーの引いたカード: $card")
        println("現在の合計: $total")

        if (total > 21) {
            println("バースト!プレイヤーの負けです。")
            break
        }

        print("ヒットしますか?(yes/no): ")
        val choice = readLine()

        if (choice == "no") {
            break
        }
    }
    return total
}

// ディーラーのターンを処理する関数
fun dealerTurn(): Int {
    /* 【穴埋め問題4】
    ここにディーラーのカード合計を保持するための変数totalを宣言し、0に初期化するコードを書いてください。
    */

    while (total < 17) {
        /* 【穴埋め問題5】
        ここに新しいカードを引いて合計値に加算するコードを書いてください。
        */

        println("ディーラーの引いたカード: $card")
        println("ディーラーの合計: $total")

        if (total > 21) {
            println("ディーラーがバーストしました。プレイヤーの勝ちです。")
            break
        }
    }
    return total
}

// メイン関数: ゲームの流れを制御する
fun main() {
    println("ブラックジャックゲームを開始します!")

    val playerTotal = playerTurn()
    if (playerTotal <= 21) {
        val dealerTotal = dealerTurn()
        println("プレイヤーの合計: $playerTotal")
        println("ディーラーの合計: $dealerTotal")

        when {
            dealerTotal > 21 || playerTotal > dealerTotal -> println("プレイヤーの勝ちです!")
            playerTotal < dealerTotal -> println("ディーラーの勝ちです。")
            else -> println("引き分けです。")
        }
    }
}

 

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

解答例

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

正解コードの例

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

********************

import kotlin.random.Random

// カードをランダムに生成する関数
// 1から11の範囲でランダムな整数を返します
fun drawCard(): Int {
    return Random.nextInt(1, 12) // 1から11のランダムな数を返す
}

// プレイヤーのターンを処理する関数
// プレイヤーがカードを引くかどうかを選択し、合計値を計算します
fun playerTurn(): Int {
    var total = 0 // プレイヤーのカードの合計を保持する変数

    while (true) { // ユーザーが「スタンド」を選ぶまでループ
        val card = drawCard() // 新しいカードを引く
        total += card // 引いたカードの値を合計に加える
        println("プレイヤーの引いたカード: $card") // 引いたカードの値を表示
        println("現在の合計: $total") // 現在の合計値を表示

        // 合計が21を超えた場合はバースト(負け)とする
        if (total > 21) {
            println("バースト!プレイヤーの負けです。")
            break // バーストしたらループを終了
        }

        // プレイヤーに次の行動を尋ねる
        print("ヒットしますか?(yes/no): ")
        val choice = readLine() // ユーザーの入力を受け取る

        // 「no」を選んだ場合、カードを引くのをやめる
        if (choice == "no") {
            break // ループを終了し、プレイヤーのターンを終了
        }
    }
    return total // プレイヤーの最終的な合計値を返す
}

// ディーラーのターンを処理する関数
// ディーラーは合計が17以上になるまでカードを引き続けます
fun dealerTurn(): Int {
    var total = 0 // ディーラーのカードの合計を保持する変数

    // ディーラーの合計が17未満である限りカードを引き続ける
    while (total < 17) {
        val card = drawCard() // 新しいカードを引く
        total += card // 引いたカードの値を合計に加える
        println("ディーラーの引いたカード: $card") // 引いたカードの値を表示
        println("ディーラーの合計: $total") // ディーラーの現在の合計値を表示

        // 合計が21を超えた場合はバースト(負け)とする
        if (total > 21) {
            println("ディーラーがバーストしました。プレイヤーの勝ちです。")
            break // バーストしたらループを終了
        }
    }
    return total // ディーラーの最終的な合計値を返す
}

// メイン関数: ゲームの流れを制御する
fun main() {
    println("ブラックジャックゲームを開始します!") // ゲームの開始メッセージを表示

    val playerTotal = playerTurn() // プレイヤーのターンを実行し、合計値を取得
    if (playerTotal <= 21) { // プレイヤーがバーストしていない場合にディーラーのターンを実行
        val dealerTotal = dealerTurn() // ディーラーのターンを実行し、合計値を取得
        println("プレイヤーの合計: $playerTotal") // プレイヤーの最終合計値を表示
        println("ディーラーの合計: $dealerTotal") // ディーラーの最終合計値を表示

        // 勝敗の判定
        when {
            dealerTotal > 21 || playerTotal > dealerTotal -> println("プレイヤーの勝ちです!") // ディーラーがバーストするか、プレイヤーの合計が勝っている場合
            playerTotal < dealerTotal -> println("ディーラーの勝ちです。") // プレイヤーの合計が負けている場合
            else -> println("引き分けです。") // 両者の合計が同じ場合
        }
    }
}

********************

正解コードの解説

ブラックジャックゲームのKotlinコードの各部分を初心者向けに説明します。コードの動作を理解し、Kotlinプログラミングの基礎を学びましょう。

ランダム関数のインポート

import kotlin.random.Random

最初に、Kotlin標準ライブラリからRandomクラスをインポートします。これを使ってランダムな数値を生成します。ランダムなカードを引くために重要な部分です。

drawCard関数の定義

fun drawCard(): Int {
    return Random.nextInt(1, 12)
}

drawCard関数は、1から11の範囲でランダムな整数を生成し、それを返します。これは、プレイヤーやディーラーがカードを引く際に使用されます。

playerTurn関数の定義

fun playerTurn(): Int {
    var total = 0
    while (true) {
        val card = drawCard()
        total += card
        println("プレイヤーの引いたカード: $card")
        println("現在の合計: $total")
        if (total > 21) {
            println("バースト!プレイヤーの負けです。")
            break
        }
        print("ヒットしますか?(yes/no): ")
        val choice = readLine()
        if (choice == "no") {
            break
        }
    }
    return total
}

playerTurn関数では、プレイヤーがカードを引いてその合計を計算します。合計が21を超えるとバーストして負けになります。

プレイヤーは「ヒット」してカードを引き続けるか、「スタンド」してターンを終えるかを選択できます。

dealerTurn関数の定義

fun dealerTurn(): Int {
    var total = 0
    while (total < 17) {
        val card = drawCard()
        total += card
        println("ディーラーの引いたカード: $card")
        println("ディーラーの合計: $total")
        if (total > 21) {
            println("ディーラーがバーストしました。プレイヤーの勝ちです。")
            break
        }
    }
    return total
}

dealerTurn関数では、ディーラーがカードを引き、合計が17以上になるまで続けます。

合計が21を超えるとディーラーはバーストし、プレイヤーが勝ちます。

メイン関数

fun main() {
    println("ブラックジャックゲームを開始します!")
    val playerTotal = playerTurn()
    if (playerTotal <= 21) {
        val dealerTotal = dealerTurn()
        println("プレイヤーの合計: $playerTotal")
        println("ディーラーの合計: $dealerTotal")
        when {
            dealerTotal > 21 || playerTotal > dealerTotal -> println("プレイヤーの勝ちです!")
            playerTotal < dealerTotal -> println("ディーラーの勝ちです。")
            else -> println("引き分けです。")
        }
    }
}

メイン関数では、ゲームの全体の流れを制御します。プレイヤーとディーラーのターンが終わった後、勝敗を判定します。

各ターンの結果が表示され、ゲームの進行が明確に分かります。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

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

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






    Kotlin練習問題集へ戻る
    トップページへ戻る