仕事で math の関数を使い、以下の記事を書きました。
[Python] math : sqrt / pow / ceil / floor / fabs
[Python] math : factorial / log / gcd / degrees / radians
[Python] math : isqrt / prod / comb / perm / fsum
せっかくここまで書いたので、これらの関数を使って、バトルゲームを作ることに。(全部は使わないけど)
要件
- プレイヤーがモンスターと戦う
- プレイヤーは数学を駆使して攻撃をする
- モンスターは
sin
を使って攻撃をしてくる - どんな数字がダメージの計算に使われるかは、ランダムである
- HPが先に 0 になった方が負け
ゲームの概要
プレイヤーが数学を武器にしてモンスターと戦うバトルゲーム。
プレイヤーは4種類の数学的攻撃を選択し、モンスターにダメージを与える。モンスターも反撃してくる。先に相手のHPを0にした方が勝ち。
ゲームの流れ
- 初期化: プレイヤーとモンスターのHPが設定される
-
プレイヤーのターン:
- プレイヤーの現在のHPとモンスターのHPが表示される
- 4種類の攻撃(平方根、階乗、組み合わせ、べき乗)から一つを選択する
- 選択した攻撃に基づいてダメージが計算され、モンスターのHPが減少
-
モンスターのターン:
- モンスターが
sin
関数に基づいた攻撃を行い、プレイヤーにダメージを与える
- モンスターが
- 勝敗判定: プレイヤーまたはモンスターのHPが0以下になると、ゲームが終了
各攻撃の詳細
-
平方根攻撃 (sqrt):
ランダムな数値の平方根を計算し、その値がダメージになる -
階乗攻撃 (factorial):
ランダムな小さい整数の階乗を計算し、その値がダメージになる -
組み合わせ攻撃 (comb):
ランダムなn
とk
を選び、nCk
(n 個から k 個を選ぶ組み合わせの数) を計算 -
べき乗攻撃 (pow):
ランダムな底と指数を選び、べき乗を計算 -
モンスターの攻撃:
ランダムな角度(度数法)と防御値を選び、sin(角度) * 防御値
を計算
コード
import math
import random
import time
def math_battle():
"""数学バトルゲーム"""
player_hp = 50
monster_hp = 70
print("\n数学バトル開始!")
time.sleep(1)
while player_hp > 0 and monster_hp > 0:
print(f"\n--- プレイヤーのターン ---")
print(f"プレイヤーHP: {player_hp}")
print(f"モンスターHP: {monster_hp}")
time.sleep(1)
# プレイヤーの攻撃選択
print("\n攻撃を選択してください:")
print("1: 平方根攻撃 (sqrt)")
print("2: 階乗攻撃 (factorial)")
print("3: 組み合わせ攻撃 (comb)")
print("4: べき乗攻撃 (pow)")
while True:
try:
choice = int(input("> "))
if 1 <= choice <= 4:
break
else:
print("無効な入力です。1〜4の数字を入力してください。")
time.sleep(1)
except ValueError:
print("無効な入力です。数字を入力してください。")
time.sleep(1)
# 攻撃の実行
if choice == 1: # 平方根攻撃
base = random.randint(100, 400)
damage = int(math.sqrt(base))
print(f"平方根攻撃!√{base} = {damage} のダメージ!")
time.sleep(1)
print("豆知識:平方根は、2乗すると元の数になる値のこと。古代バビロニアの時代から研究されているらしい。。")
time.sleep(1)
elif choice == 2: # 階乗攻撃
num = random.randint(3, 5)
damage = math.factorial(num)
print(f"階乗攻撃!{num}! = {damage} のダメージ!")
time.sleep(1)
print("豆知識:階乗は、1からその数までのすべての整数を掛け合わせたもの。順列や組み合わせの計算でよく使われるとか。。")
time.sleep(1)
elif choice == 3: # 組み合わせ攻撃
n = random.randint(5, 10)
k = random.randint(1, min(n, 4)) # kはnを超えないようにする
damage = math.comb(n, k)
print(f"組み合わせ攻撃!comb({n}, {k}) = {damage} のダメージ!")
time.sleep(1)
print(f"豆知識:{n}個の中から{k}個を選ぶ組み合わせの数は、nCk = n! / (k! * (n-k)!) で計算できる。確率や統計で重要らしい。。")
time.sleep(1)
elif choice == 4: # べき乗攻撃
base = random.randint(2, 4)
exponent = random.randint(2, 3)
damage = int(math.pow(base, exponent))
print(f"べき乗攻撃!{base}^{exponent} = {damage} のダメージ!")
time.sleep(1)
print("豆知識:べき乗は、同じ数を繰り返し掛け合わせる演算。指数法則を理解すると、複雑な計算も簡単にできると言われている。。")
time.sleep(1)
monster_hp -= damage
# モンスターの攻撃
if monster_hp > 0:
defense_value = random.randint(10, 30)
degrees = random.randint(0, 90)
radians = math.radians(degrees)
monster_damage = int(math.sin(radians) * defense_value)
print(f"\nモンスターの攻撃!sin({degrees}°) * {defense_value} = {monster_damage} のダメージ!")
time.sleep(1)
player_hp -= monster_damage
if player_hp <= 0:
print("\n敗北…")
else:
print("\n勝利!")
if __name__ == "__main__":
math_battle()
実行結果
$ python main.py
数学バトル開始!
--- プレイヤーのターン ---
プレイヤーHP: 50
モンスターHP: 70
攻撃を選択してください:
1: 平方根攻撃 (sqrt)
2: 階乗攻撃 (factorial)
3: 組み合わせ攻撃 (comb)
4: べき乗攻撃 (pow)
> 1
平方根攻撃!√317 = 17 のダメージ!
豆知識:平方根は、2乗すると元の数になる値のこと。古代バビロニアの時代から研究されているらしい。。
モンスターの攻撃!sin(23°) * 18 = 7 のダメージ!
--- プレイヤーのターン ---
プレイヤーHP: 43
モンスターHP: 53
攻撃を選択してください:
1: 平方根攻撃 (sqrt)
2: 階乗攻撃 (factorial)
3: 組み合わせ攻撃 (comb)
4: べき乗攻撃 (pow)
> 2
階乗攻撃!4! = 24 のダメージ!
豆知識:階乗は、1からその数までのすべての整数を掛け合わせたもの。順列や組み合わせの計算でよく使われるとか。。
モンスターの攻撃!sin(67°) * 29 = 26 のダメージ!
--- プレイヤーのターン ---
プレイヤーHP: 17
モンスターHP: 29
攻撃を選択してください:
1: 平方根攻撃 (sqrt)
2: 階乗攻撃 (factorial)
3: 組み合わせ攻撃 (comb)
4: べき乗攻撃 (pow)
> 3
組み合わせ攻撃!comb(7, 2) = 21 のダメージ!
豆知識:7個の中から2個を選ぶ組み合わせの数は、nCk = n! / (k! * (n-k)!) で計算できる。確率や統計で重要らしい。。
モンスターの攻撃!sin(14°) * 23 = 5 のダメージ!
--- プレイヤーのターン ---
プレイヤーHP: 12
モンスターHP: 8
攻撃を選択してください:
1: 平方根攻撃 (sqrt)
2: 階乗攻撃 (factorial)
3: 組み合わせ攻撃 (comb)
4: べき乗攻撃 (pow)
> 4
べき乗攻撃!3^3 = 27 のダメージ!
豆知識:べき乗は、同じ数を繰り返し掛け合わせる演算。指数法則を理解すると、複雑な計算も簡単にできると言われている。。
勝利!
無事に勝利しました!
まとめ
今回は、mathの関数を使って、バトルゲームを作ってみました。
こうやって数学の勉強をするのも楽しいかもしれませんね。
また何か思いついたら、作ってみます