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

50110130

一つ前のページではミックスインについて学習しました。

今回は モンスター捕獲ゲーム を作成してみましょう。

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のクラスとサイコロ処理を学ぼう

Rubyでモンスターを捕獲するシンプルなゲームを作成しましょう。

ゲームには3種類のモンスターが登場します。それぞれのモンスターはサイコロを振り、プレイヤーも同じようにサイコロを振ります。

サイコロの出目を競い、プレイヤーがモンスターの出目を上回るとモンスターを捕まえることができます。ただし、プレイヤーがモンスターに負けた場合はゲームオーバーになります。

ゲームを進める中で、すべてのモンスターを捕まえることを目指しましょう。

以下の要件に従ってコードを完成させてください。

  1. モンスタークラスを定義すること:
    • インスタンス変数 @name を持つ。
    • dice_roll メソッドを定義し、1から6までの乱数を返すこと。
  2. モンスター捕獲ゲームクラスを定義すること:
    • 3種類のモンスター(例: スライム、ゴブリン、ドラゴン)をリストとして保持する。
    • プレイヤーがサイコロを振ってモンスターと出目を競う仕組みを実装する。
  3. ゲーム進行の詳細
    • プレイヤーがサイコロを振るか選択できること。
    • プレイヤーがモンスターより高い出目を出した場合、そのモンスターを捕まえたと表示すること。
    • プレイヤーが負けた場合は「ゲームオーバー」と表示してゲームを終了すること。
    • 引き分けの場合は再挑戦する。
  4. ゲーム終了後
    • 捕まえたモンスターのリストを表示する。

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

モンスター捕獲ゲームを始めます!
スライムが現れた!
スライムがサイコロを振った。出目は 3
サイコロを振りますか? (yes/no): yes
プレイヤーがサイコロを振った。出目は 4
スライムを捕まえた!
ゴブリンが現れた!
ゴブリンがサイコロを振った。出目は 6
サイコロを振りますか? (yes/no): yes
プレイヤーがサイコロを振った。出目は 2
ゴブリンを捕まえられなかった。ゲームオーバー!
捕まえたモンスター: スライム
ゲーム終了

【ヒント】自力で解くのが難しい人へ

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

Q
ヒント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メソッドを呼び出してゲームを開始

Q
ヒント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

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

この問題の解答例と解説

この問題の正解コードとその解説は以下の通りです。

クリックして開いて確認してください。

Q
正解コード
# モンスタークラス
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
Q
正解コードの解説

コードをブロックごとに分割して解説します。

モンスタークラスの定義

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.newMonsterCaptureGameクラスの新しいインスタンスを作成します。
  • game.start_game: ゲームを開始します。

まとめ

このプログラムを通じてRubyのクラス設計や配列の操作、ランダム値の生成、条件分岐を学ぶことができます。

初心者が楽しく学べる構造で設計されており、プログラミングの基礎を自然に身につけられるでしょう。

実際にコードを変更して、独自のモンスターやゲームルールを追加してみるのも良い練習です。

ぜひ挑戦してみてください!

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

もっと分かりやすいサイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいRuby学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

Rubyの記事一覧

次のページ>>

記事URLをコピーしました