ポケモンバトル5[2.0ver]

Ruby

こんにちはkazutoです。今回は、ポケモンバトルシリーズの続きになります。

仕様内容の確認

まず初めに、実装のアウトラインを把握しましょう。仕様書は下記です。


上記のチャート図が今回、実装していくアウトラインになります。もし実装中で

  • コードの意味がわからない
  • 実装の全体像が掴めない
  • 行き詰まった場合

などの問題を抱えてしまった場合は、再度チャート図を見て、実装のアウトラインを把握しましょう。全体像が掴めないまま実装してしまうと後から大変になります。

今回は、Itemクラスを実装して、アイテムを使える様にしましょう。「ポケモンバトル2.0ver」は、だいぶ完成に近づいてきました。Itemクラスを実装する際は、他クラスとの関係性も考えて実装していきます。

Itemクラス

Itemクラスを実装していく手順は

  • インスタンスを生成、initializeメソッドを用いてインスタンス変数を初期化
  • アイテムメニュー構築
  • モンスタボール系の実装
  • 回復系アイテムの実装

 という流れで実装していきます。

インスタンスを生成、initializeメソッドを用いてインスタンス変数を初期化

他クラスと同様、Itemクラスもインスタンスを生成していきます。

class Item
    def initialize(kizugusuri,mantan,monster_bole,haiper_bole,legendary_pokemon_name)
      @kizugusuri=kizugusuri
      @mantan=mantan
      @monster_bole=monster_bole
      @haiper_bole=haiper_bole
      @legendary_pokemon_name=legendary_pokemon_name
    end
end
# 伝説のポケモン定義
legendary_pokemon=Legendary_pokemon.new
pokemon=legendary_pokemon.select_pokemon
# 手持ちのポケモン定義
puts"たたかうポケモンは、#{pokemon[:name]}"
pokemon_on_hand =Pokemon_on_hand.new
pokemons=pokemon_on_hand.pokemon_on_hand
battle_pokemon=pokemon_on_hand.pokemon_list(pokemon_on_hand)
# たたかう
attack= Attack.new(battle_pokemon,pokemon, pokemon_on_hand,pokemons)
# アイテム
item=Item.new(5,3,10,6,pokemon[:name])

Itemクラスのinitializeメソッドで初期化しているインスタンス変数は、

  • @kizugusuri
    →きずぐすりの個数
  • @mantan
    →まんたんのくすりの個数
  • @monster_bole
    →モンスタボールの個数
  • @haiper_bole
    →ハイパーボールの個数
  • @legendary_pokemon_name
    →伝説のポケモンの名前

となります。

今回は、アイテムの個数をインスタンス変数で管理をし、個数が0になった場合は、アイテムを使用できないという流れで実装していくため、上記の様な、インスタンス変数の構成になりました。

@legendary_pokemon_nameに関しては、伝説のポケモンを捕まえた際に伝説のポケモンの名前を出力させたいため、インスタンス変数と定義しています。

アイテムメニューの構築

アイテムを選択できる様にするため、アイテムメニュー欄を構築していきます。まだ、処理を何も記述していないため、大枠を整えるだけです。
アイテムメニュー欄を作成するにあたり、items_selectメソッドを作成します。

class Item
def items_select(battle_pokemon,poke_hand)
        puts  "[1]きずぐすり✖︎#{@kizugusuri}"        
        puts  "[2]まんたんなくすり✖︎#{@mantan}"       
        puts  "[3]モンスターボール✖︎#{@monster_bole}" 
        puts  "[4]ハイパーボール✖︎#{@haiper_bole}"    
        puts  "[5]戻る"
        input =gets.to_i
      case input
          when 1 
             #きずぐすり
          when 2
             #まんたんなくすり
          when 3
             #モンスターボール
          when 4
             #ハイパーボール
          else 
            puts "戻る"
      end
    end
end

コマンドメニュー欄と構成は特に変わらないと思います。なのでソースコードの説明は省略させていただきます。

        puts  "[1]きずぐすり✖︎#{@kizugusuri}"        
        puts  "[2]まんたんなくすり✖︎#{@mantan}"       
        puts  "[3]モンスターボール✖︎#{@monster_bole}" 
        puts  "[4]ハイパーボール✖︎#{@haiper_bole}"    
        puts  "[5]戻る"

こちらの変数展開で扱っているインスタンス変数の部分については、アイテム個数が入ります。

モンスタボール系の実装

続いてモンスターボール系の実装をしていきます。まず初めにアイテムを使用したらアイテム数が減る様に consume_itemメソッドを作成します。

class Item
  def consume_item(item)
      item-=1
  end
end

仕様として、どのアイテムを使用した場合でも、必ずconsume_itemメソッドを呼び出します。毎度,consume_itemメソッドを呼び出さない場合、実際に使用したアイテム数とアイテムメニュー欄に出力される個数に誤差が生じる恐れがあります。

なのでどのアイテムを使用する場合においても必ずconsume_itemメソッドを呼び出す必要があります。処理自体は、とてもシンプルです。引数と渡されるインスタンス変数(アイテムの個数)に1を引いた数を返り値として返すだけです。

アイテムを使用する事前準備ができましたので、本格的にモンスターボール系の実装を行っていきます。「ポケモンを捕まえたか判定する」という動作を再現をしたいので,新たにcatch_pokemonメソッドを作成します。

モンスタボールを投げた場合、必ずポケモンを捕まえるわけではありません。なので、一定数の確率でポケモンを捕まえられるという仕様にしています。

class Item
   def catch_pokemon(monster_ball,legendary_pokemon_name) 
       puts "・・・"
       gets
       if Random.rand(0..2) == 0 
         puts"やった〜#{legendary_pokemon_name}を捕まえたぞ"
         exit
       elsif  Random.rand(0..2) == 1
         puts "だめだ捕まらない"
       elsif  Random.rand(0..2) == 2
         puts "あ〜もう少しだったなのに〜"
       end
     end
   end
end

上記のソースコードは、Randomを用いて一定数の確率ポケモンを捕まえるという仕様を再現をしています。

処理内容は、前回にも解説をしたので省略させていただきます。

モンスターボール系の実装は、以上となりますので、アイテムメニュー欄にメソッドを呼び出す処理を記述していきましょう。

 case input
         when 1 
             #きずぐすり
         when 2
             #まんたんなくすり
         when 3
              return puts "モンスターボールは無くなった" if @monster_ball==0
              @monster_bole= consume_item(@monster_bole)
              puts"モンスターボールを投げた"
              catch_pokemon(@monster_ball,@legendary_pokemon_name)
          when 4
              return puts "ハイパーボールは無くなった" if @haiper_bole==0
              @haiper_bole= consume_item(@haiper_bole)
              puts"ハイパーボールを投げた"
              catch_pokemon(@haiper_bole,@legendary_pokemon_name)
          else 
            puts "戻る"
      end
 return puts "モンスターボールは無くなった" if @monster_ball==0

こちらは、モンスターボールの個数が0になった場合に発火し、「モンスターボールは無くなった」を文字列として出力します。

@monster_bole= consume_item(@monster_bole)

consume_itemメソッドの返り値を@monster_boleに再代入をしています。要するに1を引いた数を@monster_boleに格納しています。

 catch_pokemon(@legendary_pokemon_name)

catch_pokemonメソッドを呼び出して「ポケモンを捕まえたか判定」をしています。もしポケモンが捕まった場合、捕まえた伝説のポケモンの名前を出力をしたいので、引数に@legendary_pokemon_nameを渡しています。

ハイパーボールに関しても同じ仕組みのプログラムなので、解説は、省略します。以上で、モンスタボール系の実装を終えます。続いて、回復系のアイテムの実装を行います。

回復系アイテムの実装

続いて回復系のアイテムを実装します。仕様として回復したいポケモンを手持ちのポケモンから選ぶという流れになります。作成するメソッドについては下記です。

  • recoveryメソッド
    →ポケモンのHPを回復する
  • pokemon_selecter
    →Pokemon_on_handクラスのメソッドをつなげる
  • select_pokemon_that_uses_items(Pokemon_on_handクラス)
    →回復するポケモンを選択する

まず初めにrecoveryメソッドを作成をしていきます。

[recoveryメソッド]

class Item
  def recovery(poke_hand,item)
      poke_hand[:hp]+=40  if item == @kizugusuri
      poke_hand[:hp]=100  if item == @mantan
      if poke_hand[:hp]>=100
        poke_hand[:hp]=100
        puts"HPが満タンになった"
      end
    end
end

recoveryメソッドは、

  • もし変数itemが@kizugusuriの場合
    →ポケモンのHPを40回復する
  • もし変数itemが@mantanの場合
    →ポケモンのHPを全回復をする

 と条件分岐をしております。その後,HPが満タン(100)の場合

if poke_hand[:hp]>=100
        poke_hand[:hp]=100
        puts"HPが満タンになった"
end

HPを初期化をし、HPが満タンになったと出力をしています。以上でrecoveryメソッドの実装を終わります。ここまで積み上げきたらrecoveryメソッドのソースコードも「簡単‼️」と感じる方いる事でしょう。
後もう少しで、完成なのでもう一息,頑張りましょう。

続いて,pokemon_selecterメソッドを実装していきます。

[pokemon_selecterメソッド]

 def pokemon_selecter(poke_hand,battle_pokemon)
      poke_hand = poke_hand.select_pokemon_that_uses_items(poke_hand)
      return poke_hand
    end
  poke_hand = poke_hand.select_pokemon_that_uses_items(poke_hand)

pokemon_selecterは、
select_pokemon_that_uses_itemsメソッドを呼び出すために用意したメソッドなので少し処理内容のイメージが湧かないと思います。
ただselect_pokemon_that_uses_itemsメソッド の返り値を変数に格納してpokemon_selecterの返り値として呼び出し元に返しているというだけです。

return  poke_hand

今回は、returnメソッドを記述してpoke_handを返しています。

以上で、pokemon_selecterメソッド解説を終わります。
続いて、select_pokemon_that_uses_itemsメソッドを実装していきます。

[select_pokemon_that_uses_itemsメソッド]

def select_pokemon_that_uses_items(poke_hand)
      puts @Pokemon_on_hand
      @pokemon_on_hand.each do |pokemon|
        pokemon.each_with_index do|poke,key|
          puts  poke[:hp]>0 ?  " #{key+1}.HP:#{poke[:hp]}#{poke[:name]}" : "瀕死(#{poke[:name]}は使えません)"
          poke[:dying]="瀕死"  if poke[:hp]<=0 
        end
      end
      puts "どのポケモンを回復させる❓"
      input = gets.to_i
      return @pokemon_on_hand[0][input-1] if @pokemon_on_hand[0][input-1][:hp]==100
      if @pokemon_on_hand[0][input-1][:dying]=="瀕死"
        puts "瀕死のポケモンは回復する事はできないよ"
        return @pokemon_on_hand[0][input-1]
      end
        puts "#{@pokemon_on_hand[0][input-1][:name]}"
        return @pokemon_on_hand[0][input-1]
    end

ソースコードをみて頂ければ,select_pokemon_that_uses_itemsメソッドは、以前、「ポケモンを入れ替える」動作を再現するにあたり作成した,pokemon_listメソッドと似ている部分がある事に気づくと思います。

 @pokemon_on_hand.each do |pokemon|
        pokemon.each_with_index do|poke,key|
          puts  poke[:hp]>0 ?  " #{key+1}.HP:#{poke[:hp]}#{poke[:name]}" : "瀕死(#{poke[:name]}は使えません)"
          poke[:dying]="瀕死"  if poke[:hp]<=0 
        end
      end

こちらは、pokemon_listメソッドと同じく、each_with_indexを用いて、手持ちのポケモンの情報を配列からバラしています。

 puts  poke[:hp]>0 ?  " #{key+1}.HP:#{poke[:hp]}#{poke[:name]}" : "瀕死(#{poke[:name]}は使えません)"

こちらの三項演算子は、ポケモンのHPが0以下の場合、瀕死と出力する様に条件分岐をしています。ここまでは、pokemon_listメソッドと同じ実装になっていますが、

poke[:dying]="瀕死"  if poke[:hp]<=0 

上記のコードでハッシュに新たに:dyingというキーを追加しています。:dyingを追加をする理由は、:dyingが追加されている,すなわち瀕死状態のポケモンは回復できないという仕様にしたいためです。

今回は、瀕死状態から復活できる

  • げんきのかけら
  • げんきのかたまり

などは、バッグの中にありませんので、瀕死状態から復活をする事はありません。したがって、瀕死状態に陥った場合は、回復できないという挙動にします。

 return @pokemon_on_hand[0][input-1] if @pokemon_on_hand[0][input-1][:hp]==100

選択したポケモンのHPが100だった場合は、returnメソッドを用いて処理を強制終了しています。

 if @pokemon_on_hand[0][input-1][:dying]=="瀕死"
        puts "瀕死のポケモンは回復する事はできないよ"
        return @pokemon_on_hand[0][input-1]
     end

選択したポケモンに:dyingというキーが追加されていた場合は、選択したポケモンが瀕死状態に陥っており、回復をする事ができない状況になります。
また、返り値として選択したポケモンの情報を返します。(呼び出し側の条件分岐で使うため)

 puts "#{@pokemon_on_hand[0][input-1][:name]}"
        return @pokemon_on_hand[0][input-1]

選択したポケモンが複数のif文の条件に該当しない場合は、正当に回復をする事ができるので、返り値として選択したポケモンの情報を返します。

以上でselect_pokemon_that_uses_itemsメソッドの実装を終了します。

最後に実装した内容を、アイテムメニュー(items_selectメソッド)にまとめましょう。

def items_select(battle_pokemon,poke_hand)
        puts  "[1]きずぐすり✖︎#{@kizugusuri}"        
        puts  "[2]まんたんなくすり✖︎#{@mantan}"       
        puts  "[3]モンスターボール✖︎#{@monster_bole}" 
        puts  "[4]ハイパーボール✖︎#{@haiper_bole}"    
        puts  "[5]戻る"
        input =gets.to_i
      case input
          when 1 
              return puts "きずぐすりは無くなった" if @kizugusuri==0
              battle_pokemon = pokemon_selecter(poke_hand,battle_pokemon)
              puts battle_pokemon
              return  if battle_pokemon[:dying]== "瀕死"
              return puts"HPはまんたんだからアイテムを使う必要がないよ"  if battle_pokemon[:hp]==100
              @kizugusuri = consume_item(@kizugusuri)
              recovery(battle_pokemon,@kizugusuri)
          when 2
              return puts "まんたんのくすりは無くなった" if @mantan==0
              battle_pokemon = pokemon_selecter(poke_hand,battle_pokemon)
              puts battle_pokemon
              return if battle_pokemon[:dying]== "瀕死"
              return puts"HPはまんたんだからアイテムを使う必要がないよ"  if battle_pokemon[:hp]==100
              @mantan = consume_item(@mantan)
              recovery(battle_pokemon,@mantan)
          when 3
              return puts "モンスターボールは無くなった" if @monster_ball==0
              @monster_bole= consume_item(@monster_bole)
              puts"モンスターボールを投げた"
              catch_pokemon(@monster_ball,@legendary_pokemon_name)
          when 4
              return puts "ハイパーボールは無くなった" if @haiper_bole==0
              @haiper_bole= consume_item(@haiper_bole)
              puts"ハイパーボールを投げた"
              catch_pokemon(@haiper_bole,@legendary_pokemon_name)
          else 
            puts "戻る"
      end
    end

先ほど、モンスターボール系の解説はしたので省略をします。

     when 1 
              return puts "きずぐすりは無くなった" if @kizugusuri==0
              battle_pokemon = pokemon_selecter(poke_hand,battle_pokemon)
              return  if battle_pokemon[:dying]== "瀕死"
              return puts"HPはまんたんだからアイテムを使う必要がないよ"  if battle_pokemon[:hp]==100
              @kizugusuri = consume_item(@kizugusuri)
              recovery(battle_pokemon,@kizugusuri)
          when 2
              return puts "まんたんのくすりは無くなった" if @mantan==0
              battle_pokemon = pokemon_selecter(poke_hand,battle_pokemon)
              return if battle_pokemon[:dying]== "瀕死"
              return puts"HPはまんたんだからアイテムを使う必要がないよ"  if battle_pokemon[:hp]==100
              @mantan = consume_item(@mantan)
              recovery(battle_pokemon,@mantan)

上記が回復系の呼び出す処理になります。

 return puts "きずぐすりは無くなった" if @kizugusuri==0

こちらもアイテム数が0になった場合、アイテムが無いことを出力をしています。

 battle_pokemon = pokemon_selecter(poke_hand,battle_pokemon)

上記のソースコードは、pokemon_selecterメソッドの返り値を変数battle_pokemonに格納しています。battle_pokemonに格納されている情報を元に条件分岐をしていきます。

return  if battle_pokemon[:dying]== "瀕死"

battle_pokemonに格納の情報のハッシュに:dyingというキーがある場合は、瀕死状態になるので、回復をする事ができませんのでreturnメソッドで強制終了しています。

 return puts"HPはまんたんだからアイテムを使う必要がないよ"  if battle_pokemon[:hp]==100

battle_pokemonに格納されているポケモンのHPが100(満タン)な場合、回復をしても意味がないので、こちらもreturnメソッド使って強制終了しています。

  @mantan = consume_item(@mantan)
  recovery(battle_pokemon,@mantan)

if文の条件に一致しない場合は、battle_pokemonに格納しているポケモンは回復ができるので、consume_itemメソッドで使用したアイテム数を減らし、recoveryメソッドで、HPを回復しています。

まんたんのくすりを選択した場合も同じ処理をしているので、省略をします。以上で、回復系アイテムの実装を終了しました。そして、Itemクラスの実装も終了しました。

ポケモンバトル2.0verもコマンドメニュー欄を構築をすれば、いよいよ完成です。

メニュー欄を構築しよう

最後にメニュー欄を構築していきます。

 while true do
      puts "HP:#{pokemon[:hp]}#{pokemon[:name]}"
      puts "HP:#{battle_pokemon[:hp]}#{battle_pokemon[:name]}"
      puts"[1]たたかう"
      puts"[2]バッグ"
      puts"[3]ポケモン"
      puts"[4]逃げる"
      input=gets.to_i
      case input
        when 1
            attack.pokemon_attack(battle_pokemon,pokemon,pokemon_on_hand)
            attack.pokemon_attack(pokemon,battle_pokemon,pokemon_on_hand)
            battle_pokemon =  pokemon_on_hand.pokemon_list(pokemon_on_hand)  if battle_pokemon[:hp] <=0
        when 2
           item.items_select(battle_pokemon,pokemon_on_hand)
           attack.pokemon_attack(pokemon,battle_pokemon,pokemon_on_hand)
           battle_pokemon  =  pokemon_on_hand.pokemon_list(pokemon_on_hand)  if battle_pokemon[:hp] <=0
        when 3 
          battle_pokemon =pokemon_on_hand.pokemon_list(pokemon_on_hand)
          puts "ゆけ#{battle_pokemon[:name]}"
          attack.pokemon_attack(pokemon,battle_pokemon,pokemon_on_hand)
          battle_pokemon = pokemon_on_hand.pokemon_list(pokemon_on_hand)  if battle_pokemon[:hp] <=0
        when 4
            puts "・・・"
            gets
          if Random.rand(0..2) == 0
            puts"上手く逃げ切れた"
            exit
          else
            puts "逃げられなかった"
          end
           attack.pokemon_attack(pokemon,battle_pokemon,pokemon_on_hand)
           battle_pokemon = pokemon_on_hand.pokemon_list(pokemon_on_hand)  if battle_pokemon[:hp] <=0
        end
      end
 item.items_select(battle_pokemon,pokemon_on_hand)

items_selectメソッドを呼び出して終わりです。

まとめ:ポケモンバトルシリーズ5[2.0ver]

今回でポケモンバトル2.0verの実装を以上となります。ここまで積み上げてきた方はとても素晴らしい継続力を持っています。その素晴らしい継続力を生かして今後もプログラミング学習を継続をしていきましょう‼️

ポケモンバトル2.0verシリーズを終えた方は、Rubyの基礎的な部分には対応できると思うので、Ruby on RailsというRubyのフレームワークを学んでみても良いと思います。
なおおすすめは、プロゲートです。

※完成版のソースコードは別の記事にまとめておきます。

以上,kazutoでした。

関連記事