LoginSignup
3
2

More than 5 years have passed since last update.

スレッドどうしで対戦する2人専用じゃんけんゲーム with Java

Last updated at Posted at 2018-02-11

###【概要】
2スレッドを生成し、そのスレッドどうしでじゃんけんをして結果を表示します。
GitHubにアップしてあります → threadJankenGame

###【コード】

JankenCallable.java
package game;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

import game.Janken.Hand;

public class JankenCallable implements Callable<Janken.Hand> {

	public static int playerNumber = 1;
	public final static Object lock = new Object();

	@Override
	public Hand call() throws Exception {
		TimeUnit.SECONDS.sleep(1);

		synchronized (lock) {
			playerNumber++;

			if (playerNumber % 2 == 0) {
				System.out.println("1人目の名前 : " + Thread.currentThread().getName());
			} else {
				System.out.println("2人目の名前 : " + Thread.currentThread().getName());
			}
		}

		return Janken.getHand();
	}
}
Janken.java
package game;

public class Janken {
	public enum Hand {
		GUU("グー"), CHOKI("チョキ"), PAA("パー");

		private final String hand;

		private Hand(String hand) {
			this.hand = hand;
		}

		public String getHand() {
			return hand;
		}
	}

	/**
	 * じゃんけんの結果を表示する
	 *
	 * @param firstPlayerHand
	 *            1人目の出した手
	 * @param secondPlayerHand
	 *            2人目の出した手
	 */
	public static void getGameResult(Hand firstPlayerHand, Hand secondPlayerHand) {
		// じゃんけんの勝者を1人目と仮置きする
		Hand winner = firstPlayerHand;

		if (firstPlayerHand == Hand.GUU && secondPlayerHand == Hand.PAA) {
			winner = secondPlayerHand;
		} else if (firstPlayerHand == Hand.CHOKI && secondPlayerHand == Hand.GUU) {
			winner = secondPlayerHand;
		} else if (firstPlayerHand == Hand.PAA && secondPlayerHand == Hand.CHOKI) {
			winner = secondPlayerHand;
		}

		System.out.println(getPlayerHand(firstPlayerHand, secondPlayerHand));
		if (firstPlayerHand == secondPlayerHand) {
			System.out.println("あいこです。");
		} else if (winner == firstPlayerHand) {
			System.out.println("1人目の勝ちです。");
		} else if (winner == secondPlayerHand) {
			System.out.println("2人目の勝ちです。");
		}
		System.out.println("");
	}

	/**
	 * ランダムにじゃんけんの手を取得する
	 * @return じゃんけんの手
	 */
	public static Hand getHand() {
		double random = Math.random() * 10;
		if (6.6 < random) {
			return Hand.GUU;
		} else if (3.3 < random) {
			return Hand.CHOKI;
		}
		return Hand.PAA;
	}

	/**
	 * プレイヤーが出した手を表示する
	 *
	 * @param firstPlayerHand
	 *            1人目の出した手
	 * @param secondPlayerHand
	 *            2人目の出した手
	 * @return 1人目と2人目の手の出し方
	 */
	private static String getPlayerHand(Hand firstPlayerHand, Hand secondPlayerHand) {
		return "1人目の手は" + String.format("%s", firstPlayerHand.getHand()) + " :  2人目の手は"
				+ String.format("%s", secondPlayerHand.getHand());
	}

}
Main.java
package game;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import game.Janken.Hand;

public class Main {

	// スレッドプール数 2人専用のじゃんけんゲームのため"2"限定となってしまう
	private static final int THREAD_POOL_COUNT = 2;
	// じゃんけんのゲーム回数
	private static final int GAME_COUNT = 3;

	public static void main(String[] args) {
		ExecutorService executorService = Executors.newScheduledThreadPool(THREAD_POOL_COUNT);

		List<Future<Hand>> jankenList = new ArrayList<>();
		for (int i = 0; i < GAME_COUNT * 2; i++) {
			Future<Hand> future = executorService.submit(new JankenCallable());
			jankenList.add(future);
		}

		int count = 0;
		Hand firstPlayerHand = null;
		Hand currentPlayerHand = null;
		for (Future<Hand> hand : jankenList) {
			count++;

			try {
				currentPlayerHand = hand.get();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			} finally {
				executorService.shutdown();
			}

			// 1人目と2人目の手が決まったところで結果を表示する
			if (count % THREAD_POOL_COUNT == 0) {
				Janken.getGameResult(firstPlayerHand, currentPlayerHand);
			} else {
				firstPlayerHand = currentPlayerHand;
			}
		}
	}
}

###【実行例】

1人目の名前 : pool-1-thread-1
2人目の名前 : pool-1-thread-2
1人目の手はグー :  2人目の手はグー
あいこです。

1人目の名前 : pool-1-thread-1
2人目の名前 : pool-1-thread-2
1人目の手はグー :  2人目の手はパー
2人目の勝ちです。

1人目の名前 : pool-1-thread-2
2人目の名前 : pool-1-thread-1
1人目の手はパー :  2人目の手はグー
1人目の勝ちです。

###【参考】
ExecutorServiceを使って、Javaでマルチスレッド処理
synchronizedブロックに使用されているStaticObjectが変更される場合、実質synchronizedされていない

###【問題点・改善点】
・3人(3スレッド)以上ではじゃんけんゲームができない。
・結果のコロン(:)の位置を揃えたかった。

###【おまけのコーナー】
スレッド処理は難しい。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2