【再掲】リクエスト:じゃんけんゲームの作成
複数のコンピュータとじゃんけんをして、1人の勝者を決めるプログラムを作成してください。
想定外の入力を考慮し、正しく動作するようにしてください。
レベル3:複数のコンピュータとの勝負(異常入力への対応)
参加人数が複数のジャンケンゲームを実装してください。
プレイヤーは1人で残りはコンピュータ(CPU)とします。
最終的に1人の勝者が決まるまでジャンケンを続け、勝者の名前を表示するようにしてください。
想定外の入力があっても問題なく動作するようにしてください。
実装例
import numpy as np N_HAND = 3 # じゃんけんの手の種類 ROCK = 0 SCISSORS = 1 PAPER = 2 WIN = 0 LOSE = 1 AIKO = 2 class Player(object): """ 参加者(Player、CPU)を作成するクラス Attributes: hand (int): じゃんけんの手(グー(0)、チョキ(1)、パー(2)) name (char): プレイヤーの名前 cpu (Bool): CPUか否か survive (Bool): ゲームに残っているか。 """ def __init__(self, name='cpu', cpu=True): self.hand = np.random.randint(N_HAND) self.name = name self.cpu = cpu self.survive = True def set_hand(self, hand=None): """ じゃんけんの手を決める。 Args: hand (int): じゃんけんの手(グー(0)、チョキ(1)、パー(2)) Returns: None """ if hand is None: self.hand = np.random.randint(N_HAND) else: # TODO: 例外処理 self.hand = hand def get_hand(self): return self.hand def set_survive(self, survive): self.survive = survive def get_survive(self): return self.survive def get_name(self): return self.name def cnt_survive_player(players): """ 残っているplayer数をカウントする Args: players (list): Playerオブジェクト格納したリスト Return: cnt (int): 勝ち残っている人数 """ cnt = 0 for player in players: if player.get_survive(): cnt += 1 return cnt def get_win_lose(hands): """ あいこ以外のジャンケン判定 0, 1 : 0 win 0, 2 : 2 win 1,2 : 1 win 1, 0 : 0 win 結論:一つ上の数字(mod 3)には勝てる Args: hands (set): 全Playerの手の集合。 Return: win (int): 勝利した手 lose (int): 負けた手 """ sum_hands = sum(hands) % 3 if sum_hands == 0: # SCISSORS and PAPER win = SCISSORS lose = PAPER elif sum_hands == 1: # ROCK and SCISSORS win = ROCK lose = SCISSORS elif sum_hands == 2: # Rock and PAPER win = PAPER lose = ROCK return win, lose def judge_janken_v2(players): """ ジャンケンの判定を行い残っている人数を返す。 Args: players (list): Playerオブジェクト格納したリスト Return: 勝ち残っているplayerの人数 """ # 重複している手をまとめる hands = [] for player in players: if player.get_survive(): hands.append(player.get_hand()) hands = set(hands) if (len(hands) == 3) or (len(hands) == 1): # あいこの場合 return cnt_survive_player(players) else: win_hand, lose_hand = get_win_lose(hands) for player in players: if player.get_survive(): hand = player.get_hand() if hand == lose_hand: print(f"{player.get_name()}は負けました。") player.set_survive(False) # 敗退 return cnt_survive_player(players) def game_start(): """ じゃんけんを開始するメイン関数 """ print("じゃんけんをします") while True: try: n_player = int(input("CPUの人数を入力してください: ")) except ValueError as e: print(f'Value Error: {e.args}') print('数字を入力してください') print('') continue break n_survive_player = n_player players = [] # playerインスタンスの作成 players.append(Player(name='Taro', cpu=False)) # cpuインスタンスの作成 for i in range(n_player): players.append(Player(f'cpu{i+1}')) i = 0 while n_survive_player > 1: # 勝ち残りが1人になるまで繰り返す i += 1 print(f'{i}回戦目') # cpus_hand = {} for player in players: if player.get_survive() == False: continue if player.cpu == False: while True: try: print("あなたの手は? (0:グー、1:チョキ、2:パー)") my_hand = int(input()) print('') except ValueError as e: print(f'Value Error: {e.args}') print('数字を入力してください') continue if my_hand in [ROCK, SCISSORS, PAPER]: break else: print('0:グー、1:チョキ、2:パーのいずれかを入力してください') player.set_hand(my_hand) else: player.set_hand() print(f'{player.name}の手: {player.get_hand()}') # ジャンケンの勝敗判定 n_survive_player = judge_janken_v2(players) # 勝者を表示 for player in players: if player.get_survive(): winner = player.get_name() print(f'優勝は「{winner}」です') if __name__ == "__main__": game_start()
今回のポイント
- 141行目〜149行目:プレイヤー人数に対する例外処理
- 数字以外が入力された場合にメッセージを出して、再度入力を求めるようにしています。
- 例外処理はTry, Except構文を使用しています。Try, Except構文については以下のリンクが分かりやすかったです。
- 参考リンク:[Python入門] 例外と例外処理の基礎
- 172行目〜184行目:ジャンケンの手に対する例外処理
- プレイヤー人数に対する例外処理同様に、数字ではなかった場合の処理を記載し、加えてジャンケンの手ではない場合に再度入力を求めるようにしています。
終わりに
コードを紹介しましたが、実装例と書いているようにあくまで一例です。
今回のコードはGitHubにも上げていきますので、みなさんの実装例も紹介してもらえると幸いです。
余談
ジャンケンゲームの実装例を3回に渡って紹介してきましたので、今回でジャンケン実装は完了にしたいと思います。ゲームについてはオセロゲームの実装例も考えていますが、一旦別な方向にしてオープンデータを扱うリクエストにしていきたいと思います。
コメント