【Python】僕と僕たちの青春劇。Part. 3

前回までの青春劇。

前回の記事では、各キャラクターの特徴をよく表現するように補正をかけるようにプログラムを変更していきました。


もし、前回の記事を見られていない方は以下からぜひご参照ください。

動作環境については、以前の記事に書いてありますので
気になった方は、以下からぜひご参照ください。

今回はいよいよジュースを掛けた、血で血を洗う骨肉の争いが始まります。


///

0. 前回のおさらい

前回までのプログラムは以下の通りです。

import random

class Character:
  def __init__(self):
    self.score = Score()


class Score:
  def __init__(self):
    self.reset_japanese()
    self.reset_math()
    self.reset_english()
    self.reset_social()
    self.reset_science()

  def reset_japanese(self, min=0, max=100):
    self.japanese = random.randint(min, max)

  def reset_math(self, min=0, max=100):
    self.math = random.randint(min, max)

  def reset_english(self, min=0, max=100):
    self.english = random.randint(min, max)

  def reset_social(self, min=0, max=100):
    self.social = random.randint(min, max)

  def reset_science(self, min=0, max=100):
    self.science = random.randint(min, max)

  def print_score(self):
    print("国語:{}".format(self.japanese))
    print("数学:{}".format(self.math))
    print("英語:{}".format(self.english))
    print("社会:{}".format(self.social))
    print("理科:{}".format(self.science))

K = Character()
K.score.japanese = 68
K.score.math     = 60
K.score.english  = 47
K.score.social   = 80
K.score.science  = 62

M = Character()
M.score.reset_social(max = K.score.social-1)

R = Character()
R.score.reset_english(min = K.score.english+1)

こちらにまず戦いの本体となるbattle関数を作るところから始めていきましょう!


1. 勝負する環境を整える

では、最初に勝負する本体となるbattle関数を追加してみます。

中身はともかく、一旦関数の置き場所を決めてしまいましょう。

import random

class Character:
  def __init__(self):
    self.score = Score()


class Score:
  def __init__(self):
    self.reset_japanese()
    self.reset_math()
    self.reset_english()
    self.reset_social()
    self.reset_science()

  def reset_japanese(self, min=0, max=100):
    self.japanese = random.randint(min, max)

  def reset_math(self, min=0, max=100):
    self.math = random.randint(min, max)

  def reset_english(self, min=0, max=100):
    self.english = random.randint(min, max)

  def reset_social(self, min=0, max=100):
    self.social = random.randint(min, max)

  def reset_science(self, min=0, max=100):
    self.science = random.randint(min, max)

  def print_score(self):
    print("国語:{}".format(self.japanese))
    print("数学:{}".format(self.math))
    print("英語:{}".format(self.english))
    print("社会:{}".format(self.social))
    print("理科:{}".format(self.science))

# バトルフィールドを展開
def battle():
  return 1

K = Character()
K.score.japanese = 68
K.score.math     = 60
K.score.english  = 47
K.score.social   = 80
K.score.science  = 62

M = Character()
M.score.reset_social(max = K.score.social-1)

R = Character()
R.score.reset_english(min = K.score.english+1)
 
result = battle()
print(result)

ここから、K, M, Rの戦いを描いていきます!


2. 勝負のルールを追加する

battle関数には、バトルするための情報が不可欠です。
今回の場合は、各キャラクターのテストの点数の情報が必要です。

テストの点数の情報をbattle関数に渡せるように、引数を設定しましょう。

def battle(K, M, R):
  return 1

できれば、何も値が渡って来なかったとしても動くようにしておいた方が良いでしょう。

もし、この状態で値が渡って来ないと、後で困ったことになるのですが
何が困るのかが分からない方ほど、このまま読み進めて頂ければと思います。

一先ず、引数にデフォルト値を設定します。
一言付け加えておくならば、このデフォルト値は設定しなくてもプログラムは動きます。なので、分かっている方は設定しなくてもOKです。

def battle(K=Character(), M=Character(), R=Character()):
  return 1

ここで返り値のことも考えます。

返り値は、バトルの結果が一目で分かるようにしたいはずです。
ここで、一度バトルのルールをおさらいします。

今回のルールは
・KとRが全科目の中の最高点、Mが全ての科目の平均点
・3つの値の比較で、最も点数が高かった人が勝者になる。

と言うことは

3つの値の高低が一発で分かって、かつ誰がその点数を取ったのかが分かるような返り値が望まれます。

そのようなことを一つの形で表せるような、そんなものはあるのでしょうか?


答えはあるです。


今回利用するのは辞書型になります。

具体的に使ってみましょう。

def battle(K=Character(), M=Character(), R=Character()):
  score_dict = {'K': "Kの最高点", 'M': "Mの平均点", 'R': "Rの最高点"}
  return 1

このように表すことができます。

さて、ここからKとRの最高点、Mの平均点を計算するのですが
battle関数の中で計算をするのでしょうか?

今までテストの点数関連は、全てScoreクラスが担ってくれていました。

できれば、最高点や平均点の計算もScoreクラスがやってくれた方が
概念がブレなくてスッキリする気がするので、Scoreクラスで計算するようにプログラムを変更します。

class Score:
  def __init__(self):
    self.reset_japanese()
    self.reset_math()
    self.reset_english()
    self.reset_social()
    self.reset_science()

  def reset_japanese(self, min=0, max=100):
    self.japanese = random.randint(min, max)

  def reset_math(self, min=0, max=100):
    self.math = random.randint(min, max)

  def reset_english(self, min=0, max=100):
    self.english = random.randint(min, max)

  def reset_social(self, min=0, max=100):
    self.social = random.randint(min, max)

  def reset_science(self, min=0, max=100):
    self.science = random.randint(min, max)

  def print_score(self):
    print("国語:{}".format(self.japanese))
    print("数学:{}".format(self.math))
    print("英語:{}".format(self.english))
    print("社会:{}".format(self.social))
    print("理科:{}".format(self.science))
 
  # 最高得点を計算
  def get_max_score(self):
    score_list = [self.japanese,
                  self.math,
                  self.english,
                  self.social,
                  self.science]
    # リストの中で最大の値を抽出して返す
    return max(score_list)
 
  # 平均点を計算
  def get_ave_score(self):
    score_list = [self.japanese,
                  self.math,
                  self.english,
                  self.social,
                  self.science]
    # リストの中身を全て足した値をリストの長さで割る
    return sum(score_list)/len(score_list)


では、battle関数内でそれぞれの値を取得していきましょう。

def battle(K=Character(), M=Character(), R=Character()):
  score_dict = {'K': K.score.get_max_score(),
                'M': M.score.get_ave_score(),
                'R': R.score.get_max_score()}
  # 戻り値をscore_dictにしてみましょう
  return score_dict


さて、ここまでで一度プログラム全体がどのようになるかを確認しましょう。

import random

class Character:
 def __init__(self):
   self.score = Score()


class Score:
 def __init__(self):
   self.reset_japanese()
   self.reset_math()
   self.reset_english()
   self.reset_social()
   self.reset_science()

 def reset_japanese(self, min=0, max=100):
   self.japanese = random.randint(min, max)

 def reset_math(self, min=0, max=100):
   self.math = random.randint(min, max)

 def reset_english(self, min=0, max=100):
   self.english = random.randint(min, max)

 def reset_social(self, min=0, max=100):
   self.social = random.randint(min, max)

 def reset_science(self, min=0, max=100):
   self.science = random.randint(min, max)

 def print_score(self):
   print("国語:{}".format(self.japanese))
   print("数学:{}".format(self.math))
   print("英語:{}".format(self.english))
   print("社会:{}".format(self.social))
   print("理科:{}".format(self.science))

 def get_max_score(self):
   score_list = [self.japanese, 
                 self.math, 
                 self.english, 
                 self.social, 
                 self.science]
   return max(score_list)

 def get_ave_score(self):
   score_list = [self.japanese, 
                 self.math, 
                 self.english, 
                 self.social, 
                 self.science]
   return sum(score_list)/len(score_list)

def battle(K=Character(), M=Character(), R=Character()):
   score_dict = {'K': K.score.get_max_score(),
                 'M': M.score.get_ave_score(),
                 'R': R.score.get_max_score()}
   
   return score_dict

K = Character()
K.score.japanese = 68
K.score.math     = 60
K.score.english  = 47
K.score.social   = 80
K.score.science  = 62

M = Character()
M.score.reset_social(max = K.score.social-1)

R = Character()
R.score.reset_english(min = K.score.english+1)

result = battle()
print(result)

実行結果

{'K': 80, 'M': 29.2, 'R': 97}

なんとなく、イメージ通りの結果になったのではないでしょうか?

さて、せっかく引数の値を設定したのに

result = battle()

関数を使っているところでは、引数を設定していません。

ここで、今までに作って来たK, M, Rを渡して直接対決を実現しましょう!

result = battle(K, M, R)


3. さあ、頂上決定戦です。

import random

class Character:
 def __init__(self):
   self.score = Score()


class Score:
 def __init__(self):
   self.reset_japanese()
   self.reset_math()
   self.reset_english()
   self.reset_social()
   self.reset_science()

 def reset_japanese(self, min=0, max=100):
   self.japanese = random.randint(min, max)

 def reset_math(self, min=0, max=100):
   self.math = random.randint(min, max)

 def reset_english(self, min=0, max=100):
   self.english = random.randint(min, max)

 def reset_social(self, min=0, max=100):
   self.social = random.randint(min, max)

 def reset_science(self, min=0, max=100):
   self.science = random.randint(min, max)

 def print_score(self):
   print("国語:{}".format(self.japanese))
   print("数学:{}".format(self.math))
   print("英語:{}".format(self.english))
   print("社会:{}".format(self.social))
   print("理科:{}".format(self.science))

 def get_max_score(self):
   score_list = [self.japanese, 
                 self.math, 
                 self.english, 
                 self.social, 
                 self.science]
   return max(score_list)

 def get_ave_score(self):
   score_list = [self.japanese, 
                 self.math, 
                 self.english, 
                 self.social, 
                 self.science]
   return sum(score_list)/len(score_list)

def battle(K=Character(), M=Character(), R=Character()):
   score_dict = {'K': K.score.get_max_score(),
                 'M': M.score.get_ave_score(),
                 'R': R.score.get_max_score()}
   
   return score_dict

K = Character()
K.score.japanese = 68
K.score.math     = 60
K.score.english  = 47
K.score.social   = 80
K.score.science  = 62

M = Character()
M.score.reset_social(max = K.score.social-1)

R = Character()
R.score.reset_english(min = K.score.english+1)

result = battle(K, M, R)
print(result)

実行結果

{'K': 80, 'M': 33.6, 'R': 84}


///

"""

R「あーっはっはっはっ!どうだ!参ったか!」

K「ちくしょー!たった4点差じゃねぇか!こんなのノーカンだろ!」

R「ほう?男が事実を突きつけられて言い訳とは。見苦しい限りだ」

K「ぐっ、、、お、男に二言はねぇ。。。」

M「あーあ、負けちゃった(そもそも絶対勝てないから文句もないけどね)」

R「むっ、モトキのその余裕な顔は実に釈然としないが、勝負は勝負。しっかりジュースは頂くからな!」

M「分かってるよ。それと、おめでとう」

R「ふっふっふっ、いい景色だ。これがトップオブトップの眺めか」

K「井の中の蛙ってのはこういうことを言うんだろ?モトキ」

M「まあ、そうかもね」

R「おい!誰が両生類だ!いいか、ケンジもジュースおごりだからな!忘れるなよ?」

K「けっ、分かってるっての。ちくしょう」

"""

と言うわけで、この物語はりんねちゃんが制したようです。

中々モトキの点数はキャラクター設定よりも低くなったので、もう少し適切になるようにしても良いかもしれません。


工夫できる箇所はまだまだ多くあります。
・点数の決定箇所の見直し
・点数をバラすのではなくて、元からリストにしておく
・キャラクターごとの個性をCharacterクラスで設定できるようにする
・バトル結果を点数降順に直す

などが考えられるでしょうか?

それはまたどこか別の世界線で行おうと思います。


三部に渡るストーリーはいかがだったでしょうか?

プログラミングでも、こうやって物語を紡げるのです。
ぜひ、皆さんもプログラミングで物語を紡いでみてください。

それでは、お付き合い頂きありがとうございました。



では。

この記事が気に入ったらサポートをしてみませんか?