【Java】じゃんけんアプリをつくろう⑧～あっちむてほい～

前回は、両手じゃんけんアプリをつくりました。次は、じゃんけん＋あっちむいてほいを作成してみましょう。「①シンプルなじゃんけん」から続いたじゃんけんアプリの総合問題のようなものになりました。

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

:::note info
条件：  
・ユーザーとCPの1対1のじゃんけん/あっちむいてほいであること
・PCのじゃんけんの手と方向はランダムであること
・じゃんけんの手は次のように数字で扱うこと グー：0,チョキ：1,パー：2
・あっちむてほいの方向は次のように数字で扱うこと　上：0，下：1、左：2、右：3
・じゃんけんで勝ちまたは負けの場合は、あっちむてほいを行い、あいこの場合は、再度じゃんけんを行うこと
・あっちむてほいで、ユーザーとPCが別の方向を示した場合、「あっちむいてほいは、あいこです。」と標準出力され、じゃんけんからやり直すこと
・あっちむいてほいの勝敗は、方法を示す数字が一致しているかどうかで判定すること（じゃんけんでユーザーが勝ち、かつ　あっちむいてほいでユーザーとPCが同じ方向を選んだ際はユーザーの勝ち。じゃんけんでPCが勝ち、かつ　あっちむいてほいでユーザーとPCが同じ方向を選んだ際はPCの勝ち。）
・勝負がつくまで続けること
・じゃんけんの際に、0,1,2以外の値が入力された場合は、「グー：0，チョキ：1、パー：2　どれかの数字をいれてください。」とメッセージを表示し、じゃんけんの手を再入力できるようにすること
・あっちむいてほいの際に、0,1,2,3以外の値が入力された場合は、「上：0，下：1、左：2、右：3　どれかの数字をいれてください。」とメッセージを表示し、あっちむいてほいの方向を再入力できるようにすること
:::


# 解答例
解答例を用意しましたので、見ていきましょう。
```java:JankenAndAtchiMuiteHoi.java
package com.example.demo.controller;

import java.security.SecureRandom;
import java.util.Random;
import java.util.Scanner;

public class JankenAndAtchiMuiteHoi {

	public static void main(String[] args) {

		// 判定結果メッセージ
		String resultMessage = null;

		// じゃんけんを実行
		int playerResult = janken();

		// あっちむいてほいを実行
		while (true) {

			// じゃんけんの結果ユーザーが勝ちのとき
			if (playerResult == 2) {

				// メッセージの表示
				System.out.println("あっちむいてほい！(上：0，下：1、左：2、右：3　どれかの数字をいれてください。)");

				// ユーザーの手を読み取る
				int userDirection = getUserDirection();

				// PCの手を準備
				int pcDirection = getPcDirection();

				// 結果判定
				if (userDirection == pcDirection) {
					resultMessage = "ユーザーの勝ちです";
					showLookThisWayResult(userDirection, pcDirection, resultMessage);
					
					break;
				}
				resultMessage = "あっちむいてほいは、あいこです。";
				showLookThisWayResult(userDirection, pcDirection, resultMessage);
				playerResult = janken();

				// じゃんけんの結果ユーザーが負けのとき
			} else if (playerResult == 1) {
				// メッセージの表示
				System.out.println("あっちむいてほい！(上：0，下：1、左：2、右：3　どれかの数字をいれてください。)");

				// ユーザーの手を読み取る
				int userDirection = getUserDirection();

				// PCの手を準備
				int pcDirection = getPcDirection();

				// 結果判定
				if (userDirection == pcDirection) {
					resultMessage = "ユーザーの負けです";
					showLookThisWayResult(userDirection, pcDirection, resultMessage);
					break;
				}
				resultMessage = "あいこです。";
				showLookThisWayResult(userDirection, pcDirection, resultMessage);
				playerResult = janken();

				// じゃんけんの結果あいこのとき
			} else {
				playerResult = janken();
			}

		}

	}

	// じゃんけん
	private static int janken() {
		// メッセージの表示
		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のじゃんけんの手を準備
        Random rand = new SecureRandom();
		int pcHands = rand.nextInt(3);

		// 結果判定
		int result = (userHands - pcHands + 3) % 3;
		String resultMessage = null;
		if (result == 2) {
			resultMessage = "じゃんけんはユーザーの勝ちです";
		} else if (result == 1) {
			resultMessage = "じゃんけんはユーザーの負けです";
		} else {
			resultMessage = "じゃんけんはあいこです";
		}

		// 判定結果の表示
		String[] hands = { "グー", "チョキ", "パー" };
		System.out.println("ユーザーの手:" + hands[userHands] + ",PCの手:" + hands[pcHands]);
		System.out.println("結果：" + resultMessage);
		
		return result;
	}

	// あっちむいてほいのユーザーの手を取得
	private static int getUserDirection() {
		Scanner stdin = new Scanner(System.in);
		int userDirection = stdin.nextInt();
		
        // 入力チェック
        while (userDirection < 0 || userDirection > 3) {
            System.out.println("上：0，下：1、左：2、右：3　どれかの数字をいれてください。");
            userDirection = stdin.nextInt();
        }
		
		return userDirection;
	}

	// あっちむいてほいのPCの手を取得
	private static int getPcDirection() {
		Random rand = new Random();
		int pcDirection = rand.nextInt(4);
		return pcDirection;
	}

	// あっちむいてほい結果表示
	private static void showLookThisWayResult(int userDirection, int pcDirection, String resultMessage) {
		// 判定結果の表示
		String[] direction = { "上", "下", "左", "右" };
		System.out.println("あなたの手:" + direction[userDirection] + ",コンピュータの手:" + direction[pcDirection]);
		System.out.println("結果：" + resultMessage);
	}

}

```

## 解説
```java

		// じゃんけんを実行
		int playerResult = janken();
```
今回は、じゃんけんメソッド、ユーザーの手を読み取るメソッドなど動作をメソッドにそれぞれ切り出して、作成してみました。mainメソッドに全部書いてしまうと長くなるし、メソッドを使いまわすようにしたかったのが理由です。けっこうスッキリしましたね。

＊
```java
			// じゃんけんの結果ユーザーが勝ちのとき
			if (playerResult == 2) {

				// 省略

				// じゃんけんの結果ユーザーが負けのとき
			} else if (playerResult == 1) {
				
				// 省略
				
				// じゃんけんの結果あいこのとき
			} else {
				playerResult = janken();
			}

```
あっちむてほいの部分は、じゃんけんの結果によって、場合分けしています。じゃんけんメソッドで、結果を数字として返して使用していることがポイントです。

＊
```java
		// あっちむいてほいを実行
		while (true) {
			// じゃんけんの結果playerが勝ちのとき
			if (playerResult == 2) {
				//省略

				// 結果判定
				if (userDirection == pcDirection) {
					resultMessage = "ユーザーの勝ちです";
					showLookThisWayResult(userDirection, pcDirection, resultMessage);
					
					break;
				}

				//省略

					// じゃんけんの結果playerが負けのとき
			} else if (playerResult == 1) {
				//省略

				// 結果判定
				if (userDirection == pcDirection) {
					resultMessage = "ユーザーの負けです";
					showLookThisWayResult(userDirection, pcDirection, resultMessage);
					break;
				}
				//省略

			// じゃんけんの結果あいこのとき
			} else {
				playerResult = janken();
			}
					}

```
あっちむてほいの結果判定はあまり難しくないですが、「勝負がつくまで続ける」「あっちむてほいの結果があいこの時はじゃんけんに戻る」という条件を表現するのが難しかったです。while文で無限ループをつくって、勝敗がついたときにbreakするという力技で、記述してみました。おかげで、決着がつくまでの時間が長くなります。

＊
```java
				resultMessage = "あいこです。";
				showLookThisWayResult(userDirection, pcDirection, resultMessage);
				playerResult = janken();
```
あっちむてほいの結果判定に該当しない場合は、あいこ（ユーザーとPCが別の方向を選択）の時なので、上記のようにあいこのメッセージを表示して、再度じゃんけんメソッドを呼び出しています。じゃんけんの部分をメソッドとして切り出したので、使いやすいですね。

＊

```java
	// あっちむいてほいのユーザーの手を取得
	private static int getUserDirection() {
		Scanner stdin = new Scanner(System.in);
		int userDirection = stdin.nextInt();
		
        // 入力チェック
        while (userDirection < 0 || userDirection > 3) {
            System.out.println("上：0，下：1、左：2、右：3　どれかの数字をいれてください。");
            userDirection = stdin.nextInt();
        }
		
		return userDirection;
	}

	// あっちむいてほいのPCの手を取得
	private static int getPcDirection() {
		Random rand = new Random();
		int pcDirection = rand.nextInt(4);
		return pcDirection;
	}

	// あっちむいてほい結果表示
	private static void showLookThisWayResult(int userDirection, int pcDirection, String resultMessage) {
		// 判定結果の表示
		String[] direction = { "上", "下", "左", "右" };
		System.out.println("あなたの手:" + direction[userDirection] + ",コンピュータの手:" + direction[pcDirection]);
		System.out.println("結果：" + resultMessage);
	}
```

あっちむいてほいのユーザーの手を取得するメソッド、あっちむいてほいでPCの手を取得するメソッド、あっちむいてほいの結果表示するメソッドに分けて記載してみました。メソッドに分けてmainメソッドから呼び出したときに、「static」をつけるのがポイントです。

＊
```java
		// PCのじゃんけんの手を準備
        Random rand = new SecureRandom();
		int pcHands = rand.nextInt(3);
```
じゃんけんの手を準備するところでは、SecureRandom()をnewしています。これを使うと、ランダム値の偏りが少なくなるようです。

＊

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

＊
「習うより慣れよ」ということで、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】じゃんけんアプリをつくろう⑧～あっちむてほい～")

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