こんにちは!じゃいごテックのあつしです。
今回はpaiza クラス・構造体メニュー からSTEP3: 格闘ゲームという問題を解説します。
この問題集はクラスの応用的な使い方に関する4個のSTEP問題(B~A級)とFINAL問題(A級)で構成されていて、STEP問題を解いて行けばFINAL問題も解けるはず!となっています。
STEP3: 格闘ゲーム(paizaランク B 相当)を解いてみる
※ paizaレベルアップ問題集 クラス・構造体メニューより
問題
友達の家で N 人で遊んでいる paiza 君は格闘ゲームを遊ぶことにしました。
格闘ゲームのルールは次の通りです。
- 各プレイヤーは 決まった hp と 3 種類の技を持っていて、技には強化系の技と攻撃の技があり、各攻撃技には技を出すための発生フレーム F とダメージ A が設定されている。
- hp が 0 になったプレイヤーは退場となる。
- あるプレイヤー 1 が、他のプレイヤーにある技 T_1 (発生フレーム F_1 , 攻撃力 A_1) を使って攻撃した場合、攻撃を受けたプレイヤー 2 は反撃の技 T_2 (発生フレーム F_2 , 攻撃力 A_2) を選ぶ。その後、次のようなルールに従っていずれかのプレイヤーにダメージが入る。
どちらか片方でもプレイヤーが退場している場合、互いに何も起こらない。
強化系の技を使った場合、使ったプレイヤーの他の全ての技の発生フレーム(最短 1 フレーム) を -3 , 攻撃力を +5 する。
相手が攻撃技を使っていた場合、その攻撃の攻撃力分 hp が減少する。
互いに攻撃技を使った場合
- F_1 < F_2 のとき、プレイヤー 2 の hp が A_1 減る
- F_1 > F_2 のとき、プレイヤー 1 の hp が A_2 減る
- F_1 = F_2 のとき、何も起こらない
各プレイヤーの持っている技についての情報と、技が出された回数、使われた技の詳細が与えられるので、全ての技が使われた後に場に残っているプレイヤーの人数を答えてください。
入力される値
N K
hp_1 F1_1 A1_1 F2_1 A2_1 F3_1 A3_3
...
hp_N F1_N A1_N F2_N A2_N F3_N A3_N
P1_1 T1_1 P2_1 T2_1
...
P1_K T1_K P2_K T2_K
- 1 行目では、プレイヤー数 N と攻撃回数 K が与えられます。
- 続く N 行のうち i 行目(1 ≦ i ≦ N)では、
i 番目のプレイヤーの hp である hp_i,
技 1 の発生フレーム F1_i , 攻撃力 A1_i
技 2 の発生フレーム F2_i , 攻撃力 A2_i
技 3 の発生フレーム F3_i , 攻撃力 A3_i が半角スペース区切りで与えられます。
ただし、発生フレーム・攻撃力が共に 0 である技は強化技であることを表しています。 - 続く K 行のうち、 i 行目では i 回目の攻撃内容が与えられます。
技を使ったプレイヤーの番号 P1_i と P1_i が選んだ技の番号 T1_i
技を使ったプレイヤーの番号 P2_i と P2_i が選んだ技の番号 T2_i
が半角スペース区切りで与えられます。
入力値最終行の末尾に改行が1つ入ります。
期待する出力
場に残っているプレイヤーの人数を 1 行で出力してください。
条件
すべてのテストケースにおいて、以下の条件をみたします。
- 1 ≦ N , K ≦ 1000
- 1 ≦ hp_i ≦ 100 (1 ≦ i ≦ N)
- 0 ≦ F1_i , F2_i , F3_i ≦ 60 (1 ≦ i ≦ N)
- 0 ≦ A1_i , A2_i , A3_i ≦ 30 (1 ≦ i ≦ N)
- 1 ≦ P1_i , P2_i ≦ N , P1_i ≠ P2_i (1 ≦ i ≦ K)
- T1_i , T2_i は 1 , 2 , 3 のいずれか (1 ≦ i ≦ K)
- 強化技は各プレイヤーに最大 1 つまで
- 入力例1
- 3 6
10 1 1 2 2 3 3
10 0 0 6 1 7 2
10 0 0 7 5 8 3
1 1 2 2
1 2 3 2
1 3 2 3
2 2 3 1
2 3 3 1
1 2 3 2
- 出力例1
- 2
- 入力例2
- 5 10
8 2 24 40 25 42 26
59 48 13 21 13 56 2
5 59 7 57 5 25 24
99 28 6 32 5 23 2
62 24 19 11 19 7 21
2 1 3 2
2 1 3 2
5 1 3 1
5 3 1 2
1 1 2 2
4 2 3 1
5 3 3 2
2 3 3 2
4 1 5 3
2 3 3 2
- 出力例2
- 3
攻略ポイント
ポイント
- プレイヤーの情報をクラスにまとめる
- hpをインスタンス変数に格納する
- 手持ちスキルをインスタンス変数に格納する
- ダメージを受けたときの処理を考える
- 退場の処理を考える(今回はhp=0で退場とする)
- hpがマイナスにならないようにする
- インスタンスメソッドで強化技を実装する
- ゲームの流れを管理するクラスを考える
- ターンスキップの処理
- プレイヤーのどちらかが退場している
- 攻撃技同士でスピードが同じ場合
- 攻撃処理の条件分岐
- 両方が攻撃技のとき
- スピードが速い方が攻撃できる
- 片方が強化技の時
- 強化技を実行する
- 相手の攻撃を受ける
- 両方が強化技の時
- 両方が強化技を実行する
- 両方が攻撃技のとき
- ターンスキップの処理
参考記事
クラス
メソッドの定義と呼び出し
標準入力・標準出力
問題を解く流れ
入出力例をコピペしてヒアドキュメントで変数に代入し、データを確認します。正しく受け取れていれば確認用コードは削除します。
INPUT1 = <<~"EOS" 3 6 10 1 1 2 2 3 3 10 0 0 6 1 7 2 10 0 0 7 5 8 3 1 1 2 2 1 2 3 2 1 3 2 3 2 2 3 1 2 3 3 1 1 2 3 2 EOS OUTPUT1 = <<~"EOS" 2 EOS INPUT2 = <<~"EOS" 5 10 8 2 24 40 25 42 2 59 48 13 21 13 56 2 5 59 7 57 5 25 24 99 28 6 32 5 23 2 62 24 19 11 19 7 21 2 1 3 2 2 1 3 2 5 1 3 1 5 3 1 2 1 1 2 2 4 2 3 1 5 3 3 2 2 3 3 2 4 1 5 3 2 3 3 2 EOS OUTPUT2 = <<~"EOS" 3 EOS # 確認用コード pp INPUT1 # > "3 6\n" + # > "10 1 1 2 2 3 3\n" + # > "10 0 0 6 1 7 2\n" + # > "10 0 0 7 5 8 3\n" + # > "1 1 2 2\n" + # > "1 2 3 2\n" + # > "1 3 2 3\n" + # > "2 2 3 1\n" + # > "2 3 3 1\n" + # > "1 2 3 2\n" p OUTPUT1 # > "2\n" pp INPUT2 # > "5 10\n" + # > "8 2 24 40 25 42 26\n" + # > "59 48 13 21 13 56 2\n" + # > "5 59 7 57 5 25 24\n" + # > "99 28 6 32 5 23 2\n" + # > "62 24 19 11 19 7 21\n" + # > "2 1 3 2\n" + # > "2 1 3 2\n" + # > "5 1 3 1\n" + # > "5 3 1 2\n" + # > "1 1 2 2\n" + # > "4 2 3 1\n" + # > "5 3 3 2\n" + # > "2 3 3 2\n" + # > "4 1 5 3\n" + # > "2 3 3 2\n" p OUTPUT2 # > "3\n"
続いてPlayerクラス・FightingGameクラス
と問題を解く
solveメソッド
を変数の下に定義します。
まず、Playerクラス
を定義します。
Playerクラス
- インスタンス変数
- 体力 @hp : Integer(外部から参照可)
- 所持スキル @skills : Array(外部から参照可)
- initializeメソッド
- initialize(hp, skills)
- @hp を hp で初期化する
- @skills を skills で初期化する
- initialize(hp, skills)
- インスタンスメソッド
- reinforce
- 強化技以外の所持スキルを強化する
- 早さ(speed) を -3 (下限を1とする)
- 攻撃(power) を +5 インスタンスメソッド
- 強化技以外の所持スキルを強化する
- take_damage(damage)
- @hp から damage を引く(下限を0とする)
- reinforce
class Player attr_reader :hp, :skills def initialize(hp, skills) @hp = hp @skills = skills end def reinforce @skills.each do |skill| if skill[:speed] > 0 skill[:speed] = [1, skill[:speed] - 3].max skill[:power] += 5 end end end def take_damage(damage) @hp = [0, @hp - damage].max end end # 確認用コード # インスタンスの生成 skills = [{ speed: 0, power: 0 }, { speed: 3, power: 10 }, { speed: 10, power: 20 }] player = Player.new(100, skills) # インスタンス変数の確認 pp player # > #<Player:0x00007ffff2b95588 # > @hp=100, # > @skills= # > [{:speed=>0, :power=>0}, {:speed=>3, :power=>10}, {:speed=>10, :power=>20}]> p player.hp # > 100 p player.skills # > [{:speed=>0, :power=>0}, {:speed=>3, :power=>10}, {:speed=>10, :power=>20}] # reinforce の確認 p player.reinforce # > [{:speed=>0, :power=>0}, {:speed=>1, :power=>15}, {:speed=>7, :power=>25}] p player.reinforce # > [{:speed=>0, :power=>0}, {:speed=>1, :power=>20}, {:speed=>4, :power=>30}] p player.reinforce # > [{:speed=>0, :power=>0}, {:speed=>1, :power=>25}, {:speed=>1, :power=>35}] # take_gamage の確認 p player.take_damage(80) # > 20 p player.take_damage(999) # > 0
続いて、FightingGameクラス
を定義します。
FightingGameクラス
- インスタンス変数
- 参加プレイヤー @players : Player(外部から参照可)
- initializeメソッド
- initialize(players)
- @players を players で初期化する
- initialize(players)
- インスタンスメソッド
- fighting(p_no1, s_no1, p_no2, s_no2)
- 引数の情報を基に戦うプレイヤーと使うskillを選択する
- プレイヤー player = players[p_no - 1]
- 使用スキル skill = player.skills[s_no - 1]
- turn_end? メソッドでターンスキップを確認する
- スキルのスピード順で並び替える(player1が早い、player2が遅い)
- 戦闘の処理を行う
- player1が攻撃技ならskill1でplayer2のtake_damageメソッドを実行してターン終了
- player1が強化技ならplayer1がreinforce メソッドを実行してplayer2の手番
- player2が攻撃技ならskill2でplayer1のtake_damageメソッドを実行してターン終了
- player2が強化技ならplayer2がreinforceメソッドを実行してターン終了
- 引数の情報を基に戦うプレイヤーと使うskillを選択する
- turn_end?(player1, skill1, player2, skill2)(外部から呼び出し不可)
- ターンスキップの判定を行う
- どちらかのhpが0ならtrue
- 両方が攻撃技でスピードが同じならtrue
- 上記どちらにも当てはまらなければfalse
- ターンスキップの判定を行う
- fighting(p_no1, s_no1, p_no2, s_no2)
class FightingGame attr_reader :players def initialize(players) @players = players end def fighting(p_no1, s_no1, p_no2, s_no2) # プレイヤーとスキルを選択 player1 = @players[p_no1 - 1] skill1 = player1.skills[s_no1 - 1] player2 = @players[p_no2 - 1] skill2 = player2.skills[s_no2 - 1] # ターンスキップの条件を満たしているなら何もせず終了 if turn_end?(player1, skill1, player2, skill2) # 確認用コード puts "スキップ" puts "---------------------------------" return end # スピード順で並び替える if skill1[:speed] > skill2[:speed] player1, player2 = player2, player1 skill1, skill2 = skill2, skill1 end # ///// 確認用コード ///// puts <<~"EOS" < order > player#{p_no1}, skill_no: #{s_no1} player#{p_no2}, skill_no: #{s_no2} < fighting > player#{p_no1} hp:#{@players[p_no1 - 1].hp} skills: #{@players[p_no1 - 1].skills} skill_params: #{@players[p_no1 - 1].skills[s_no1 - 1]} player#{p_no2} hp:#{@players[p_no2 - 1].hp} skills: #{@players[p_no2 - 1].skills} skill_params: #{@players[p_no2 - 1].skills[s_no2 - 1]} EOS # /////////////////////// # 戦闘の処理 if skill1[:power] > 0 # player1 が攻撃 player2.take_damage(skill1[:power]) else # player1 が強化 player1.reinforce if skill1[:power] == 0 if skill2[:power] == 0 # player2 が強化 player2.reinforce else # player2 が攻撃 player1.take_damage(skill2[:power]) end end # ///// 確認用コード ///// puts <<~"EOS" < result > player#{p_no1} hp:#{@players[p_no1 - 1].hp} skills: #{@players[p_no1 - 1].skills} player#{p_no2} hp:#{@players[p_no2 - 1].hp} skills: #{@players[p_no2 - 1].skills} --------------------------------- EOS # /////////////////////// end private # ターンスキップの判定 def turn_end?(player1, skill1, player2, skill2) # どちらかが倒れていれば何もしない return true if player1.hp == 0 || player2.hp == 0 # 両方攻撃技でspeedが同じなら何もしない return true if skill1[:power] > 0 && skill2[:power] > 0 && skill1[:speed] == skill2[:speed] false end end # 確認用コード p1 = Player.new(10, [{ speed: 1, power: 1 }, { speed: 2, power: 2 }, { speed: 3, power: 3 }]) p2 = Player.new(10, [{ speed: 0, power: 0 }, { speed: 6, power: 1 }, { speed: 7, power: 2 }]) p3 = Player.new(10, [{ speed: 0, power: 0 }, { speed: 7, power: 5 }, { speed: 8, power: 3 }]) game = FightingGame.new([p1, p2, p3]) # 両方が攻撃技でスピードが違うとき game.fighting(1, 1, 2, 2) # > < order > # > player1, skill_no: 1 # > player2, skill_no: 2 # > # > < fighting > # > player1 hp:10 # > skills: [{:speed=>1, :power=>1}, {:speed=>2, :power=>2}, {:speed=>3, :power=>3}] # > skill_params: {:speed=>1, :power=>1} # > # > player2 hp:10 # > skills: [{:speed=>0, :power=>0}, {:speed=>6, :power=>1}, {:speed=>7, :power=>2}] # > skill_params: {:speed=>6, :power=>1} # > # > < result > # > player1 hp:10 # > skills: [{:speed=>1, :power=>1}, {:speed=>2, :power=>2}, {:speed=>3, :power=>3}] # > # > player2 hp:9 # > skills: [{:speed=>0, :power=>0}, {:speed=>6, :power=>1}, {:speed=>7, :power=>2}] # > --------------------------------- # 両方が攻撃技でスピードが同じとき game.fighting(2, 3, 3, 2) # > スキップ # > --------------------------------- # 片方がが強化技のとき game.fighting(2, 1, 1, 1) # > < order > # > player2, skill_no: 1 # > player1, skill_no: 1 # > # > < fighting > # > player2 hp:9 # > skills: [{:speed=>0, :power=>0}, {:speed=>6, :power=>1}, {:speed=>7, :power=>2}] # > skill_params: {:speed=>0, :power=>0} # > # > player1 hp:10 # > skills: [{:speed=>1, :power=>1}, {:speed=>2, :power=>2}, {:speed=>3, :power=>3}] # > skill_params: {:speed=>1, :power=>1} # > # > < result > # > player2 hp:8 # > skills: [{:speed=>0, :power=>0}, {:speed=>3, :power=>6}, {:speed=>4, :power=>7}] # > # > player1 hp:10 # > skills: [{:speed=>1, :power=>1}, {:speed=>2, :power=>2}, {:speed=>3, :power=>3}] # > --------------------------------- # 両方強化技の時 game.fighting(2, 1, 3, 1) # > < order > # > player2, skill_no: 1 # > player3, skill_no: 1 # > # > < fighting > # > player2 hp:8 # > skills: [{:speed=>0, :power=>0}, {:speed=>3, :power=>6}, {:speed=>4, :power=>7}] # > skill_params: {:speed=>0, :power=>0} # > # > player3 hp:10 # > skills: [{:speed=>0, :power=>0}, {:speed=>7, :power=>5}, {:speed=>8, :power=>3}] # > skill_params: {:speed=>0, :power=>0} # > # > < result > # > player2 hp:8 # > skills: [{:speed=>0, :power=>0}, {:speed=>1, :power=>11}, {:speed=>1, :power=>12}] # > # > player3 hp:10 # > skills: [{:speed=>0, :power=>0}, {:speed=>4, :power=>10}, {:speed=>5, :power=>8}] # > --------------------------------- # K.O. game.fighting(2, 2, 3, 3) # > < order > # > player2, skill_no: 2 # > player3, skill_no: 3 # > # > < fighting > # > player2 hp:8 # > skills: [{:speed=>0, :power=>0}, {:speed=>1, :power=>11}, {:speed=>1, :power=>12}] # > skill_params: {:speed=>1, :power=>11} # > # > player3 hp:10 # > skills: [{:speed=>0, :power=>0}, {:speed=>4, :power=>10}, {:speed=>5, :power=>8}] # > skill_params: {:speed=>5, :power=>8} # > # > < result > # > player2 hp:8 # > skills: [{:speed=>0, :power=>0}, {:speed=>1, :power=>11}, {:speed=>1, :power=>12}] # > # > player3 hp:0 # > skills: [{:speed=>0, :power=>0}, {:speed=>4, :power=>10}, {:speed=>5, :power=>8}] # > --------------------------------- # どちらかが hp=0 のとき game.fighting(2, 2, 3, 3) # > スキップ # > ---------------------------------
クラスの動作が良さそうなら、確認用コードを削除してFightingGameクラス
の下にsolveメソッド
を記述していきます。
まず、入力データを受け取る処理を書きます。
def solve(input_data) # 入力データ受け取り input_data = input_data.split("\n") n, k = input_data.shift.split.map(&:to_i) players = input_data.shift(n).map do |player_params| hp, *skill_params = player_params.split.map(&:to_i) skills = skill_params.each_slice(2).map do |speed, power| { speed: speed, power: power } end [hp, skills] end requests = input_data.shift(k).map { |request| request.split.map(&:to_i) } # 確認用コード [players, requests] end # 確認用コード pp solve(INPUT1) # > [[[10, # > [{:speed=>1, :power=>1}, {:speed=>2, :power=>2}, {:speed=>3, :power=>3}]], # > [10, # > [{:speed=>0, :power=>0}, {:speed=>6, :power=>1}, {:speed=>7, :power=>2}]], # > [10, # > [{:speed=>0, :power=>0}, {:speed=>7, :power=>5}, {:speed=>8, :power=>3}]]], # > [[1, 1, 2, 2], # > [1, 2, 3, 2], # > [1, 3, 2, 3], # > [2, 2, 3, 1], # > [2, 3, 3, 1], # > [1, 2, 3, 2]]] pp solve(INPUT2) # > [[[8, # > [{:speed=>2, :power=>24}, # > {:speed=>40, :power=>25}, # > {:speed=>42, :power=>26}]], # > [59, # > [{:speed=>48, :power=>13}, # > {:speed=>21, :power=>13}, # > {:speed=>56, :power=>2}]], # > [5, # > [{:speed=>59, :power=>7}, # > {:speed=>57, :power=>5}, # > {:speed=>25, :power=>24}]], # > [99, # > [{:speed=>28, :power=>6}, # > {:speed=>32, :power=>5}, # > {:speed=>23, :power=>2}]], # > [62, # > [{:speed=>24, :power=>19}, # > {:speed=>11, :power=>19}, # > {:speed=>7, :power=>21}]]], # > [[2, 1, 3, 2], # > [2, 1, 3, 2], # > [5, 1, 3, 1], # > [5, 3, 1, 2], # > [1, 1, 2, 2], # > [4, 2, 3, 1], # > [5, 3, 3, 2], # > [2, 3, 3, 2], # > [4, 1, 5, 3], # > [2, 3, 3, 2]]]
データが正しく受け取れていれば、solve メソッド
に処理を追加していきます。
配列players
の先頭から順にPlayerクラス
でインスタンス化した配列で上書きします。配列requests
の値に従ってgame.fightingメソッド
を実行します。
game.fighting(player1の番号, player1が使うスキルの番号, player2の番号, player2が使うスキルの番号)- 戦闘終了後、
配列players
のうちhp
が残っている人数をカウントします。
def solve(input_data) # 入力データ受け取り input_data = input_data.split("\n") n, k = input_data.shift.split.map(&:to_i) players = input_data.shift(n).map do |player_params| hp, *skill_params = player_params.split.map(&:to_i) skills = skill_params.each_slice(2).map do |speed, power| { speed: speed, power: power } end [hp, skills] end requests = input_data.shift(k).map { |request| request.split.map(&:to_i) } # players をインスタンス化して上書き players.map! { |hp, skills| Player.new(hp, skills) } # playersを渡してFightingGameクラスでインスタンス game を生成 game = FightingGame.new(players) # game に request を渡してゲームを進める requests.each do |request| game.fighting(*request) end # ゲーム終了時に hp が残っている player の人数を返す game.players.count { |player| player.hp > 0 } end # 確認用コード p solve(INPUT1) # > 2 p solve(INPUT1) == OUTPUT1 # > false p solve(INPUT2) # > 3 p solve(INPUT2) == OUTPUT2 # > false
後は出力形式を整えれば完成です。
p solve(INPUT1) == OUTPUT1 -> true
を確認するために、配列result
を改行で連結して末尾に改行を加えます。
def solve(input_data) # 入力データ受け取り input_data = input_data.split("\n") n, k = input_data.shift.split.map(&:to_i) players = input_data.shift(n).map do |player_params| hp, *skill_params = player_params.split.map(&:to_i) skills = skill_params.each_slice(2).map do |speed, power| { speed: speed, power: power } end [hp, skills] end requests = input_data.shift(k).map { |request| request.split.map(&:to_i) } # players をインスタンス化して上書き players.map! { |hp, skills| Player.new(hp, skills) } # playersを渡してFightingGameクラスでインスタンス game を生成 game = FightingGame.new(players) # game に request を渡してゲームを進める requests.each do |request| game.fighting(*request) end # ゲーム終了時に hp が残っている player の人数を返す game.players.count { |player| player.hp > 0 }.to_s << "\n" end # 確認用コード p solve(INPUT1) # > "2\n" p solve(INPUT1) == OUTPUT1 # > true p solve(INPUT2) # > "3\n" p solve(INPUT2) == OUTPUT2 # > true
入出力例での動作確認が出来ましたので、標準入力からのデータ受け取りに変更して、手動で動作確認をしたら提出します。
複数行のデータ受け取りなので STDIN.read
を使います。(入力終了は Ctrl+D
又は Ctrl+Z
)
解答コード
class Player attr_reader :hp, :skills def initialize(hp, skills) @hp = hp @skills = skills end def reinforce @skills.each do |skill| if skill[:speed] > 0 skill[:speed] = [1, skill[:speed] - 3].max skill[:power] += 5 end end end def take_damage(damage) @hp = [0, @hp - damage].max end end class FightingGame attr_reader :players def initialize(players) @players = players end def fighting(p_no1, s_no1, p_no2, s_no2) # プレイヤーとスキルを選択 player1 = @players[p_no1 - 1] skill1 = player1.skills[s_no1 - 1] player2 = @players[p_no2 - 1] skill2 = player2.skills[s_no2 - 1] # ターンスキップの条件を満たしているなら何もせず終了 return if turn_end?(player1, skill1, player2, skill2) # スピード順で並び替える if skill1[:speed] > skill2[:speed] player1, player2 = player2, player1 skill1, skill2 = skill2, skill1 end # 戦闘の処理 if skill1[:power] > 0 # player1 が攻撃 player2.take_damage(skill1[:power]) else # player1 が強化 player1.reinforce if skill1[:power] == 0 if skill2[:power] == 0 # player2 が強化 player2.reinforce else # player2 が攻撃 player1.take_damage(skill2[:power]) end end end private # ターンスキップの判定 def turn_end?(player1, skill1, player2, skill2) # どちらかが倒れていれば何もしない return true if player1.hp == 0 || player2.hp == 0 # 両方攻撃技でspeedが同じなら何もしない return true if skill1[:power] > 0 && skill2[:power] > 0 && skill1[:speed] == skill2[:speed] false end end def solve(input_data) # 入力データ受け取り input_data = input_data.split("\n") n, k = input_data.shift.split.map(&:to_i) players = input_data.shift(n).map do |player_params| hp, *skill_params = player_params.split.map(&:to_i) skills = skill_params.each_slice(2).map do |speed, power| { speed: speed, power: power } end [hp, skills] end requests = input_data.shift(k).map { |request| request.split.map(&:to_i) } # players をインスタンス化して上書き players.map! { |hp, skills| Player.new(hp, skills) } # playersを渡してFightingGameクラスでインスタンス game を生成 game = FightingGame.new(players) # game に request を渡してゲームを進める requests.each do |request| game.fighting(*request) end # ゲーム終了時に hp が残っている player の人数を文字列に変換して末尾に改行を追加 game.players.count { |player| player.hp > 0 }.to_s << "\n" end puts solve(STDIN.read)
今回のまとめ
Playerクラス
と、ゲームを管理するFightingGameクラス
を作って問題を解いてみました。
一見複雑そうな問題に見えますが、クラス別に動作を確認して最後に全体をまとめる感じで解くことが出来ました。
オブジェクト指向プログラミングらしくなってきましたね!
次からはA級問題となります!