[Python]　classを理解するために、kenに旅に出てもらった【RPG風コード】

# はじめに
classの写経何度かしたけどよーわからんのでkenに旅に出てもらうことにしました。
Google Colabで実行できます。
[Colabの使い方(Python.jp)](https://www.python.jp/train/experience/colab.html "Python.jp 入門講座")

# 下書き
まずはプレイヤーとエネミーのクラスを作って、
オープニングとエンカウントのテキストを入力ﾎﾟﾁｰ
~~~Python:コード
class Player:
  def __init__(self, name, hp):
    self.name = name
    self.hp = hp
  def attack(self):
    power = 5
    return power
class Monster:
  def __init__(self, name, hp):
    self.name = name
    self.hp = hp
  def attack(self):
    power = 1
    return power

hero = Player(ken, 35)
enemy = Monster(mochi, 10)

print(f'{hero.name}は旅にでた。')
print(f'{enemy.name}があらわれた！')
~~~
~~~:実行結果
NameError                                 Traceback (most recent call last)
<ipython-input-8-d2117a274943> in <cell line: 16>()
~~~
おっと……、文字列はちょんちょんで囲もうな！！！

# 戦闘開始
さいしょの村だし、プレイヤーが勝つとして、こんな感じか？
~~~Python:コード
p_t = hero.attack()
e_h = enemy.hp - p_t

print(f'{hero.name}の攻撃')
print(f'{enemy.name}に{p_t}のダメージ')
print(f'{enemy.name}の残りHP：{e_h}')
print(f'{enemy.name}の攻撃')
print(f'{hero.name}に{e_t}のダメージ')
print(f'{hero.name}の残りHP：{p_h}')
print(f'{hero.name}の攻撃')
print(f'{enemy.name}に{p_t}のダメージ')
print(f'{enemy.name}の残りHP：{e_h}')
print(f'{hero.name}の勝利')
~~~
~~~:実行結果
kenの攻撃
mochiに5のダメージ
mochiの残りHP：5
mochiの攻撃
kenに1のダメージ
kenの残りHP：34
kenの攻撃
mochiに5のダメージ
mochiの残りHP：5
kenの勝利
~~~
妙だな……、敵の残HP5……？？？

# while使ってみる
もしかしてclassいっこでいいのか？
バトルシーンは関数にしてみよ。
~~~Python:コード
class Character:
  def __init__(self, name, hp, attack):
    self.name = name
    self.hp = hp
    self.attack = attack
  def attack(self):
    pass

def battle(p_n, p_hp, p_atk, e_n, e_hp, e_atk):
  p_rhp = p_hp
  e_rhp = e_hp
  while e_rhp > 0:
    print(f'{p_n}の攻撃')
    print(f'{e_n}に{p_atk}のダメージ！')
    e_rhp = e_rhp - p_atk
    print(f'{e_n}の攻撃')
    print(f'{p_n}に{e_atk}のダメージ！')
    p_rhp = p_rhp - e_atk
  print(f'{p_n}の勝利!!')

def main():
  player = Character('ken', 35, 5)
  enemy = Character('mochi', 10, 1)
  print(f'{player.name}は旅にでた')
  print(f'{enemy.name}があらわれた！')
  battle(player.name, player.hp, player.attack, enemy.name, enemy.hp, enemy.attack)

if __name__ == '__main__':
  main()
~~~
~~~:実行結果
kenは旅にでた。
mochiがあらわれた！
kenの攻撃
mochiに5のダメージ！
mochiの攻撃
kenに1のダメージ！
kenの攻撃
mochiに5のダメージ！
mochiの攻撃
kenに1のダメージ！
kenの勝利!!
~~~
えっ、オーバーキルしてる！mochiかわいそう。
条件式の判定は処理中に発動しないのか。
whileくんのことなんにも分かってなかったわ。
break完全に理解した。

# 完成
～～～紆余曲折～～～
<details><summary>こんな感じ</summary>

~~~Python:コード
class Character:  
  '''
  キャラクター(オブジェクト)のパラメーターだよ。敵味方共通で利用するよ
  '''
  def __init__(self, name, hp, power):  # とりあえず名前とHPと攻撃力入れる
    self.name = name
    self.hp = hp
    self.power = power
  def attack(self):   # passって書いてみたかった
    pass

def battle(p_n, p_hp, p_atk, e_n, e_hp, e_atk): # 戦闘部分を演算してくれ
  p_rhp = p_hp      # 残HPを管理する変数を用意するよ
  e_rhp = e_hp
  print('---battle start---')
  while e_rhp > 0:  # まずは敵を倒したら勝ちってことにするよ
    print(f'{p_n}の攻撃')
    print(f'{e_n}に{p_atk}のダメージ！')
    e_rhp = e_rhp - p_atk
    if e_rhp <= 0:  # 敵のHPがゼロになった時点で勝利宣言
      print(f'{p_n}の勝利!!')
      break         # ループ抜けるよ
    print(f'{e_n}の攻撃')
    print(f'{p_n}に{e_atk}のダメージ！')
    p_rhp = p_rhp - e_atk

def main(): # なんかPythonっぽいふんいき()にしてみる
  player = Character('ken', 35, 5)  # プレイヤーを生成、値を設定
  enemy = Character('mochi', 10, 1)  # 変数enemyを利用して、プレイヤーとは異なるインスタンスを生成
  print(f'{player.name}は旅にでた')
  print(f'{enemy.name}があらわれた！')
  battle(player.name, player.hp, player.power, enemy.name, enemy.hp, enemy.power)

if __name__ == '__main__':  # 動け（祈り）
  main()
~~~
~~~:実行結果
kenは旅にでた。
mochiがあらわれた！
---battle start---
kenの攻撃
mochiに5のダメージ！
mochiの攻撃
kenに1のダメージ！
kenの攻撃
mochiに5のダメージ！
kenの勝利!!
~~~
</details>

# おわり
PTメンバー増やすとかレベルアップさせるとか、
敵キャラのドロップ設定すること考えたらやっぱりクラスは2個あってもいいのかも。
インスタンス生成の理解のためには良かった。
次は攻撃力をランダムにしたり残HPを反映して2回目以降の戦闘発生させたりlose分岐作ったりしたい。

ここまで読んでくれてありがとうございました！