【Java】じゃんけんアプリをつくろう⑤～3人でじゃんけん～

前回は、3勝した方が勝ちというじゃんけんアプリをつくりました。今回は3人でじゃんけんをした場合のじゃんけんアプリをつくってみましょう。前回とは違って、結果判定の部分がかなり難しいです。

# じゃんけんアプリをつくろう！
:::note info
問題：「じゃんけんポン！と標準出力される。ユーザがコンソールにじゃんけんの手（0,1,2）を入力すると、じゃんけんの結果（ユーザの手、PCの手、ユーザの勝ち負けあいこ）が標準出力されるプログラムをJavaで記載せよ。」
:::

:::note info
条件：  
・ユーザーとCP×2の3人のじゃんけんであること
・PCの手はランダムであること
・PC1とPC2は別の手を出すこと
・じゃんけんの手は次のように数字で扱うこと グー：0,チョキ：1,パー：2
・0,1,2以外の数値が入力された場合は、「0,1,2のどれかの数字を入力してください。」とメッセージを表示し、じゃんけんの手を再入力できるようにすること
:::

# 解答例
解答例を用意しましたので、見ていきましょう。

```java:Janken3player.java
package com.example.demo.controller;

import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;

public class Janken3player {

	public static void main(String[] args) {
		
		// メッセージの表示
		System.out.println("じゃんけんポン！(グー：0，チョキ：1、パー：2　どれかの数字をいれてください。)");

		// ユーザーの手を読み取る
		Scanner stdin = new Scanner(System.in);
		int userHands = stdin.nextInt();
		
        // 入力チェック
        while (userHands < 0 || userHands > 2) {
            System.out.println("グー：0，チョキ：1、パー：2　どれかの数字をいれてください。");
            userHands = stdin.nextInt();
        }

		// PCのじゃんけんの手を準備
		ArrayList<Integer> handsList = new ArrayList<Integer>();
		for(int i = 0 ; i <= 2 ; i++) {
			handsList.add(i);
        }
		Collections.shuffle(handsList);
		int pc1Hands = handsList.get(0);
		int pc2Hands = handsList.get(1);
		
		//結果判定
		int result = (userHands +  pc1Hands + pc2Hands) % 3;
		String resultMessage = null;
		
		switch (result) {
		//あいこ
		case 0:
			resultMessage = "あいこです";
			break;
			
			//1人だけ負け（2人勝ち）
		case 1:
			if(userHands == pc1Hands) {
				resultMessage = "ユーザーとpc1の勝ちです";
			} else if(userHands == pc2Hands){
				resultMessage = "ユーザーとpc2の勝ちです";
			} else {
				resultMessage = "pc1とpc2の勝ちです";
			}
			break;
			
		case 2:
			//2人だけ負け（1人勝ち）
			if(userHands == pc1Hands) {
				resultMessage = "pc2の勝ちです";
			} else if(userHands == pc2Hands){
				resultMessage = "pc1の勝ちです";
			} else {
				resultMessage = "ユーザーの勝ちです";
			}
			break;			
		
		default:
			break;
		}
		
		// 判定結果の表示
		String[] hands = { "グー", "チョキ", "パー" };
		System.out.println("ユーザーの手:" + hands[userHands] + ",pc1の手:" + hands[pc1Hands]+ ",pc2の手:" + hands[pc2Hands]);
		System.out.println("結果：" + resultMessage);
		
		// Scannerをクローズ
		stdin.close();
	}
}
```
# 解説

```java
		// PCのじゃんけんの手を準備
		ArrayList<Integer> handsList = new ArrayList<Integer>();
		for(int i = 0 ; i <= 2 ; i++) {
			handsList.add(i);
        }
		Collections.shuffle(handsList);
		int pc1Hands = handsList.get(0);
		int pc2Hands = handsList.get(1);
```
PC1とPC2の手を準備します。RandomクラスのnextInt() で、整数の乱数を作成すると、同じ結果になってしまったので、少し変えてみました。0,1,2をlistで持たせ、シャッフルして値を持ち直します。そして、1番目と2番目に格納されている値をそれぞれpc1Hands、pc2Handsとしました。

＊
```java
        Random rand = new Random();
		int pc1Hands = rand.nextInt(3);
		Random random = new Random();
		int pc2Hands = random.nextInt(3);
```
このような乱数の生成だと、pc1Handsとpc2Handsの結果が同じになってしまいました。。。（pc1とpc2のじゃんけんの手を完全にそれぞれランダムで生成する方法が見当たらなかったので、コードの書きやすくする視点から「PC1とPC2は別の手を出すこと」という条件を追加しました。）

＊
```java
		//結果判定
		int result = (userHands +  pc1Hands + pc2Hands) % 3;
		String resultMessage = null;
		
		switch (result) {
		//あいこ
		case 0:
			resultMessage = "あいこです";
			break;
			
			//1人だけ負け（2人勝ち）
		case 1:
			if(userHands == pc1Hands) {
				resultMessage = "ユーザーとpc1の勝ちです";
			} else if(userHands == pc2Hands){
				resultMessage = "ユーザーとpc2の勝ちです";
			} else {
				resultMessage = "pc1とpc2の勝ちです";
			}
			break;
			
		case 2:
			//2人だけ負け（1人勝ち）
			if(userHands == pc1Hands) {
				resultMessage = "pc2の勝ちです";
			} else if(userHands == pc2Hands){
				resultMessage = "pc1の勝ちです";
			} else {
				resultMessage = "ユーザーの勝ちです";
			}
			break;			
		
		default:
			break;
		}
```
3人でじゃんけんする際に一番難しいのが、結果判定の部分です。3×3×3で全ての通りを記述するのは、可読性が低くなるのでおすすめできません。なんとか法則を見つけて記述したいです。

そこで、ユーザー、PC1、PC2のじゃんけんの手の数値を足して、3で割った時のあまりに注目します。そして、勝った人数によって、場合分けします。そのあとは、出した手の組み合わせで勝敗を判定します。日本語で整理すると、以下のように場合分けをします。

```
(i)あまりが0の時
　→あいこ
(ii)あまりが1の時（2人勝ちのとき）
　(1)ユーザーとPC1の手が同じ時
　　→ユーザーとPC1の勝ち
　(2)ユーザーとPC2の手が同じ時
　　→ユーザーとPC2の勝ち
　(3)PC1とPC2の手が同じ時
　　→PC1とPC2の勝ち
(iii)あまりが2の時（1人勝ちのとき）
　(1)ユーザーとPC1の手が同じ時
　　→PC2の勝ち
　(2)ユーザーとPC2の手が同じ時
　　→PC1の勝ち
　(3)PC1とPC2の手が同じ時
　　→ユーザーの勝ち
```

細かいですがswitch文を使っているので、教科書通りに最後はdefaultも記述したいですね。

＊
いろんな書き方があるので、一例ととらえてもらえると嬉しいです。
解説は以上です！

＊
「習うより慣れよ」ということで、8種類題材を作成してみました！
[【Java】じゃんけんアプリをつくろう①～シンプルなじゃんけん～](https://qiita.com/aki_number16/items/89b3c0803c2bc235e0c9 "【Java】じゃんけんアプリをつくろう①～シンプルなじゃんけん～")
[【Java】じゃんけんアプリをつくろう②～あいこの場合はもう一度～](https://qiita.com/aki_number16/items/2c13747e1e89bd1a110b "【Java】じゃんけんアプリをつくろう②～あいこの場合はもう一度～")
[【Java】じゃんけんアプリをつくろう③～3回じゃんけんをしてみよう～](https://qiita.com/aki_number16/items/a0d79dbfe252c6b566dd "【Java】じゃんけんアプリをつくろう③～3回じゃんけんをしてみよう～")
[【Java】じゃんけんアプリをつくろう④～先に3勝した方が勝ち～](https://qiita.com/aki_number16/items/a58308affbf3bbe18168 "【Java】じゃんけんアプリをつくろう④～先に3勝した方が勝ち～")
[【Java】じゃんけんアプリをつくろう⑤～3人でじゃんけん～](https://qiita.com/aki_number16/items/38ed393c8cc39c3a6bf4 "【Java】じゃんけんアプリをつくろう⑤～3人でじゃんけん～")
[【Java】じゃんけんアプリをつくろう⑥～後出しじゃんけん～](https://qiita.com/aki_number16/items/59fe0b0b8323c3650d43 "【Java】じゃんけんアプリをつくろう⑥～後出しじゃんけん～")
[【Java】じゃんけんアプリをつくろう⑦～両手じゃんけん～](https://qiita.com/aki_number16/items/8e70be194ab64676f116 "【Java】じゃんけんアプリをつくろう⑦～両手じゃんけん～")
[【Java】じゃんけんアプリをつくろう⑧～あっちむてほい～](https://qiita.com/aki_number16/items/deb5c9b87e59e5dc77b4 "【Java】じゃんけんアプリをつくろう⑧～あっちむてほい～")

最後まで読んでいただいた方、ありがとうございました。