ゲームのキャラクターをクラスで作れ。 キャラクターのオブジェクトは、名前、最大体力 m、今の体力をフィールドに持つ。 今の体力は m から始まる。 キャラクターにはメソッドを三つ用意する。 hit(d) は体力を d だけ減らす。 ただし体力は 0 より小さくならず、0 で止まる。 heal(h) は体力を h だけ増やす。 ただし体力は m より大きくならず、m で止まる。 体力が 0 のキャラクターは倒れているので、回復を受けても何も変わらない。 状態文字列のメソッドは、キャラクターを "名前 体力/m" の形の文字列にして返す(例:ann 7/10)。 体力が 0 のときは、その後ろに空白一つと down を付ける(例:ann 0/10 down)。 状態文字列のメソッドは、その言語がオブジェクトを文字列に変えるときに呼ぶ名前で作ってみよう(Python __str__、Java・JS・TS toString、C# ToString、C++ operator<<)。 一行目にキャラクターの数 n と命令の数 q が与えられる。 続く n 行に、1 番から n 番までのキャラクターの名前と最大体力 m が一行に一つずつ与えられる。 続く q 行に、命令が一行に一つずつ与えられる。 hit i d は i 番のキャラクターの hit(d) を呼び、heal i h は i 番のキャラクターの heal(h) を呼ぶ。 命令を一つ処理するたびに、i 番のキャラクターの状態文字列を一行に出力せよ。 すべての命令を処理したあと、最後の行に倒れていない(体力が 1 以上の)キャラクターの数を出力せよ。 採点は出力だけを見るので、メソッドの分け方は検査しない。
入力
1 ≤ n ≤ 100、1 ≤ q ≤ 1,000、1 ≤ m ≤ 1,000、1 ≤ i ≤ n、1 ≤ d ≤ 1,000、1 ≤ h ≤ 1,000(すべて整数で、カンマなしの数字だけで与えられる)。 名前は英小文字・数字 1〜10 文字で、同じ名前のキャラクターが複数いることがある。 一行の中の値は空白一つで区切る
出力
命令ごとに一行ずつ q 行、そして最後の行に倒れていないキャラクターの数
例 1 · stdin
2 6
ann 10
bo 5
hit 1 3
heal 1 5
hit 2 9
heal 2 3
hit 1 4
hit 2 1
stdout
ann 7/10
ann 10/10
bo 0/5 down
bo 0/5 down
ann 6/10
bo 0/5 down
1
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.StringTokenizer;public class Main { static class Hero { private final String name; private final int maxHp; private int hp; Hero(String name, int maxHp) { this.name = name; this.maxHp = maxHp; this.hp = maxHp; // 체력은 가득 찬 채로 시작한다 } void hit(int d) { hp = Math.max(0, hp - d); // 0보다 작아지지 않는다 } void heal(int h) { if (hp == 0) return; // 쓰러진 캐릭터는 회복하지 못한다 hp = Math.min(maxHp, hp + h); } boolean isDown() { return hp == 0; } // println(hero)와 "" + hero 가 부르는 메서드. @Override가 이름 오타를 잡아 준다 @Override public String toString() { String text = name + " " + hp + "/" + maxHp; return isDown() ? text + " down" : text; } } public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int n = Integer.parseInt(st.nextToken()); int q = Integer.parseInt(st.nextToken()); Hero[] heroes = new Hero[n]; for (int i = 0; i < n; i++) { st = new StringTokenizer(br.readLine()); String name = st.nextToken(); heroes[i] = new Hero(name, Integer.parseInt(st.nextToken())); } StringBuilder sb = new StringBuilder(); for (int i = 0; i < q; i++) { st = new StringTokenizer(br.readLine()); String cmd = st.nextToken(); Hero hero = heroes[Integer.parseInt(st.nextToken()) - 1]; int amount = Integer.parseInt(st.nextToken()); if (cmd.equals("hit")) hero.hit(amount); else hero.heal(amount); sb.append(hero).append('\n'); // append(객체)가 toString을 부른다 } int up = 0; for (Hero h : heroes) if (!h.isDown()) up++; sb.append(up).append('\n'); System.out.print(sb); }}
C#Main.cs · 65 行
using System;using System.Text;class Hero{ private readonly string name; private readonly int maxHp; private int hp; public Hero(string name, int maxHp) { this.name = name; this.maxHp = maxHp; hp = maxHp; // 체력은 가득 찬 채로 시작한다 } public void Hit(int d) { hp = Math.Max(0, hp - d); // 0보다 작아지지 않는다 } public void Heal(int h) { if (hp == 0) return; // 쓰러진 캐릭터는 회복하지 못한다 hp = Math.Min(maxHp, hp + h); } public bool IsDown => hp == 0; // Console.WriteLine(hero)와 $"{hero}"가 부르는 메서드. override를 빼면 불리지 않는다 public override string ToString() { string text = $"{name} {hp}/{maxHp}"; return IsDown ? text + " down" : text; }}class Program{ static void Main() { string[] first = Console.ReadLine()!.Trim().Split(' '); int n = int.Parse(first[0]), q = int.Parse(first[1]); var heroes = new Hero[n]; for (int i = 0; i < n; i++) { string[] p = Console.ReadLine()!.Trim().Split(' '); heroes[i] = new Hero(p[0], int.Parse(p[1])); } var sb = new StringBuilder(); for (int i = 0; i < q; i++) { string[] p = Console.ReadLine()!.Trim().Split(' '); Hero hero = heroes[int.Parse(p[1]) - 1]; int amount = int.Parse(p[2]); if (p[0] == "hit") hero.Hit(amount); else hero.Heal(amount); sb.Append(hero).Append('\n'); // Append(객체)가 ToString을 부른다 } int up = 0; foreach (Hero h in heroes) if (!h.IsDown) up++; sb.Append(up).Append('\n'); Console.Write(sb); }}
C++main.cpp · 58 行
#include <algorithm>#include <iostream>#include <string>#include <vector>using namespace std;class Hero { string name_; int max_hp_; int hp_;public: Hero(const string& name, int max_hp) : name_(name), max_hp_(max_hp), hp_(max_hp) {} void hit(int d) { hp_ = max(0, hp_ - d); } // 0보다 작아지지 않는다 void heal(int h) { if (hp_ == 0) return; // 쓰러진 캐릭터는 회복하지 못한다 hp_ = min(max_hp_, hp_ + h); } bool is_down() const { return hp_ == 0; } // C++에는 toString이 없다. cout << hero 가 되도록 << 연산자를 만들어 준다 friend ostream& operator<<(ostream& os, const Hero& h) { os << h.name_ << ' ' << h.hp_ << '/' << h.max_hp_; if (h.is_down()) os << " down"; return os; }};int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, q; cin >> n >> q; vector<Hero> heroes; for (int i = 0; i < n; i++) { string name; int m; cin >> name >> m; heroes.emplace_back(name, m); } for (int i = 0; i < q; i++) { string cmd; int idx, amount; cin >> cmd >> idx >> amount; Hero& hero = heroes[idx - 1]; // &가 없으면 복사본을 고치게 된다 if (cmd == "hit") hero.hit(amount); else hero.heal(amount); cout << hero << '\n'; } int up = 0; for (const Hero& h : heroes) if (!h.is_down()) up++; cout << up << '\n'; return 0;}