【再掲】リクエスト:じゃんけんゲームの作成
複数のコンピュータとじゃんけんをして、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回に渡って紹介してきましたので、今回でジャンケン実装は完了にしたいと思います。ゲームについてはオセロゲームの実装例も考えていますが、一旦別な方向にしてオープンデータを扱うリクエストにしていきたいと思います。
コメント