Java じゃんけん　初心者用

# Java練習問題：じゃんけんゲームを作ろう（初級）
### ■ 問題文
以下の仕様に従って、コンピュータとプレイヤーがじゃんけんで対戦できるプログラムを作成しなさい。

### ■ 仕様
プレイヤーの名前をキーボードから入力させること。
プレイヤーは次のいずれかの手を入力する：

- 1 → グー
- 2 → チョキ
- 3 → パー

入力が「1〜3」の範囲でない場合は、再入力させること。

コンピュータの手はランダムに生成すること。

プレイヤーとコンピュータの手を表示し、勝敗を以下のルールで判定する：

- *グーはチョキに勝つ*
- チョキはパーに勝つ
- パーはグーに勝つ
- 同じ手は「あいこ」

勝敗の結果を画面に表示すること。

勝敗が決まったら「もう一度プレイしますか？（y/n）」と尋ね、y であればもう一度プレイ、n で終了すること。

プレイヤーの情報は Player クラス（または record）を使って保持すること。

ゲームのロジックは Game クラスにまとめること。



```java
package org.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;

public class Game {
    private static final int ROCK = 1;
    private static final int SCISSORS = 2;
    private static final int PAPER = 3;
    
    private static final int DRAW = -1;
    private static final int COMPUTER_WIN = 0;
    private static final int PLAYER_WIN = 1;
    
    private final BufferedReader reader;
    private final Random random;
    
    public Game() {
        this.reader = new BufferedReader(new InputStreamReader(System.in));
        this.random = new Random();
    }
    
    public static void main(String[] args) {
        Game game = new Game();
        game.start();
    }
    
    public void start() {
        boolean continueGame = true;
        
        System.out.println("===== じゃんけんゲームへようこそ！ =====");
        
        while (continueGame) {
            Player player = createPlayer();
            
            if (player != null) {
                int result = playRound(player.hand());
                
                if (result == DRAW) {
                    System.out.println("もう一度じゃんけんします...");
                    continue;
                } else if (result == COMPUTER_WIN) {
                    System.out.println("もう一度挑戦しますか？ (y/n)");
                    continueGame = askYesNo();
                } else {  // プレイヤーの勝ち
                    System.out.println("おめでとうございます！もう一度プレイしますか？ (y/n)");
                    continueGame = askYesNo();
                }
            } else {
                System.out.println("プレイヤーの作成に失敗しました。");
                continueGame = false;
            }
        }
        
        closeResources();
        System.out.println("ゲームを終了します。ありがとうございました！");
    }

    private Player createPlayer() {
        try {
            System.out.print("名前を入力してください: ");
            String name = reader.readLine();
            
            int hand = getValidHandInput();
            if (hand == -1) {
                return null; // 入力エラー
            }
            
            return new Player(name, hand);
        } catch (IOException e) {
            System.out.println("入力エラー: " + e.getMessage());
            return null;
        } catch (Exception e) {
            System.out.println("予期しないエラー: " + e.getMessage());
            return null;
        }
    }
    
    private int getValidHandInput() throws IOException {
        while (true) {
            System.out.println("手を選んでください:");
            System.out.println("1: グー");
            System.out.println("2: チョキ");
            System.out.println("3: パー");
            System.out.print("選択 (1-3): ");
            
            String handInput = reader.readLine();
            
            try {
                int hand = Integer.parseInt(handInput);
                if (hand >= 1 && hand <= 3) {
                    return hand;
                } else {
                    System.out.println("1から3の間の数字を入力してください。");
                }
            } catch (NumberFormatException e) {
                System.out.println("数字の形式が正しくありません。もう一度お試しください。");
            }
        }
    }
    
    public int playRound(int playerHand) {
        int computerHand = generateComputerHand();
        
        System.out.println("コンピュータの手: " + handToString(computerHand));
        System.out.println("あなたの手: " + handToString(playerHand));
        
        // 勝敗判定
        if (playerHand == computerHand) {
            System.out.println("あいこです");
            return DRAW;
        } else if ((playerHand == ROCK && computerHand == PAPER) || 
                   (playerHand == SCISSORS && computerHand == ROCK) || 
                   (playerHand == PAPER && computerHand == SCISSORS)) {
            System.out.println("コンピュータの勝ちです");
            return COMPUTER_WIN;
        } else {
            System.out.println("あなたの勝ちです");
            return PLAYER_WIN;
        }
    }
    
    private boolean askYesNo() {
        try {
            while (true) {
                String response = reader.readLine().trim().toLowerCase();
                if (response.equals("y") || response.equals("yes")) {
                    return true;
                } else if (response.equals("n") || response.equals("no")) {
                    return false;
                } else {
                    System.out.print("'y'（はい）または 'n'（いいえ）を入力してください: ");
                }
            }
        } catch (Exception e) {
            System.out.println("入力エラー: " + e.getMessage());
            return false;
        }
    }

    private String handToString(int hand) {
        switch (hand) {
            case ROCK:
                return "グー";
            case SCISSORS:
                return "チョキ";
            case PAPER:
                return "パー";
            default:
                return "不明な手";
        }
    }

    public int generateComputerHand() {
        return random.nextInt(3) + 1; // 1から3の乱数を生成
    }
    
    private void closeResources() {
        try {
            reader.close();
        } catch (IOException e) {
            System.out.println("リソースのクローズに失敗しました: " + e.getMessage());
        }
    }
}
```

```java
package org.example;

public record Player(String name, int hand) {
    @Override
    public String toString() {
        return name + " は " + handToString() + " を選びました";
    }
    
    private String handToString() {
        return switch (hand) {
            case 1 -> "グー";
            case 2 -> "チョキ";
            case 3 -> "パー";
            default -> "不明な手";
        };
    }
}
```