質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

528閲覧

ランダムな組で対戦できるようにしたい

ike-0315

総合スコア30

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2018/04/11 08:33

編集2018/04/13 01:44

前提・実現したいこと

初投稿です。
投稿の作法についても、プログラミングの作法についてもまだまだ未熟かと思います。
ご指導よろしくお願いいたします。
Javaでジャンケンプログラムを作っています。
1.プレイヤーは3人
2.対戦は毎回プレイヤーの中からランダムに2名を選び、勝ち負けが出るまで対戦する
3.この1対1対戦をn回繰り返します。
4.結果は
Player1 : Yamada
Player2 : Suzuki
Player3 : Tanaka
Judge Sato

Results: 20games
1 vs 2 : 5 games
1 vs 3 : 7 games
2 vs 3 : 8 games

Yamada 6 win, 6 lose, 3 draw
Suzuki 5 win, 8 lose, 11 draw
Tanaka 9 win, 6 lose, 8 draw
のように出力します。

発生している問題・エラーメッセージ

2.のランダムにプレーヤーを対戦させるアイデアが浮かびませんでした。

該当のソースコード

Java

1import javax.xml.transform.Result; 2 3public class Judge { 4 private String name; 5 private RandomJankenPlayer player1, player2, player3; 6 7 public Judge(String _name) { 8 name = _name; 9 } 10 public void setPlayers(RandomJankenPlayer _player1, RandomJankenPlayer _player2, RandomJankenPlayer _player3) { 11 player1 = _player1;// player3人にする 12 player2 = _player2; 13 player3 = _player3; 14 } 15 16 public void play(int n) { 17 Hand hand1 = null, hand2 = null, hand3 = null; 18 Result result1,result2,result3; 19 20 for (int i = 0; i < n; i++) { 21 hand1 = player1.showHand(); 22 hand2 = player2.showHand(); 23 hand3 = player3.showHand(); 24 25//対戦プレイヤーランダム選択?? 26 27 //勝敗判定Judge 28 29 if (hand1 == hand2) { 30 draw1++; 31 draw2++; 32 } 33 if (hand1 == Hand.ROCK && hand2 == Hand.SCISSORS) { 34 win1++; 35 lose2++; 36 break; 37 } 38 if (hand1 == Hand.ROCK && hand2 == Hand.PAPER) { 39 lose1++; 40 win2++; 41 break; 42 } 43 if (hand1 == Hand.SCISSORS && hand2 == Hand.ROCK) { 44 lose1++; 45 win2++; 46 break; 47 } 48 if (hand1 == Hand.SCISSORS && hand2 == Hand.PAPER) { 49 win1++; 50 lose2++; 51 break; 52 } 53 if (hand1 == Hand.PAPER && hand2 == Hand.ROCK) { 54 win1++; 55 lose2++; 56 break; 57 } 58 if (hand1 == Hand.PAPER && hand2 == Hand.SCISSORS) { 59 lose1++; 60 win2++; 61 break; 62 } 63 } 64 } 65 //結果表示 66 System.out.println("Player1 : " + player1.getName()); 67 System.out.println("Player2 : " + player2.getName()); 68 System.out.println("Player3 : " + player3.getName()); 69 System.out.println("Judge : " + name); 70 System.out.println(); 71 System.out.println("Results: " + n + " games"); 72 System.out.println("1 vs 2 : " + a +" games"); 73 System.out.println("1 vs 3 : " + b +" games"); 74 System.out.println("2 vs 3 : " + c +" games"); 75 System.out.println( 76 player1.getName() + win1+ " win," 77 + " " + lose1 + " lose, " + draw1 + " draw"); 78 System.out.println( 79 player2.getName() + win2 + " win," 80 + " " + lose2 + " lose, " + draw2 + " draw"); 81 System.out.println( 82 player3.getName() + win2 + " win," 83 + " " + lose2 + " lose, " + draw2 + " draw"); 84 } 85 86 public static void main(String[] args) { 87 try { 88 int num = Integer.parseInt(args[0]); 89 RandomJankenPlayer player1 = new RandomJankenPlayer("Yamada"); 90 RandomJankenPlayer player2 = new RandomJankenPlayer("Suzuki"); 91 RandomJankenPlayer player3 = new RandomJankenPlayer("Tanaka"); 92 Judge judge = new Judge("Sato"); 93 judge.setPlayers(player1, player2, player3); 94 judge.play(num); 95 } catch (Exception e) { 96 System.out.println("this requires an integer argument."); 97 } 98 } 99} 100 101/* 102public class RandomJankenPlayer { 103 private String name;//private:ReadOnly 104 public RandomJankenPlayer(String name){ 105 this.name = name; 106 } 107 public String getName() { 108 return name; 109 } 110 public void setName(String name) { 111 this.name = name; 112 } 113 public Hand showHand(){ 114 Hand play; 115 double rnd = Math.random(); 116 if(rnd < 1.0/3.0){ 117 play = Hand.ROCK; 118 }else if (rnd < 2.0/3.0){ 119 play = Hand.PAPER; 120 }else{ 121 play = Hand.SCISSORS; 122 } 123 return play; 124 } 125 // main 126 public static void main(String[] args){ 127 RandomJankenPlayer player1 = new RandomJankenPlayer("Yamada"); 128 RandomJankenPlayer player2 = new RandomJankenPlayer("Suzuki"); 129 Hand hand1, hand2; 130 for(int i=0; i<10; i++){ 131 hand1 = player1.showHand(); 132 hand2 = player2.showHand(); 133 System.out.println(i+")"+ 134 "["+player1.getName()+"]"+hand1+" vs "+ 135 "["+player2.getName()+"]"+hand2); 136 } 137 } 138} 139 140*/ 141/* 142enum Hand {ROCK, PAPER, SCISSORS} 143*/ 144/* 145enum Result {WIN,LOSE,DRAW} 146*/ 147

試したこと

2人の場合について勝敗判定するプログラムを作成してみました

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは、少し説明が長くなりますが順を追ってわかりやすく説明したいと思います。
int型の変数nに自然数を入力した状態から説明します。

1.乱数を使うにはimort java.util.Random;

これをインポートします。そして、Main関数内にて Random rand = new Random();
を宣言します。player1 = rand.nextInt(n);で0からn - 1までの整数をランダムに出力します。
今回はplayerが3人なのでn = 3にします。

2.どの2人が対戦したのか カウントするための配列を用意する.
要素数が3の配列を準備します。
0番目:Yamada vs Suzuki の回数
1番目:Suzuki vs Tanaka の回数
2番目:Tanaka vs Yamada の回数
を後でカウントします。私が書いたソースコードではswitch文で処理しています。

3.選ばれた2人がそれぞれどの手を出すか乱数を使って出力
ここも1で説明した乱数を使います。
グーが0 チョキが1 パーが2に対応しています。

4.勝ち負け引き分けの判定をする。
勝ち負け引き分けの判定ですべての場合を出してif文で評価してもいいですが
もっと効率的な方法があります。次の表をご覧ください。
|player1の手|player2の手|結果|2つの整数の差を3で割ったときのあまり|
|:--:|:--:|--:|
|0|0|引き分け|0|
|2|1|player1の負け,player2の勝ち|1|
|1|2|player1の勝ち,player2の負け|2|

他の場合もありますが,上の表のように
(player1の手) - (player2の手)を3で割った余り0,1,2がそれぞれの結果と対応します。
ただし、(player1の手) - (player2の手)が負の整数になったときは余りが-2などになるので
プログラム上では、(player1の手) - (player2の手) + 3を3で割ったときの余りを求めます。

5.3人 それぞれの勝ち負け引き分けの回数をカウントする配列を用意する
今回用意する配列は2次配列です。(サイズは3*3)
内容は

Yamadaの引き分けの回数Suzukiの負けた回数Suzukiの勝った回数
Suzukiの引き分けの回数Suzukiの負けた回数Suzukiの勝った回数
Tanakaの引き分けの回数Tanakaの負けた回数Tanakaの勝った回数

となります。4で説明した方法で判定し それぞれの回数をカウントします。

6.配列を使って効率的に結果表示する。
最後の結果表示ではもちろんfor文を使うのですが,

playerの名前String []player = {"Yamada","Suzuki","Tanaka"};
結果 String []result_text = {"Draw","Lose","Win"};
を使うとfor文の中で変数iをインクリメントしながら効率的に表示できると思います。

説明が長くなってすいません。表を使ってわかりやすく説明したつもりですが
何かわからなかったところがあればまたご連絡ください。
私が書いたソースコードを載せておきます。

Java

1import java.util.Random; 2import java.util.Scanner; 3 4public class Midi{ 5 public static void main(String[] args){ 6 7 Scanner sc = new Scanner(System.in); 8 String line = sc.nextLine(); 9 int n = Integer.parseInt(line); 10 Random rand = new Random(); 11 12 int []battle_num = {0,0,0}; //どの2人が対戦したのか カウントするための配列。 13 int [][]result = new int[3][3]; 14 for(int j = 0; j < 3; j++){ 15 for(int k = 0; k < 3; k ++){ 16 result[j][k] = 0; 17 } 18 } 19 int player1; 20 int player2; 21 for(int i = 0; i < n; i++){ 22 player1 = 0; 23 player2 = 0; 24 while(player1 == player2){ 25 player1 = rand.nextInt(3); //どの2人が選ばれるか 26 player2 = rand.nextInt(3); 27 } 28 switch(player1 + player2){ //最初は3で割った余りを求めようと思ったがそれだと要素の番号がずれる 29 case 1: 30 battle_num[0]++; 31 break; 32 case 2: 33 battle_num[2]++; 34 break; 35 case 3: 36 battle_num[1]++; 37 break; 38 default: 39 break; 40 } //どの2人が対戦したのか カウントします。 41 int player1_hand = rand.nextInt(3); //グーが0,チョキが1,パーが2 42 int player2_hand = rand.nextInt(3); 43 44 switch((player1_hand - player2_hand + 3) % 3){ 45 case 0: //引き分け 46 result[player1][0]++; 47 result[player2][0]++; 48 break; 49 case 1: //player1が負け,player2が勝ち 50 result[player1][1]++; 51 result[player2][2]++; 52 break; 53 case 2: //player1が勝ち,player2が負け 54 result[player1][2]++; 55 result[player2][1]++; 56 break; 57 default: 58 break; 59 } 60 } 61 //さぁ、結果の表示だ 62 String []player = {"Yamada","Suzuki","Tanaka"}; 63 String []result_text = {"Draw","Lose","Win"}; 64 System.out.println("対戦回数:" + n + "回"); //printfのほうがいいかもしれません 65 for(int i = 0; i < 3; i++){ 66 System.out.println(player[i % 3] + " VS " + player[(i + 1) % 3] + ":" + battle_num[i] + "回"); 67 } 68 for(int i = 0; i < 3; i++){ 69 System.out.print(player[i] + ":"); 70 for(int j = 0; j < 3; j++){ 71 System.out.print(result_text[j] + ":" + result[i][j] + " "); 72 } 73 System.out.println(); 74 } 75 } 76}

結果の例

対戦回数:100回
Yamada VS Suzuki:34回
Suzuki VS Tanaka:30回
Tanaka VS Yamada:36回
Yamada:Draw:25 Lose:23 Win:22
Suzuki:Draw:18 Lose:21 Win:25
Tanaka:Draw:23 Lose:23 Win:20

投稿2018/04/11 14:34

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/04/11 14:38

ちなみに出力結果では 3人がそれぞれ負けた回数の和と勝った回数の和は等しいです。(当然ですが...) そして、その和をmとすると3人がそれぞれ引き分けだった回数の和は(n - m) * 2になります。 引き分けの時はじゃんけんをした"2人"の引き分け回数がカウントされるから2倍になります。
退会済みユーザー

退会済みユーザー

2018/04/11 14:41

私が回答に載せたものだと対戦回数が100回の時, (3人がそれぞれ負けた回数) = (3人がそれぞれ勝った回数) = 67で、 (3人がそれぞれ引き分けだった回数) = (100 - 67) * 2 = 66となっています。
ike-0315

2018/04/12 01:20

非常に丁寧でわかりやすい回答でした! おかげさまでなんとかなりそうです。ありがとうございました!!
退会済みユーザー

退会済みユーザー

2018/04/12 03:13 編集

ike-0315さんが書いたクラスのところをそのままにして、「じゃんけんの判定」と 「playerの名前、勝ち負け引き分けの判定などを配列にする」のところを 私が説明したものに変えれば私か載せたソースコードより短くてわかりやすくなるかもしれません。
guest

0

次の二つを解決すれば良いです。
0. playerを配列やリストで管理すること
0. [0, 人数)の整数のうち、2つを重複なくランダムに選択すること

2番目はいろいろな実装が考えられますが(※)、最も単純なのは次の方法でしょう。

Java

1Random rand = new Random(); 2int idx1 = rand.nextInt(人数); 3int idx2 = idx1; 4 5while(idx1 == idx2) { 6 idx2 = rand.nextInt(人数); 7}

あとはidx1番目のプレイヤーとidx2番目のプレイヤーを戦わせればよいです。


[0, 人数)の整数リストをシャッフルし、最初の二つを選択する方法が効率が良い。

投稿2018/04/11 08:45

編集2018/04/11 09:03
LouiS0616

総合スコア35658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ike-0315

2018/04/12 01:22

ランダムに数字を生成することでプレーヤーをランダムに選択できるのですね...! 参考になりました。回答ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問