上級演習:RPGの戦闘シミュレータ
クラス・継承・ループ・乱数を組み合わせて、ターン制の「RPG戦闘シミュレータ」を作ります。
📝 問題
以下の仕様を満たすプログラムを作成してください。
Characterクラスを作成し、name(名前)・hp(HP)・atk(攻撃力)を持たせるattack(target)メソッドで相手に ランダムなダメージ(atk±5)を与えるCharacterを継承したHeroクラスを作り、必殺技(ダメージが通常の2倍)を持たせる- 勇者とモンスターが交互に攻撃するターン制バトルを実装する
- 3ターン目 に勇者が必殺技を使用する
- どちらかのHPが0以下になったらバトル終了・勝者を表示する
💡 ヒント
- ダメージは
random.randint(self.atk - 5, self.atk + 5)で計算できます - 生存確認は
def is_alive(self): return self.hp > 0で実装できます - 継承は
class Hero(Character):と書きます - ループは
while hero.is_alive() and monster.is_alive():で回します
✅ 回答例
import random
class Character:
def __init__(self, name, hp, atk):
self.name = name
self.hp = hp
self.atk = atk
def attack(self, target):
damage = random.randint(self.atk - 5, self.atk + 5)
target.hp -= damage
print(f" {self.name} → {target.name} に {damage} ダメージ!"
f"(残りHP:{max(0, target.hp)})")
def is_alive(self):
return self.hp > 0
class Hero(Character):
def special(self, target):
damage = self.atk * 2
target.hp -= damage
print(f" ★ {self.name} の必殺技!"
f" {target.name} に {damage} の大ダメージ!")
# バトル開始
hero = Hero("勇者", 100, 20)
monster = Character("ドラゴン", 80, 15)
turn = 1
print(f"=== {hero.name} vs {monster.name} ===")
while hero.is_alive() and monster.is_alive():
print(f"
--- ターン {turn} ---")
if turn == 3:
hero.special(monster) # 3ターン目は必殺技
else:
hero.attack(monster)
if monster.is_alive():
monster.attack(hero)
turn += 1
winner = hero.name if hero.is_alive() else monster.name
print(f"
=== 勝者:{winner} ===")
▶ 出力結果(例)
=== 勇者 vs ドラゴン === --- ターン 1 --- 勇者 → ドラゴン に 23 ダメージ!(残りHP:57) ドラゴン → 勇者 に 17 ダメージ!(残りHP:83) --- ターン 2 --- 勇者 → ドラゴン に 18 ダメージ!(残りHP:39) ドラゴン → 勇者 に 12 ダメージ!(残りHP:71) --- ターン 3 --- ★ 勇者 の必殺技! ドラゴン に 40 の大ダメージ! === 勝者:勇者 ===
🔍 解説ポイント
max(0, target.hp)でHPが負になっても表示上は0になるclass Hero(Character):と書くだけで Character の全メソッドを引き継げるwhile hero.is_alive() and monster.is_alive():でどちらも生存している間ループが続く- 乱数を使っているので毎回バトルの展開が変わる(実行するたびに結果が異なる)
🚀 発展課題(できる人向け)
- モンスターにも特殊攻撃を追加してみよう
- 勇者にHP回復アイテムを持たせてバトルを長くしてみよう
- バトル終了時に「勇者の残りHP」「総ターン数」を表示してみよう
