じゃんけんを三人でするプログラム
Q&A
Closed
下記のプログラムをすべて使って、じゃんけんを三人でするプログラムを作成したいのですが、ここで注意すべきことは、三人でじゃんけんをする時は、一回のじゃんけんで勝者が一人ではない場合があるということです。
このとき、例えば三人がそれぞれグー、グー、チョキなどの手を出したとしたとき、グー、グーと出した人同士でじゃんけんをし、そこから勝者(または、再びあいこになった場合にはもう一度じゃんけんをする処理)を出すというプログラム処理を「Judge.java」で行いたいのですが、どうしたらいいのかわかりません。
教えていただけるととても助かります。
現状のコード:
public class Choki implements Hand {
public String toString() {
return "Choki";
}
}
public class Goo implements Hand {
public String toString() {
return "Goo";
}
}
public interface Hand {
/** 手を表す文字列を返す */
String toString();
}
/** ジャンケンを開始するためのクラス */
public class JankenErr {
public static void main(String args[]) {
try {
Judge judge = new Judge(); // 審判の作成
// プレイヤの作成と審判への登録
Player jhon = new OrderedComputerPlayer("Jhon");
judge.registPlayer(jhon);
Player paul = new NormalComputerPlayer("Paul");
judge.registPlayer(paul);
Player george = new NormalComputerPlayer("George");
judge.registPlayer(george);
// 3回勝負でジャンケンの開始
judge.startJankens(3);
}
catch (JankenException e) {
System.err.println(e.getMessage());
}
}
}
/* じゃんけんに関する例外 */
public class JankenException extends Exception {
public JankenException() {
super();
}
public JankenException(String msg) {
super(msg);
}
}
import javax.swing.*;
/** じゃんけん の審判のクラス */
public class Judge {
protected Player players[]; // プレイヤの配列
protected int numOfPlayers; // プレイヤの数
protected int wins[]; // 勝ち数を記録する配列
int counter=0;
/** コンストラクタ */
public Judge() {
// 2人のプレイヤの配列を作成し、各要素はnullに初期化
players = new Player[3];
players[0] = players[1] = players[2] = null;
// プレイヤの数は0に初期化
numOfPlayers = 0;
// 2人の勝ち星数の配列を作成し、各要素を0に初期化
wins = new int[3];
wins[0] = wins[1] = wins[2] = 0;
}
/** じゃんけんをするプレイヤを知らされる */
public void registPlayer(Player player) throws JankenException {
if (numOfPlayers < players.length) {
// まだ余裕があるので登録
players[numOfPlayers] = player;
numOfPlayers++; // プレイヤの数を増やす
}
else {
throw new JankenException("too many players");
}
}
/** matches回勝負のじゃんけんを開始する
* つまり、誰かがmatches回勝つまでじゃんけんをする
*/
public void startJankens(int matches) throws JankenException {
if (numOfPlayers < players.length) {
throw new JankenException("need more players");
}
// プレイヤにmatches回勝負であることを知らせる
notifyMatches(matches);
int match = 1; // match回目の勝負
while (!isEndOfJankens(matches)) { // 誰かがmatches回勝つまで繰り返す
startOneJanken(match); // match回目のじゃんけんを行う
match++;
}
// matches回勝負のチャンピオンを調べる
Player[] champions = getChampions(matches);
// チャンピオンのメッセージを表示
showChampionsMessage(champions);
}
/** matches回勝負のじゃんけんが終わったか判定 */
protected boolean isEndOfJankens(int matches) {
// プレイヤの1人でもmatches回勝っていたら終わり
for (int i = 0; i < numOfPlayers; i++) {
if (wins[i] == matches) { // matches回勝っていた
return true;
}
}
return false; // 誰もmatches回勝っていない
}
/** match回目のじゃんけんを開始する */
protected void startOneJanken(int match) {
int num = 0; // 何回目の手か
Player[] winners; // 勝者の配列
do { // 勝者が決まるまで繰り返す
num++; // 手の回数を増やす
counter++;
// 掛け声
showJankenMessage(match, num);
// 各プレイヤの手を得る
Hand hands[] = getHands(match, num);
// 手を表示
showHandsMessage(hands, match, num);
// 勝者を判定する
winners = judge(hands);
} while (winners == null);
// 勝者を表示
showWinnersMessage(winners, match);
// プレイヤに勝敗を知らせる
notifyResult(winners);
}
/** match回目の勝負のnum回目の全プレイヤの手を配列で返す */
protected Hand[] getHands(int match, int num) {
// players[i]の手はhands[i]に入れる
Hand hands[] = new Hand[numOfPlayers];
for (int i = 0; i < numOfPlayers; i++) {
hands[i] = players[i].showHand(match, num, counter);
}
return hands;
}
/** ジャンケンの勝負を判定をする。
* 勝負がついた場合は 勝者のPlayerの配列を返す。
* あいこの場合は null を返す。
* なお、2人勝負の場合は常に勝者は1人である
*/
protected Player[] judge(Hand hands[]) {
// 勝者の判定をする
Player[] winner;
if ((hands[0] instanceof Goo && hands[1] instanceof Choki && hands[2] instanceof Choki)
|| (hands[0] instanceof Choki && hands[1] instanceof Par && hands[2] instanceof Par)
|| (hands[0] instanceof Par && hands[1] instanceof Goo && hands[2] instanceof Goo)) {
winner = new Player[1];
winner[0] = players[0];
wins[0]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Par && hands[2] instanceof Goo)
|| (hands[0] instanceof Choki && hands[1] instanceof Goo && hands[2] instanceof Choki)
|| (hands[0] instanceof Par && hands[1] instanceof Choki && hands[2] instanceof Par)) {
winner = new Player[2];
winner[0] = players[1];
wins[1]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Goo && hands[2] instanceof Par)
|| (hands[0] instanceof Choki && hands[1] instanceof Choki && hands[2] instanceof Goo)
|| (hands[0] instanceof Par && hands[1] instanceof Par && hands[2] instanceof Choki)) {
winner = new Player[3];
winner[0] = players[2];
wins[2]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Goo && hands[2] instanceof Choki)
|| (hands[0] instanceof Choki && hands[1] instanceof Choki && hands[2] instanceof Par)
|| (hands[0] instanceof Par && hands[1] instanceof Par && hands[2] instanceof Goo)) {
//ここの処理(0と1が勝負して、0が勝つ処理)
winner = new Player[1];
winner[0] = players[1];
wins[0]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Goo && hands[2] instanceof Choki)
|| (hands[0] instanceof Choki && hands[1] instanceof Choki && hands[2] instanceof Par)
|| (hands[0] instanceof Par && hands[1] instanceof Par && hands[2] instanceof Goo)) {
//ここの処理(0と1が勝負して、1が勝つ処理)
winner = new Player[2];
winner[0] = players[1];
wins[1]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Choki && hands[2] instanceof Goo)
|| (hands[0] instanceof Choki && hands[1] instanceof Par && hands[2] instanceof Choki)
|| (hands[0] instanceof Par && hands[1] instanceof Goo && hands[2] instanceof Par)) {
//ここの処理(0と2が勝負して、0が勝つ処理)
winner = new Player[1];
winner[0] = players[0];
wins[0]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Choki && hands[2] instanceof Goo)
|| (hands[0] instanceof Choki && hands[1] instanceof Par && hands[2] instanceof Choki)
|| (hands[0] instanceof Par && hands[1] instanceof Goo && hands[2] instanceof Par)) {
//ここの処理(0と2が勝負して、2が勝つ処理)
winner = new Player[3];
winner[0] = players[2];
wins[2]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Par && hands[2] instanceof Par)
|| (hands[0] instanceof Choki && hands[1] instanceof Goo && hands[2] instanceof Goo)
|| (hands[0] instanceof Par && hands[1] instanceof Choki && hands[2] instanceof Choki)) {
//ここの処理(1と2が勝負して、1が勝つ処理)
winner = new Player[2];
winner[0] = players[1];
wins[1]++;
}else if ((hands[0] instanceof Goo && hands[1] instanceof Par && hands[2] instanceof Par)
|| (hands[0] instanceof Choki && hands[1] instanceof Goo && hands[2] instanceof Goo)
|| (hands[0] instanceof Par && hands[1] instanceof Choki && hands[2] instanceof Choki)) {
//ここの処理(1と2が勝負して、2が勝つ処理)
winner = new Player[3];
winner[0] = players[2];
wins[2]++;
}
else {
// あいこ
winner = null;
}
return winner;
}
/** 各プレイヤの勝ち数を調べてチャンピオンを決める
* つまりmatches回勝ったプレイヤがチャンピオンである
* 3人以上の場合はチャンピオンが2人以上出る場合がある
*/
protected Player[] getChampions(int matches) {
// チャンピオンは最大 (プレイヤ数 -1)人いるので
// numOfPlayers-1 の長さの配列を作っておく
Player champions[] = new Player[numOfPlayers-1];
// 各プレイヤの勝ち数を調べてチャンピオンを決める
int championsIndex = 0;
for (int playersIndex = 0; playersIndex < numOfPlayers;
playersIndex++) {
if (wins[playersIndex] == matches) {
// matches回勝っているのでチャンピオン
champions[championsIndex] = players[playersIndex];
championsIndex++;
}
}
// 配列championsの残りの要素はnullにする
for (; championsIndex < champions.length; championsIndex++) {
champions[championsIndex] = null;
}
return champions;
}
/** 何回勝負かプレイヤに知らせる */
protected void notifyMatches(int matches) {
for (int i = 0; i < numOfPlayers; i++) {
players[i].setMatches(matches);
}
}
/** じゃんけんの結果を各プレイヤに知らせる
* 引数winnersは勝者の配列
*/
protected void notifyResult(Player[] winners) {
// 外側のループはプレイヤのループ
for (int playersIndex = 0;
playersIndex < numOfPlayers; playersIndex++) {
boolean won = false; // players[playersIndex]が勝ったかどうか
// players[playersIndex]が配列winnersに含まれているか調べる
// 内側のループは勝者のループ
for (int winnersIndex = 0; winnersIndex < winners.length;
winnersIndex++) {
if (winners[winnersIndex] == players[playersIndex]) {
// players[playersIndex]は勝った
won = true;
}
}
// プレイヤに勝敗を知らせる
if (won) players[playersIndex].youWon();
else players[playersIndex].youLost();
}
}
/** ウィンドウと標準出力にメッセージを表示する
* showXxxxMessageメソッドから呼ばれる下請メソッド
*/
protected void showMessage(String mesg) {
System.out.println(mesg);
JOptionPane.showMessageDialog(null, mesg);
}
/** じゃんけんぽん のメッセージを表示 */
protected void showJankenMessage(int match, int num) {
if (num == 1) { // 1回目は じゃんけんぽん
showMessage("Match " + match + ": Jan Ken Pon!");
}
else { // 2回目以降は あいこでしょ
showMessage("Aiko de Sho");
}
}
/** プレイヤの手のメッセージを表示 */
protected void showHandsMessage(Hand[] hands, int match, int num) {
String handMesg = "Match " + match + "-" + num + ":\n";
for (int i = 0; i < numOfPlayers; i++) {
handMesg += players[i].getName() + "'s hand is "
+ hands[i].toString() + "\n";
}
showMessage(handMesg);
}
/** ジャンケンの各回の勝者のメッセージを表示 */
protected void showWinnersMessage(Player[] winners, int match) {
String mesg = "Match " + match + ": ";
for (int i = 0; i < winners.length; i++) {
mesg += winners[i].getName() + " won.\n";
}
showMessage(mesg);
}
/** チャンピオンのメッセージを表示 */
protected void showChampionsMessage(Player[] champions) {
// チャンピオンのメッセージ
String championMesg = "";
for (int i = 0; i < champions.length && champions[i] != null; i++) {
championMesg += champions[i].getName() + " is a champion.\n";
}
// 各プレイヤが何勝したかのメッセージ
String winNumMesg = "";
for (int i = 0; i < numOfPlayers; i++) {
winNumMesg += players[i].getName() + ": " + wins[i] + " wins\n";
}
// メッセージを表示
showMessage(championMesg + winNumMesg);
}
}
/** ジャンケン の通常のコンピュータ プレイヤ */
public class NormalComputerPlayer extends Player {
protected Hand goo, choki, par;
protected java.util.Random random; // 手を決めるときに使う乱数
/** コンストラクタ, プレイヤの名前を指定する */
public NormalComputerPlayer(String name) {
super(name);
// 手を設定する
goo = new Goo();
choki = new Choki();
par = new Par();
random = new java.util.Random();
}
/** match回目の勝負のnum回目のプレイヤの手を出す
* Player の showHand をオーバーライド
*/
public Hand showHand(int match, int num, int counter) {
int hand = random.nextInt(3);
if (hand == 0) {
return goo;
} else if (hand == 1) {
return choki;
} else {
return par;
}
}
}
/** ジャンケン の通常のコンピュータ プレイヤ */
public class OrderedComputerPlayer extends Player {
protected Hand goo, choki, par;
// 手を決めるときに使う乱数
/** コンストラクタ, プレイヤの名前を指定する */
public OrderedComputerPlayer(String name) {
super(name);
// 手を設定する
goo = new Goo();
choki = new Choki();
par = new Par();
}
/** match回目の勝負のnum回目のプレイヤの手を出す
* Player の showHand をオーバーライド
*/
public Hand showHand(int match, int num, int counter) {
switch((counter++)%4){
case 2: return par;
case 3: return choki;
default: return goo;
}
}
}
public class Par implements Hand {
public String toString() {
return "Par";
}
}
/** ジャンケン プレイヤの抽象クラス */
public abstract class Player {
protected String name; // プレイヤの名前
protected int matches; // matches回勝負(matches回先に勝った方が勝ち)
protected int wins; // プレイヤの勝利数
protected int losts; // プレイヤの負け数
/** コンストラクタ, プレイヤの名前を指定する */
public Player(String name) {
this.name = name; // プレイヤの名前
wins = losts = 0; // 勝敗を初期化
}
/** プレイヤの名前を返す */
public String getName() {
return name;
}
/** 何回勝負か設定するメソッド
*/
public void setMatches(int matches) {
this.matches = matches;
}
/**
* 勝ったことを知らされるメソッド
*/
public void youWon() {
wins++;
}
/**
* 負けたことを知らされるメソッド
*/
public void youLost() {
losts++;
}
/** match回目の勝負のnum回目のプレイヤの手を出す
* 抽象メソッドなので,サブクラスでオーバーライドする
*/
public abstract Hand showHand(int match, int num, int counter);
}