Pythonでじゃんけんゲームを作ってみた

# はじめに
何気なくQiitaのタイムラインを見ているとこんな記事を見かけました。

https://qiita.com/JK447/items/72239cc9c626fcfd8563

これを見た私は「pythonに置き換えて作成してみるか―」と思いました。では作成していきます。

# ゲーム仕様


#### 1. **プレイヤーの登録**
- ゲーム開始時に、プレイヤーは自分の名前を入力します

#### 2. **手の選択**
- プレイヤーは次の選択肢からじゃんけんの手を入力します：
  ```
  1 → グー
  2 → チョキ
  3 → パー
  ```
- 入力が 1〜3 の範囲外だった場合は再入力が求められます

#### 3. **コンピュータの手**
- コンピュータの手は `1〜3` の間でランダムに決まります

#### 4. **勝敗のルール**
以下のルールで勝敗を判定します：

| プレイヤー | コンピュータ | 勝敗     |
|------------|--------------|----------|
| グー       | チョキ       | プレイヤーの勝ち |
| チョキ     | パー         | プレイヤーの勝ち |
| パー       | グー         | プレイヤーの勝ち |
| 同じ手     | 同じ手       | あいこ（引き分け） |
| その他     |              | コンピュータの勝ち |

#### 5. **勝敗表示**
- プレイヤーとコンピュータの出した手を表示
- 勝ち・負け・引き分けを表示

#### 6. **再戦確認**
- 勝敗がついた後は、以下の質問を表示：
  ```
  もう一度プレイしますか？ (y/n)
  ```
- 「y」または「yes」なら続行、「n」または「no」なら終了
- 引き分け（あいこ）の場合は、自動的に再試合

#### 7. **終了**
- プレイヤーが「n」または「no」と答えたら、
  ```
  ゲームを終了します。ありがとうございました！
  ```
  と表示して終了します。

---

### 🔧 クラス構成

#### `Player` クラス
- プレイヤーの名前と手を持つ
- 自分の手を文字列で表示する `__str__` メソッドあり

#### `Game` クラス
- ゲーム進行全体を管理
- 定数（ROCK、SCISSORS、PAPER など）を持ち、勝敗判定や再戦処理を実装

---
# 実際のコード
```python:janken_game.py
import random

class Player:
    def __init__(self, name: str, hand: int):
        self.name = name
        self.hand = hand

    def __str__(self):
        return f"{self.name} は {self.hand_to_string()} を選びました"

    def hand_to_string(self):
        return {
            1: "グー",
            2: "チョキ",
            3: "パー"
        }.get(self.hand, "不明な手")

class Game:
    ROCK = 1
    SCISSORS = 2
    PAPER = 3

    DRAW = -1
    COMPUTER_WIN = 0
    PLAYER_WIN = 1

    def start(self):
        print("===== じゃんけんゲームへようこそ！ =====")
        continue_game = True

        while continue_game:
            player = self.create_player()
            if player:
                result = self.play_round(player.hand)
                if result == self.DRAW:
                    print("もう一度じゃんけんします...")
                    continue
                elif result == self.COMPUTER_WIN:
                    print("もう一度挑戦しますか？ (y/n)")
                    continue_game = self.ask_yes_no()
                else:
                    print("おめでとうございます！もう一度プレイしますか？ (y/n)")
                    continue_game = self.ask_yes_no()
            else:
                print("プレイヤーの作成に失敗しました。")
                continue_game = False

        print("ゲームを終了します。ありがとうございました！")

    def create_player(self):
        try:
            name = input("名前を入力してください: ").strip()
            hand = self.get_valid_hand_input()
            if hand == -1:
                return None
            return Player(name, hand)
        except Exception as e:
            print(f"エラーが発生しました: {e}")
            return None

    def get_valid_hand_input(self):
        while True:
            print("手を選んでください:")
            print("1: グー")
            print("2: チョキ")
            print("3: パー")
            hand_input = input("選択 (1-3): ").strip()

            try:
                hand = int(hand_input)
                if hand in [1, 2, 3]:
                    return hand
                else:
                    print("1から3の間の数字を入力してください。")
            except ValueError:
                print("数字を入力してください。")

    def play_round(self, player_hand):
        computer_hand = self.generate_computer_hand()
        print("コンピュータの手:", self.hand_to_string(computer_hand))
        print("あなたの手:", self.hand_to_string(player_hand))

        if player_hand == computer_hand:
            print("あいこです")
            return self.DRAW
        elif (player_hand == self.ROCK and computer_hand == self.PAPER) or \
             (player_hand == self.SCISSORS and computer_hand == self.ROCK) or \
             (player_hand == self.PAPER and computer_hand == self.SCISSORS):
            print("コンピュータの勝ちです")
            return self.COMPUTER_WIN
        else:
            print("あなたの勝ちです")
            return self.PLAYER_WIN

    def ask_yes_no(self):
        while True:
            response = input().strip().lower()
            if response in ["y", "yes"]:
                return True
            elif response in ["n", "no"]:
                return False
            else:
                print("'y'（はい）または 'n'（いいえ）を入力してください: ")

    def hand_to_string(self, hand):
        return {
            self.ROCK: "グー",
            self.SCISSORS: "チョキ",
            self.PAPER: "パー"
        }.get(hand, "不明な手")

    def generate_computer_hand(self):
        return random.randint(1, 3)

if __name__ == "__main__":
    game = Game()
    game.start()

```

# まとめ
今回はpythonでじゃんけんゲームを作成してみました。是非遊んでみてください。

# 参考文献

https://qiita.com/JK447/items/72239cc9c626fcfd8563