【Kotlin】レッスン4-☆1:ナインゲームを作ろう|配列と乱数を使った実践ゲーム

一つ前のページではコレクションとジェネリクスの組み合わせについて学習しました。
今回は ナインゲーム を作成していきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:コレクション編
・Lesson4-1:配列を理解しよう
・Lesson4-2:Listを理解しよう
・Lesson4-3:Setを理解しよう
・Lesson4-4:Mapを理解しよう
・Lesson4-5:コレクションを使いこなそう
・Lesson4-6:コレクションとジェネリクスを組み合わせよう
・確認問題4-☆1:ナインゲームを作ろう ◁今回はココ
・確認問題4-☆2:アラビア数字をローマ数字に変換しよう
・確認問題4-☆3:宝探しゲームを作ろう
Lesson5:オブジェクト指向編
Kotlinのゲームコード一覧はこちら
ナインゲームを実装しよう|配列・乱数・スコア管理を学ぶ

ナインゲームを作成しましょう。
ナインゲームはプレイヤーとコンピュータが対戦するシンプルなゲームです。
この問題の要件
以下の要件に従ってコードを完成させてください。
- プレイヤーとコンピュータは1から9までの9枚の牌を持っています。
- プレイヤーとコンピュータはそれぞれのターンで牌を一枚選びます。
- 牌の数字を比較し、大きい数字を出した方にその数字と同じ数の得点が入ります。
- 一度出した牌は再び使用することはできません。全ての牌が使われるまでゲームは続きます。
- 最終的に得点が多い方が勝者となります。
- プレイヤーの牌はユーザーが入力し、コンピュータの牌はランダムに選ばれます。
- ゲームの進行に合わせて、各ターンの状況と結果を表示してください。
ただし、以下のような実行結果となること。
ナインゲームを開始します! プレイヤーの持ち牌 ⇒「1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9」 コンピュータの持ち牌⇒「1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9」 【第1回戦】 プレイヤーの得点 : 0点 コンピュータの得点: 0点 持ち牌の中から出す牌を選択してください > 9 コンピュータの打牌:5 プレイヤーの打牌:9 > 5:コンピュータの打牌 プレイヤーは9点獲得 プレイヤーの持ち牌 ⇒「1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,-」 コンピュータの持ち牌⇒「1 ,2 ,3 ,4 ,- ,6 ,7 ,8 ,9」 ...
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:
main関数の定義とゲーム開始メッセージの出力
□playerTilesをinitializeTiles関数で初期化
□computerTilesをinitializeTiles関数で初期化
□playerScoreを0で初期化
□computerScoreを0で初期化
□forループで1から9まで繰り返し処理
□ □ ラウンド情報を出力
□ □displayScores関数でプレイヤーとコンピュータのスコアを表示
□ □displayTiles関数でプレイヤーの持ち牌を表示
□ □displayTiles関数でコンピュータの持ち牌を表示
□ □getPlayerTile関数でプレイヤーの打牌を取得
□ □getComputerTile関数でコンピュータの打牌を取得
□ □ 勝敗判定のためにjudgeRound関数を呼び出し、結果をroundResultに代入
□ □ 結果に基づきwhen構文でスコア加算または引き分けを表示
□ □ ラウンドの詳細結果を出力
□displayFinalResult関数で最終スコアとゲーム結果を表示
2:initializeTiles関数の定義
□ 空のMutableMapを生成
□forループで1から9のキーにtrueを設定
□ 生成したマップを返す
3:displayScores関数の定義
□ プレイヤーとコンピュータのスコアを出力
4:displayTiles関数の定義
□tilesマップの各キーと値をループ処理
□ 未使用牌は番号を表示し、使用済み牌は「-」を表示
5:getPlayerTile関数の定義
□whileループでプレイヤーからの入力を繰り返し取得
□if文で選択した牌が未使用か判定
□ □ 未使用なら牌を使用済みに設定し返す
□ □ 使用済みならエラーメッセージを出力し再入力を促す
6:getComputerTile関数の定義
□ 未使用牌をランダムに選択
□ 選択した牌を使用済みに設定し返す
7:judgeRound関数の定義
□when構文で打牌の大小を比較し勝敗を返す
8:displayFinalResult関数の定義
□ ゲーム終了メッセージを出力
□ プレイヤーとコンピュータの最終スコアを出力
□ スコアに基づき最終結果を判定し出力
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
import kotlin.random.Random fun main() { println("ナインゲームを開始します!") // プレイヤーとコンピュータの持ち牌を初期化 val playerTiles = initializeTiles() val computerTiles = initializeTiles() // スコア初期化 var playerScore = 0 var computerScore = 0 // 9回戦を行う for (round in 1..9) { println("\n【第${round}回戦】") displayScores(playerScore, computerScore) // プレイヤーとコンピュータの持ち牌を表示 displayTiles("プレイヤー", playerTiles) displayTiles("コンピュータ", computerTiles) // プレイヤーとコンピュータの打牌 val playerTile = getPlayerTile(playerTiles) val computerTile = getComputerTile(computerTiles) // 勝敗判定 val roundResult = judgeRound(playerTile, computerTile) println("プレイヤーの打牌:$playerTile > $computerTile:コンピュータの打牌") when (roundResult) { "player" -> { println("プレイヤーは${playerTile}点獲得") playerScore += playerTile } "computer" -> { println("コンピュータは${computerTile}点獲得") computerScore += computerTile } else -> println("引き分けです") } } // ゲーム終了後の結果表示 displayFinalResult(playerScore, computerScore) } /* 【穴埋め問題1】 ここにinitializeTiles関数を作成し、1から9までのキーをtrueに設定したMutableMapを返すコードを書いてください。 */ /* 【穴埋め問題2】 ここにdisplayScores関数を作成し、プレイヤーとコンピュータのスコアをそれぞれ出力するコードを書いてください。 */ /* 【穴埋め問題3】 ここにdisplayTiles関数を作成し、指定された持ち牌の内容を表示するコードを書いてください。 */ /* 【穴埋め問題4】 ここにgetPlayerTile関数を作成し、プレイヤーから未使用の打牌を選択させるコードを書いてください。 */ /* 【穴埋め問題5】 ここにgetComputerTile関数を作成し、コンピュータの未使用の打牌をランダムに選択するコードを書いてください。 */ /* 【穴埋め問題6】 ここにjudgeRound関数を作成し、プレイヤーとコンピュータの打牌を比較して勝敗を判定するコードを書いてください。 */ /* 【穴埋め問題7】 ここにdisplayFinalResult関数を作成し、最終スコアとゲームの結果を出力するコードを書いてください。 */
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
import kotlin.random.Random fun main() { println("ナインゲームを開始します!") // プレイヤーとコンピュータの持ち牌を初期化 val playerTiles = initializeTiles() val computerTiles = initializeTiles() // スコア初期化 var playerScore = 0 var computerScore = 0 // 9回戦を行う for (round in 1..9) { println("\n【第${round}回戦】") displayScores(playerScore, computerScore) // プレイヤーとコンピュータの持ち牌を表示 displayTiles("プレイヤー", playerTiles) displayTiles("コンピュータ", computerTiles) // プレイヤーとコンピュータの打牌 val playerTile = getPlayerTile(playerTiles) val computerTile = getComputerTile(computerTiles) // 勝敗判定 val roundResult = judgeRound(playerTile, computerTile) println("プレイヤーの打牌:$playerTile > $computerTile:コンピュータの打牌") when (roundResult) { "player" -> { println("プレイヤーは${playerTile}点獲得") playerScore += playerTile } "computer" -> { println("コンピュータは${computerTile}点獲得") computerScore += computerTile } else -> println("引き分けです") } } // ゲーム終了後の結果表示 displayFinalResult(playerScore, computerScore) } // 関数:持ち牌を初期化 fun initializeTiles(): MutableMap<Int, Boolean> { return mutableMapOf<Int, Boolean>().apply { for (i in 1..9) { this[i] = true } } } // 関数:得点を表示 fun displayScores(playerScore: Int, computerScore: Int) { println("プレイヤーの得点 : ${playerScore}点") println("コンピュータの得点: ${computerScore}点") } // 関数:持ち牌を表示 fun displayTiles(playerType: String, tiles: Map<Int, Boolean>) { print("$playerType の持ち牌⇒「") tiles.forEach { (key, value) -> if (value) print("$key ,") else print("- ,") } println("」") } // 関数:プレイヤーの打牌を取得 fun getPlayerTile(tiles: MutableMap<Int, Boolean>): Int { var playerTile: Int while (true) { print("持ち牌の中から出す牌を選択してください > ") playerTile = readLine()!!.toInt() if (tiles[playerTile] == true) { tiles[playerTile] = false // 使用済みに設定 return playerTile } else { println("その牌は既に使われています。別の牌を選んでください。") } } } // 関数:コンピュータの打牌を取得 fun getComputerTile(tiles: MutableMap<Int, Boolean>): Int { val computerTile = tiles.filter { it.value }.keys.random() tiles[computerTile] = false return computerTile } // 関数:勝敗判定 fun judgeRound(playerTile: Int, computerTile: Int): String { return when { playerTile > computerTile -> "player" computerTile > playerTile -> "computer" else -> "draw" } } // 関数:最終結果を表示 fun displayFinalResult(playerScore: Int, computerScore: Int) { println("\nゲーム終了!") println("最終得点:") println("プレイヤーの得点 : ${playerScore}点") println("コンピュータの得点: ${computerScore}点") when { playerScore > computerScore -> println("プレイヤーの勝利です!") computerScore > playerScore -> println("コンピュータの勝利です!") else -> println("引き分けです!") } }
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
ランダム関数のインポート
import kotlin.random.Random
import kotlin.random.Random: Kotlin標準ライブラリのRandomクラスを使用して、コンピュータがランダムな牌を選ぶ機能を実現しています。メイン関数の開始
fun main() { println("ナインゲームを開始します!")fun main(): Kotlinプログラムのエントリーポイント。プログラムはこの関数から実行されます。println: コンソールにメッセージを表示します。この場合、ゲームの開始を知らせています。
持ち牌の初期化
val playerTiles = mutableMapOf<Int, Boolean>() val computerTiles = mutableMapOf<Int, Boolean>() for (i in 1..9) { playerTiles[i] = true computerTiles[i] = true }mutableMapOf: 可変のマップを作成します。ここでは各プレイヤーの牌(キー)とその使用状態(値)を管理しています。for (i in 1..9): 1から9までの連続した数字をループで処理し、全ての牌を初期化しています。
スコアの初期化
var playerScore = 0 var computerScore = 0
var: 変更可能な変数を宣言します。- プレイヤーとコンピュータの得点を0に初期化します。
ゲームのラウンドを処理
for (round in 1..9) { println("\n【第${round}回戦】") println("プレイヤーの得点 : ${playerScore}点") println("コンピュータの得点: ${computerScore}点") }for (round in 1..9): 9回のラウンドを繰り返します。println: 現在のラウンド数やスコアを表示します。${}: 文字列テンプレートを使い、変数の値を埋め込んでいます。
持ち牌の表示
playerTiles.forEach { (key, value) -> if (value) print("$key ,") else print("- ,") }forEach: マップ内の全ての要素に対して繰り返し処理を行います。if (value): 牌が使用可能かをチェックします。使用可能ならその番号を表示し、使用済みなら-を表示します。
プレイヤーの打牌を入力
var playerTile: Int while (true) { print("持ち牌の中から出す牌を選択してください > ") playerTile = readLine()!!.toInt() if (playerTiles[playerTile] == true) { playerTiles[playerTile] = false break } else { println("その牌は既に使われています。別の牌を選んでください。") } }readLine(): ユーザー入力を取得します。!!.toInt(): 入力された文字列を整数に変換します。!!はnull値がないことを保証します。while (true): 条件が満たされるまで繰り返し実行します。if (playerTiles[playerTile] == true): 入力された牌が使用可能かを確認します。
コンピュータの打牌を決定
val computerTile = computerTiles.filter { it.value }.keys.random() computerTiles[computerTile] = falsefilter: 条件を満たす要素を抽出します。ここでは使用可能な牌だけを選択しています。keys.random(): 使用可能な牌の中からランダムに1つを選択します。
ラウンド結果の判定と得点更新
if (playerTile > computerTile) { println("プレイヤーは${playerTile}点獲得") playerScore += playerTile } else if (computerTile > playerTile) { println("コンピュータは${computerTile}点獲得") computerScore += computerTile } else { println("引き分けです") }if: 条件に応じた処理を実行します。+=: 変数に得点を加算します。
最終結果の表示
if (playerScore > computerScore) { println("プレイヤーの勝利です!") } else if (computerScore > playerScore) { println("コンピュータの勝利です!") } else { println("引き分けです!") }if-else: プレイヤーとコンピュータのスコアを比較して勝敗を判定します。
Kotlinのゲームコード一覧はこちら
- サイト改善アンケート & ご指摘/ご質問
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などを アンケート 形式でお伺いしています。また記事の内容に関する ご指摘 や ご質問 もお待ちしています。


