【Ruby】レッスン5-☆1:クラスとインスタンスでモンスター捕獲ゲームを作ろう

一つ前のページではミックスインについて学習しました。
今回は モンスター捕獲ゲーム を作成してみましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:イニシャライザを理解しよう
・Lesson5-3:アクセスメソッドを理解しよう
・Lesson5-4:クラス変数とクラスメソッドを理解しよう
・Lesson5-5:privateメソッドを理解しよう
・Lesson5-6:正規表現を理解しよう
・Lesson5-7:クラスの継承を理解しよう
・Lesson5-8:ファイル操作を理解しよう
・Lesson5-9:オーバーライドを理解しよう
・Lesson5-10:モジュールを使ってみよう
・Lesson5-11:ミックスインを使ってみよう
・確認問題5-☆1:モンスター捕獲ゲームを作ろう ◁今回はココ
・確認問題5-☆2:モンスターとの戦闘ゲームを作ろう
・確認問題5-☆3:マルバツゲームを作ろう
Rubyのゲームコード一覧はこちら
モンスター捕獲ゲームを作りながらRubyのクラスとサイコロ処理を学ぼう

Rubyでモンスターを捕獲するシンプルなゲームを作成しましょう。
ゲームには3種類のモンスターが登場します。それぞれのモンスターはサイコロを振り、プレイヤーも同じようにサイコロを振ります。
サイコロの出目を競い、プレイヤーがモンスターの出目を上回るとモンスターを捕まえることができます。ただし、プレイヤーがモンスターに負けた場合はゲームオーバーになります。
ゲームを進める中で、すべてのモンスターを捕まえることを目指しましょう。
以下の要件に従ってコードを完成させてください。
- モンスタークラスを定義すること:
- インスタンス変数
@name
を持つ。 dice_roll
メソッドを定義し、1から6までの乱数を返すこと。
- インスタンス変数
- モンスター捕獲ゲームクラスを定義すること:
- 3種類のモンスター(例: スライム、ゴブリン、ドラゴン)をリストとして保持する。
- プレイヤーがサイコロを振ってモンスターと出目を競う仕組みを実装する。
- ゲーム進行の詳細:
- プレイヤーがサイコロを振るか選択できること。
- プレイヤーがモンスターより高い出目を出した場合、そのモンスターを捕まえたと表示すること。
- プレイヤーが負けた場合は「ゲームオーバー」と表示してゲームを終了すること。
- 引き分けの場合は再挑戦する。
- ゲーム終了後:
- 捕まえたモンスターのリストを表示する。
ただし、以下のような実行結果となること。
モンスター捕獲ゲームを始めます! スライムが現れた! スライムがサイコロを振った。出目は 3 サイコロを振りますか? (yes/no): yes プレイヤーがサイコロを振った。出目は 4 スライムを捕まえた! ゴブリンが現れた! ゴブリンがサイコロを振った。出目は 6 サイコロを振りますか? (yes/no): yes プレイヤーがサイコロを振った。出目は 2 ゴブリンを捕まえられなかった。ゲームオーバー! 捕まえたモンスター: スライム ゲーム終了
【ヒント】自力で解くのが難しい人へ
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)1:Monsterクラスを定義
□ attr_readerでname属性を公開
□ initializeメソッドを定義し、引数nameを@nameに代入
□ dice_rollメソッドを定義し、rand(1..6)を返す
2:MonsterCaptureGameクラスを定義
□ initializeメソッドを定義
□ □ @monstersにMonsterクラスのインスタンス(スライム、ゴブリン、ドラゴン)を格納
□ □ @captured_monstersに空の配列を代入
□ start_gameメソッドを定義
□ □ 「モンスター捕獲ゲームを始めます!」と出力
□ □ @monstersをループで処理
□ □ □ モンスター名を出力
□ □ □ capturedフラグをfalseに設定
□ □ □ whileループをcapturedがtrueになるまで繰り返す
□ □ □ □ モンスターのdice_rollメソッドを呼び出し、出目を出力
□ □ □ □ 「サイコロを振りますか?」と出力し、ユーザー入力を取得
□ □ □ □ if文で入力が”no”の場合を判定
□ □ □ □ □ 「次のモンスターへ進みます。」と出力し、breakでループを抜ける
□ □ □ □ player_rollを乱数で取得し、出目を出力
□ □ □ □ if文でプレイヤーの出目がモンスターより大きい場合を判定
□ □ □ □ □ モンスターを捕獲し、名前を@captured_monstersに追加
□ □ □ □ □ capturedをtrueに設定
□ □ □ □ elsif文で引き分けの場合を判定
□ □ □ □ □ 「引き分けでもう一度!」と出力
□ □ □ □ else文でプレイヤーの出目が負けた場合を判定
□ □ □ □ □ 「ゲームオーバー!」と出力し、end_gameメソッドを呼び出して終了
□ end_gameメソッドを定義
□ □ 捕獲したモンスターのリストを出力
□ □ 「ゲーム終了」と出力
3:MonsterCaptureGameクラスのインスタンスを生成し、start_gameメソッドを呼び出してゲームを開始
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# モンスタークラス class Monster attr_reader :name =begin 【穴埋め問題1】 initializeメソッドを定義し、引数nameをインスタンス変数@nameに代入するコードを書いてください。 =end =begin 【穴埋め問題2】 dice_rollメソッドを定義し、1から6までの乱数を返すコードを書いてください。 =end end # ゲームクラス class MonsterCaptureGame =begin 【穴埋め問題3】 initializeメソッドを定義し、以下の内容を実装してください。 ・@monstersにMonsterクラスのインスタンス(スライム、ゴブリン、ドラゴン)を格納すること。 ・@captured_monstersに空の配列を代入すること。 =end =begin 【穴埋め問題4】 start_gameメソッドを定義し、以下を実装してください。 ・「モンスター捕獲ゲームを始めます!」と出力すること。 ・@monstersをループで処理し、各モンスターに対してサイコロの勝負を行うコードを書くこと。 ・プレイヤーがモンスターに勝った場合、そのモンスターを捕まえるコードを書くこと。 ・プレイヤーが負けた場合、ゲームオーバーを表示して終了するコードを書くこと。 =end =begin 【穴埋め問題5】 end_gameメソッドを定義し、以下を実装してください。 ・捕まえたモンスターのリストを出力すること。 ・「ゲーム終了」と出力すること。 =end end # ゲーム開始 =begin 【穴埋め問題6】 MonsterCaptureGameクラスのインスタンスを生成し、start_gameメソッドを呼び出すコードを書いてください。 =end
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答例と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
# モンスタークラス class Monster attr_reader :name def initialize(name) @name = name end def dice_roll rand(1..6) # 1から6までのランダムな数字を返す end end # ゲームクラス class MonsterCaptureGame def initialize @monsters = [ Monster.new("スライム"), Monster.new("ゴブリン"), Monster.new("ドラゴン") ] @captured_monsters = [] end def start_game puts "モンスター捕獲ゲームを始めます!" @monsters.each do |monster| puts "#{monster.name}が現れた!" captured = false while !captured monster_roll = monster.dice_roll puts "#{monster.name}がサイコロを振った。出目は #{monster_roll}" print "サイコロを振りますか? (yes/no): " response = gets.chomp.downcase if response == "no" puts "次のモンスターへ進みます。" break end player_roll = rand(1..6) puts "プレイヤーがサイコロを振った。出目は #{player_roll}" if player_roll > monster_roll puts "#{monster.name}を捕まえた!" @captured_monsters << monster.name captured = true elsif player_roll == monster_roll puts "引き分けでもう一度!" else puts "#{monster.name}を捕まえられなかった。ゲームオーバー!" return end_game end end end end_game end def end_game puts "捕まえたモンスター: #{@captured_monsters.join(', ')}" puts "ゲーム終了" end end # ゲーム開始 game = MonsterCaptureGame.new game.start_game
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
モンスタークラスの定義
class Monster attr_reader :name def initialize(name) @name = name end def dice_roll rand(1..6) end end
class Monster
: これはRubyでクラスを定義する構文です。Monster
はモンスターの性質を表現するクラスです。attr_reader :name
: この文法は@name
というインスタンス変数を読み取るためのゲッターメソッドを自動生成します。これにより外部からモンスターの名前を取得できます。initialize
メソッド: クラスのインスタンスが作られるときに実行されるコンストラクタです。@name
にモンスターの名前を設定しています。dice_roll
メソッド: サイコロを振る処理を表現しています。rand(1..6)
で1から6のランダムな整数を生成します。
モンスター捕獲ゲームクラスの定義
class MonsterCaptureGame def initialize @monsters = [ Monster.new("スライム"), Monster.new("ゴブリン"), Monster.new("ドラゴン") ] @captured_monsters = [] end
class MonsterCaptureGame
: ゲーム全体のロジックを管理するクラスです。initialize
メソッド:@monsters
: モンスターを管理する配列です。各要素はMonster
クラスのインスタンスです。@captured_monsters
: 捕獲したモンスターの名前を保持する空の配列です。
ゲーム開始のメインロジック
def start_game puts "モンスター捕獲ゲームを始めます!" @monsters.each do |monster| puts "#{monster.name}が現れた!" captured = false
start_game
メソッド: ゲームの進行を管理するメソッドです。@monsters.each
: 配列@monsters
をループで処理し、各モンスターを順に操作します。captured = false
: 各モンスターが捕獲されたかどうかを追跡するフラグです。
プレイヤーのサイコロ対決の処理
while !captured monster_roll = monster.dice_roll puts "#{monster.name}がサイコロを振った。出目は #{monster_roll}" print "サイコロを振りますか? (yes/no): " response = gets.chomp.downcase
while !captured
: モンスターが捕獲されるまでループを継続します。monster.dice_roll
: モンスターがサイコロを振ります。その出目をmonster_roll
に格納します。gets.chomp.downcase
: プレイヤーが「yes」または「no」を入力する処理です。入力を小文字に変換して処理します。
プレイヤーとモンスターの勝負
player_roll = rand(1..6) puts "プレイヤーがサイコロを振った。出目は #{player_roll}" if player_roll > monster_roll puts "#{monster.name}を捕まえた!" @captured_monsters << monster.name captured = true elsif player_roll == monster_roll puts "引き分けでもう一度!" else puts "#{monster.name}を捕まえられなかった。ゲームオーバー!" return end_game end end
player_roll = rand(1..6)
: プレイヤーがサイコロを振り、その出目を生成します。if player_roll > monster_roll
: プレイヤーの出目がモンスターより大きい場合、モンスターを捕まえます。elsif player_roll == monster_roll
: 引き分けの場合、再挑戦となります。else
: プレイヤーが負けた場合、ゲームオーバーを宣言し、ゲームを終了します。
ゲーム終了処理
def end_game puts "捕まえたモンスター: #{@captured_monsters.join(', ')}" puts "ゲーム終了" end
end_game
メソッド: 捕獲したモンスターのリストを表示し、ゲーム終了を告げる処理です。@captured_monsters.join(', ')
: 配列をカンマで結合して文字列に変換します。
ゲームの実行
game = MonsterCaptureGame.new game.start_game
MonsterCaptureGame.new
:MonsterCaptureGame
クラスの新しいインスタンスを作成します。game.start_game
: ゲームを開始します。
まとめ
このプログラムを通じてRubyのクラス設計や配列の操作、ランダム値の生成、条件分岐を学ぶことができます。
初心者が楽しく学べる構造で設計されており、プログラミングの基礎を自然に身につけられるでしょう。
実際にコードを変更して、独自のモンスターやゲームルールを追加してみるのも良い練習です。
ぜひ挑戦してみてください!
Rubyのゲームコード一覧はこちら