スレッドを使ってバトルロワイアルを作ろう
今回は前回作った戦闘シミュレーションを改造して、3人以上で戦うバトルロワイアルのプログラムを作りましょう。
実行イメージ
3人のプレイヤーが自動で自分以外の相手を攻撃して、最後までHP(ヒットポイント)が残っていた人が勝ちになります。
プレイヤーのパラメーターは、HP、攻撃力、敏捷性がランダムで設定されます。
ターン制ではないので、敏捷性の値が高ければ早く攻撃ができるようになり、場合によっては連続して攻撃します。
実行例
C:\>python battle2-1.py
戦士A HP[29] 攻撃力[12] 敏捷性[19]
戦士B HP[84] 攻撃力[ 9] 敏捷性[ 6]
戦士C HP[48] 攻撃力[ 6] 敏捷性[ 8]
戦士Aは戦士Bに14のダメージ
→ 戦士Bの残HP[70]
戦士Cは戦士Bに16のダメージ
→ 戦士Bの残HP[54]
戦士Bは戦士Aに14のダメージ
→ 戦士Aの残HP[15]
戦士Aは戦士Cに13のダメージ
→ 戦士Cの残HP[35]
戦士Cは戦士Aに14のダメージ
→ 戦士Aの残HP[1]
戦士Bは戦士Cに16のダメージ
→ 戦士Cの残HP[19]
戦士Aは戦士Cに16のダメージ
→ 戦士Cの残HP[3]
戦士Aは戦士Cに16のダメージ
→ 戦士Cの残HP[0]
戦士Bは戦士Aに14のダメージ
→ 戦士Aの残HP[0]
++ 戦士Bの勝利! ++
Pythonスクリプト
今回のPythonスクリプトは、以下のようになります。
前回との違いは、動いているスレッドからMainスレッドを除外した配列を作り、その配列の並びをシャッフルして攻撃する相手をランダムに選択するようにしています。
敏捷性が低いと自分が攻撃する間もなく、他の相手に攻撃されて終了することもあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
### インポート import time import random import threading ### 定数 PLAYER = ["戦士A","戦士B","戦士C"] # プレイヤー名 ############################ ### プレイヤークラス ############################ class Player(threading.Thread): ############################ ### 初期化メソッド ############################ def __init__(self, name): ### Threadクラスの初期化 threading.Thread.__init__(self) ### クラス変数設定 self.name = name # プレイヤー名 self.hp = random.randint(10, 99) # 体力 self.atk = random.randint( 1, 20) # 攻撃力 self.agi = random.randint( 1, 20) # 敏捷性 ### ステータスを表示 print("{:<4} HP[{:>2}] 攻撃力[{:>2}] 敏捷性[{:>2}]".format(self.name, self.hp, self.atk, self.agi)) ############################ ### 攻撃メソッド ############################ def run(self): ### 自分のHPが0になるまでループ while self.hp > 0: ### 次の攻撃まで待機 time.sleep(5 / (self.agi + random.randint(0, 10))) ### Main以外のスレッドを取得 enemies = [enemy for enemy in threading.enumerate()[1:]] ### 対象をシャッフル random.shuffle(enemies) ### 対象をループ for enemy in enemies: ### 自スレッドだったら飛ばす if enemy is threading.currentThread(): continue ### 自分または相手のHPが0なら終了 if self.hp == 0 or enemy.hp == 0: break ### 相手プレイヤーのHPを減算 damage = self.atk + random.randint(0, 10) enemy.hp -= damage ### 相手プレイヤーのHPが0未満なら0にする if enemy.hp < 0: enemy.hp = 0 ### 画面表示 print("{}は{}に{}のダメージ".format(self.name, enemy.name, damage)) print(" → {}の残HP[{}]".format(enemy.name, enemy.hp)) ### 一人倒したら一旦終了 break ### 相手がいなければ終了 if threading.active_count()-1 == 1: print("++ {}の勝利! ++".format(self.name)) break ############################ ### メイン関数 ############################ def main(): ### プレイヤーを作成 players = [Player(name) for name in PLAYER] ### スレッドを開始 for player in players: player.start() ############################ ### メイン関数呼び出し ############################ if __name__ == "__main__": ### 処理開始 main() |