【Kotlin】レッスン5-☆1:モンスター捕獲ゲームを作ろう|抽象クラスとランダム処理で学ぶ継承の基本

一つ前のページではデータクラスについて学習しました。
今回は モンスター捕獲ゲーム を作成していきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数編
Lesson4:コレクション編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:プライマリコンストラクタを理解しよう
・Lesson5-3:セカンダリコンストラクタを理解しよう
・Lesson5-4:ふたつのコンストラクタを使いこなそう
・Lesson5-5:アクセス修飾子とカプセル化を理解しよう
・Lesson5-6:クラスメンバとインスタンスメンバを理解しよう
・Lesson5-7:クラスの継承を理解しよう
・Lesson5-8:メソッドのオーバーライドを理解しよう
・Lesson5-9:クラスを拡張しよう
・Lesson5-10:抽象クラスを理解しよう
・Lesson5-11:インターフェースを理解しよう
・Lesson5-12:データクラスを理解しよう
・確認問題5-☆1:モンスター捕獲ゲームを作ろう ◁今回はココ
・確認問題5-☆2:マルバツゲームを作ろう
・確認問題5-☆3:石取りゲームを作ろう
Kotlinのゲームコード一覧はこちら
Kotlinでモンスター捕獲ゲームを実装しよう|抽象クラスとサイコロロジックを学ぶ

複数のモンスターを捕まえるゲームを作成しましょう。
このゲームではモンスターがサイコロを振り、その結果を見てプレイヤーはサイコロを振るかどうかを決めることができます。
プレイヤーのサイコロの目がモンスターのサイコロの目より大きければ捕獲成功。小さければ失敗でゲーム終了です。
この問題の要件
以下の要件に従ってコードを完成させてください。
- 抽象クラス
Character
を定義name
という名前のプロパティを持ちます(String
型)。- サイコロを振る
rollDice
という関数を持ちます。この関数は 1 から 6 までのランダムな整数を返します。
Character
クラスを継承するMonster
クラスを定義- コンストラクタでモンスターの名前を受け取ります。
Character
クラスを継承するPlayer
クラスを定義- コンストラクタでプレイヤーの名前を受け取ります。
main
関数でゲームを実行Player
オブジェクトを作成し、名前は「勇者」とします。Monster
オブジェクトを 3 つ作成し、それぞれ「ゴブリン」、「スライム」、「ドラゴン」という名前をつけます。- これらのモンスターを
ArrayList
に格納します。 - プレイヤーが各モンスターを捕まえようとするループを実行します。ループの中で、プレイヤーはサイコロを振るかどうかを決めることができます。
- プレイヤーのサイコロの目がモンスターのサイコロの目より大きければ捕まえることができます。失敗するとゲームオーバーとなり、ループが終了します。
ただし、以下のような実行結果となること。
ゴブリンを捕まえようとしています...
ゴブリンのサイコロ: 4
サイコロを振りますか? (yes/no): yes
プレイヤーのサイコロ: 6
ゴブリンを捕まえました!
スライムを捕まえようとしています...
スライムのサイコロ: 5
サイコロを振りますか? (yes/no): yes
プレイヤーのサイコロ: 3
スライムを捕まえられませんでした...
ゲームオーバー!
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:kotlin.random.Randomモジュールのインポート
2:抽象クラスCharacterの定義
□ プライマリコンストラクタでnameプロパティを初期化
□ rollDice関数の定義
□ □ Random.nextIntを用いて1から6までのランダムな整数を返す
3:Monsterクラスの定義
□ Characterクラスを継承
4:Playerクラスの定義
□ Characterクラスを継承
5:main関数の定義
□ Playerオブジェクトplayerの生成
□ Monsterオブジェクトmonster1、monster2、monster3の生成
□ ArrayListにモンスターを格納
□ forループでmonstersリストを反復処理
□ □ モンスターの名前を出力
□ □ モンスターのrollDice関数を呼び出して結果をmonsterRollに格納
□ □ monsterRollを出力
□ □ 「サイコロを振りますか?」と出力
□ □ ユーザー入力を受け取り、response変数に格納
□ □ if文でresponseが”yes”と一致するか判定(大文字小文字を無視)
□ □ □ プレイヤーのrollDice関数を呼び出して結果をplayerRollに格納
□ □ □ playerRollを出力
□ □ □ if文でplayerRollがmonsterRollより大きいか判定
□ □ □ □ 成功メッセージを出力
□ □ □ □ ゲーム続行
□ □ □ else文
□ □ □ □ 失敗メッセージを出力
□ □ □ □ ゲームオーバーメッセージを出力
□ □ □ □ breakでループ終了
□ □ else文
□ □ □ モンスター捕獲を諦めた旨を出力
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
クリックして開く148481import kotlin.random.Random
2
3// 抽象クラス Character を定義
4abstract class Character(val name: String) {
5// サイコロを振る関数
6fun rollDice(): Int {
7/* 【穴埋め問題1】
8ここにサイコロを振るためのランダムな数を生成するコードを書いてください。
9*/
10}
11}
12
13// Character クラスを継承する Monster クラスを定義
14class Monster(name: String) : Character(name)
15
16// Character クラスを継承する Player クラスを定義
17class Player(name: String) : Character(name)
18
19fun main() {
20// プレイヤーを作成
21val player = Player("勇者")
22
23// モンスターを作成
24val monster1 = Monster("ゴブリン")
25val monster2 = Monster("スライム")
26val monster3 = Monster("ドラゴン")
27
28// モンスターを格納するArrayListを作成
29val monsters = arrayListOf(monster1, monster2, monster3)
30
31// プレイヤーがモンスターを捕まえようとするループ
32for (monster in monsters) {
33println("${monster.name}を捕まえようとしています...")
34val monsterRoll = monster.rollDice()
35println("${monster.name}のサイコロ: $monsterRoll")
36
37print("サイコロを振りますか? (yes/no): ")
38val response = readLine()?.trim() ?: ""
39
40if (response.equals("yes", ignoreCase = true)) {
41/* 【穴埋め問題2】
42ここにプレイヤーがサイコロを振るためのコードを書いてください。
43*/
44} else {
45println("${monster.name}を捕まえるのを諦めました。")
46}
47}
48}
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
練習問題の解答と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
クリックして開く153531
import kotlin.random.Random
2
3// 抽象クラス Character を定義
4abstract class Character(val name: String) {
5// サイコロを振る関数
6fun rollDice(): Int {
7return Random.nextInt(6) + 1 // 1から6までのランダムな数を返す
8}
9}
10
11// Character クラスを継承する Monster クラスを定義
12class Monster(name: String) : Character(name)
13
14// Character クラスを継承する Player クラスを定義
15class Player(name: String) : Character(name)
16
17fun main() {
18// プレイヤーを作成
19val player = Player("勇者")
20
21// モンスターを作成
22val monster1 = Monster("ゴブリン")
23val monster2 = Monster("スライム")
24val monster3 = Monster("ドラゴン")
25
26// モンスターを格納するArrayListを作成
27val monsters = arrayListOf(monster1, monster2, monster3)
28
29// プレイヤーがモンスターを捕まえようとするループ
30for (monster in monsters) {
31println("${monster.name}を捕まえようとしています...")
32val monsterRoll = monster.rollDice()
33println("${monster.name}のサイコロ: $monsterRoll")
34
35print("サイコロを振りますか? (yes/no): ")
36val response = readLine()?.trim() ?: ""
37
38if (response.equals("yes", ignoreCase = true)) {
39val playerRoll = player.rollDice()
40println("プレイヤーのサイコロ: $playerRoll")
41
42if (playerRoll > monsterRoll) {
43println("${monster.name}を捕まえました!")
44} else {
45println("${monster.name}を捕まえられませんでした...")
46println("ゲームオーバー!")
47break
48}
49} else {
50println("${monster.name}を捕まえるのを諦めました。")
51}
52}
53}
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
抽象クラス Character の定義
クリックして開く151abstract class Character(val name: String) {
2fun rollDice(): Int {
3return Random.nextInt(6) + 1
4}
5}
- abstract class Character: これは抽象クラスで、具体的なインスタンスを作成できません。他のクラスが継承して使うことを目的としています。
- val name: String: キャラクターの名前を表すプロパティです。
- fun rollDice(): Int: サイコロを振る関数です。
Random.nextInt(6)
によって、1~6 のランダムな値を生成します。
Monster クラスと Player クラスの定義
クリックして開く121class Monster(name: String) : Character(name)
2class Player(name: String) : Character(name)
- class Monster:
Character
クラスを継承しています。モンスター専用の追加機能はありません。 - class Player: プレイヤーのクラスも
Character
を継承し、基本的に同じ構造です。
main関数とゲームのセットアップ
クリックして開く171fun main() {
2val player = Player("勇者")
3val monster1 = Monster("ゴブリン")
4val monster2 = Monster("スライム")
5val monster3 = Monster("ドラゴン")
6
7val monsters = arrayListOf(monster1, monster2, monster3)
- fun main(): Kotlinプログラムのエントリーポイントです。
- val player = Player(“勇者”): プレイヤーのインスタンスを作成します。
- val monsters = arrayListOf(…): モンスターをリストに格納し、順番に操作できるようにします。
モンスターとの対戦ループ
クリックして開く141for (monster in monsters) {
2println("${monster.name}を捕まえようとしています...")
3val monsterRoll = monster.rollDice()
4println("${monster.name}のサイコロ: $monsterRoll")
- for (monster in monsters): リスト内のモンスターを1体ずつ順番に処理します。
- monster.rollDice(): モンスターがサイコロを振ります。
プレイヤーの選択と対戦結果の処理
クリックして開く118181print("サイコロを振りますか? (yes/no): ")
2val response = readLine()?.trim() ?: ""
3
4if (response.equals("yes", ignoreCase = true)) {
5val playerRoll = player.rollDice()
6println("プレイヤーのサイコロ: $playerRoll")
7
8if (playerRoll > monsterRoll) {
9println("${monster.name}を捕まえました!")
10} else {
11println("${monster.name}を捕まえられませんでした...")
12println("ゲームオーバー!")
13break
14}
15} else {
16println("${monster.name}を捕まえるのを諦めました。")
17}
18}
- readLine(): コンソールからユーザーの入力を取得します。
- response.equals(“yes”, ignoreCase = true): ユーザーが「yes」を入力したかを確認します。
- player.rollDice(): プレイヤーがサイコロを振ります。
- if (playerRoll > monsterRoll): プレイヤーのサイコロの値がモンスターより大きい場合、捕まえることに成功します。それ以外はゲームオーバーになります。
まとめ
このコードではKotlinの基本的なクラス構造やリスト操作、サイコロを使ったゲームロジックを学べます。
特に継承とループの使い方、そしてユーザー入力の処理が中心となっています。
これを応用して、さらに複雑なゲームやアプリを作成できるスキルを磨いていきましょう!
Kotlinのゲームコード一覧はこちら
- サイト改善アンケート & ご指摘/ご質問
-
本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などを アンケート 形式でお伺いしています。また記事の内容に関する ご指摘 や ご質問 もお待ちしています。