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

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

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

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

3296閲覧

ジャンケンの勝敗判定がおかしいです。手にはクラスを使いました。

gyro16

総合スコア89

Java

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2016/05/18 05:03

編集2016/05/18 10:47

###前提・実現したいこと
クラスの2次元配列を使っていますが、それで勝敗判定を正確にすること。

ジャンケンの勝敗判定したいです。
ジャンケンの勝敗判定が正確にできません。
勝敗判定がおかしいです。
Teクラスを継承したStone,Scissors,Paperクラスを作りました。

###発生している問題・エラーメッセージ
どんな結果でも引き分け判定になる

###該当のソースコード

public class JudgeC{ List<PlayerC> winners; boolean winFlg; boolean loseFlg; public void startJanken(PlayerC player1, PlayerC player2, PlayerC player3) throws Exception{ System.out.println("【ジャンケン開始】"); for(int cnt = 0; cnt < 3; cnt++){ System.out.println("【" + (cnt + 1) + "回戦目】"); winners =judgeJanken(player1, player2, player3); if(!winners.isEmpty()){ Iterator<PlayerC> it = winners.iterator(); while(it.hasNext()){ PlayerC winner = it.next(); System.out.println(winner.getName() + "が勝ちました!"); winner.notifyResult(true); } } if(winners.isEmpty()){ System.out.println("引き分けです!"); } } System.out.println("【ジャンケン終了】"); judgeFinalWinner(player1, player2, player3); } private List<PlayerC> judgeJanken(PlayerC player1, PlayerC player2, PlayerC player3){ winners = new ArrayList<PlayerC>(); Te te1 = player1.showHand(); Te te2 = player2.showHand(); Te te3 = player3.showHand(); printHand(te1); System.out.print(" vs. "); printHand(te2); System.out.print(" vs. "); printHand(te3); System.out.print("\n"); Te[][] winPattern = { { new Stone(), new Scissors() }, { new Scissors(), new Paper() }, { new Paper(), new Stone() } }; Te[][] losePattern = { { new Stone(), new Paper() }, { new Scissors(), new Stone() }, { new Paper(), new Scissors() } }; Te[] hands = { te1, te2, te3 }; for(int i = 0; i < hands.length; i++){ winFlg = false; loseFlg = false; for(int j = 0; j < hands.length; j++){ Te[][] turn = {{ hands[i], hands[j] }}; for(int a = 0; a < winPattern.length; a++){ for(int b = 0; b < winPattern[a].length; b++){ Te poi = turn[0][0]; Te wpattern = winPattern[a][b]; if(poi.equals(wpattern)){ winFlg = true; } Te lpattern = losePattern[a][b]; if(poi.equals(lpattern)){ loseFlg = true; } } } } System.out.println("w" + winFlg);// テスト出力 System.out.println("l" + loseFlg);// テスト出力 if((winFlg == true) && (loseFlg == false)){ switch(i){ case 0: winners.add(player1); break; case 1: winners.add(player2); break; case 2: winners.add(player3); break; default: break; } } } return winners; } ''' ###試したこと equals() と hashCode() の オーバーライドをStone,Scissors,Paperでやりました。 ###補足情報(言語/FW/ツール等のバージョンなど) 上のコードを下記に変更しましたが、うまくいきません。 for(int a = 0; a < winPattern.length; a++){ Te poiA = turn[0][0];// hands[i] Te poiB = turn[0][1];// hands[j] Te wpatternA = winPattern[a][0]; Te wpatternB = winPattern[a][1]; Te lpatternA = losePattern[a][0]; Te lpatternB = losePattern[a][1]; if((poiA.equals(wpatternA)) && (poiB.equals(wpatternB))){ winFlg = true; } else if((poiA.equals(lpatternA)) && (poiB.equals(lpatternB))){ loseFlg = true; } } こういうことですかね。 それでもうまくいきませんが。 public class Stone extends Te{ final int STONE = 0; int hand = STONE; public boolean equals(Object o){ if(o == this){ return true; } if(o == null){ return false; } if(!(o instanceof Stone)){ return false; } Stone s = (Stone) o; if(!(s.hand == this.hand)){ return false; } return true; } public int hashCode(){ int res = 4; res = res * 40 + hand; return res; } }

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

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

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

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

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

guest

回答3

0

ベストアンサー

Teenumを使った方がequalshashCodeを実装する必要が無くなりますし、毎回newする必要もありません。

Teの実装例

lang

1enum Te { 2 3 Stone, Scissors, Paper; 4 5}

これを踏まえて書き換えたところ、それっぽく動いているように見えます。

lang

1import static local.Te.*; 2import java.util.*; 3 4final class App { 5 6 public static void main(String[] args) throws Exception { 7 JudgeC j = new JudgeC(); 8 j.startJanken(new PlayerC("AAA"), new PlayerC("BBB"), new PlayerC("CCC")); 9 } 10 11} 12 13final class JudgeC { 14 15 public void startJanken(PlayerC player1, PlayerC player2, PlayerC player3) throws Exception { 16 System.out.println("【ジャンケン開始】"); 17 18 for (int cnt = 0; cnt < 3; cnt++) { 19 System.out.println("【" + (cnt + 1) + "回戦目】"); 20 21 List<PlayerC> winners = judgeJanken(player1, player2, player3); 22 23 if (winners.isEmpty()) { 24 System.out.println("引き分けです!"); 25 } 26 else { 27 Iterator<PlayerC> it = winners.iterator(); 28 while (it.hasNext()) { 29 PlayerC winner = it.next(); 30 System.out.println(winner.getName() + "が勝ちました!"); 31 winner.notifyResult(true); 32 } 33 } 34 } 35 System.out.println("【ジャンケン終了】"); 36 37 // judgeFinalWinner(player1, player2, player3); 38 } 39 private List<PlayerC> judgeJanken(PlayerC player1, PlayerC player2, PlayerC player3) { 40 List<PlayerC> winners = new ArrayList<PlayerC>(); 41 Te te1 = player1.showHand(); 42 Te te2 = player2.showHand(); 43 Te te3 = player3.showHand(); 44 45 printHand(te1); 46 System.out.print(" vs. "); 47 printHand(te2); 48 System.out.print(" vs. "); 49 printHand(te3); 50 System.out.print("\n"); 51 52 Te[][] winPattern = { { Stone, Scissors }, { Scissors, Paper }, { Paper, Stone } }; 53 Te[][] losePattern = { { Stone, Paper }, { Scissors, Stone }, { Paper, Scissors } }; 54 Te[] hands = { te1, te2, te3 }; 55 56 for (int i = 0; i < hands.length; i++) { 57 boolean winFlg = false; 58 boolean loseFlg = false; 59 for (int j = 0; j < hands.length; j++) { 60 Te[][] turn = { { hands[i], hands[j] } }; 61 for(int a = 0; a < winPattern.length; a++){ 62 63 Te poiA = turn[0][0];// hands[i] 64 Te poiB = turn[0][1];// hands[j] 65 Te wpatternA = winPattern[a][0]; 66 Te wpatternB = winPattern[a][1]; 67 68 Te lpatternA = losePattern[a][0]; 69 Te lpatternB = losePattern[a][1]; 70 if((poiA.equals(wpatternA)) && (poiB.equals(wpatternB))){ 71 winFlg = true; 72 } else if((poiA.equals(lpatternA)) && (poiB.equals(lpatternB))){ 73 loseFlg = true; 74 } 75 } 76 } 77 System.out.println("w" + winFlg);// テスト出力 78 System.out.println("l" + loseFlg);// テスト出力 79 if ((winFlg == true) && (loseFlg == false)) { 80 switch (i) { 81 case 0: 82 winners.add(player1); 83 break; 84 case 1: 85 winners.add(player2); 86 break; 87 case 2: 88 winners.add(player3); 89 break; 90 default: 91 break; 92 } 93 } 94 } 95 return winners; 96 } 97 98 private void printHand(Te te) { 99 System.out.print(te); 100 } 101 102} 103 104class PlayerC { 105 106 private String name; 107 private boolean result; 108 109 PlayerC(String name) { 110 this.name = name; 111 } 112 113 public Te showHand() { 114 List<Te> hands = new ArrayList<>(Arrays.asList(Stone, Scissors, Paper)); 115 Collections.shuffle(hands); 116 return hands.get(0); 117 } 118 119 void notifyResult(boolean b) { 120 this.result = b; 121 } 122 123 String getName() { 124 return name; 125 } 126 127} 128 129enum Te { 130 131 Stone, Scissors, Paper; 132 133}

結果

【ジャンケン開始】 【1回戦目】 Scissors vs. Scissors vs. Stone wfalse ltrue wfalse ltrue wtrue lfalse CCCが勝ちました! 【2回戦目】 Stone vs. Stone vs. Stone wfalse lfalse wfalse lfalse wfalse lfalse 引き分けです! 【3回戦目】 Stone vs. Paper vs. Paper wfalse ltrue wtrue lfalse wtrue lfalse BBBが勝ちました! CCCが勝ちました! 【ジャンケン終了】


本題とは関係ないですが、

  • List<PlayerC> winners, boolean winFlg, loseFlgは勝負ごとに新しくする必要があるので、フィールドにすると間違えやすいのでローカル変数にしたほうが良いです。
  • if (!winners.isEmpty()) {は、必ずどちらかに振り分けられるので、if文を2つ書くのはよろしくないです。if (winners.isEmpty()) { /* 引き分け */ } else { /* 誰かが勝ち */ }で済みます。

投稿2016/05/18 12:57

argius

総合スコア9388

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

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

0

実行環境が手元にないため、コードレビューのみでのアドバイスになります。

まず、これは意図した動きをしないコードあるあるなのですが、わかりづらい処理(複雑な処理)を記述しているのにコード内にまったくコメントがないため、余計にわかりづらい状態になっています。
(実装したい機能以上に複雑なコードになっているような気もします。)

このコード内に正しくコメントを記述できるほどコードが理解できていますか?
できているのでしたら、まずコメントを書き込むことが状況把握の近道になるかもしれません。


あやしそうなところとしてはとりあえず以下2点。
・Teクラスのequalsがどういう判断になっているのか不明ですが、poi.equals(wpattern)は要素1・2ともに同じ組み合わせの場合にTrueを返すものと思いますが、これが意図した結果を返しているか。
・poiは意図した組み合わせ(1週目はPlayer1と1の手、2週目はPlayer1と2の手・・・)となっているか。


原因究明の手助けとして、
<startJanken>
・試行回数をとりあえず1回にする。
<judgeJanken>
・ループ処理で勝敗判定を行う際、判定中のpoi(の手の組み合わせ)を画面に表示する
・同じく、判定中の勝ちパターン/負けパターン(の手の組み合わせ)を画面に表示する。
・Win回数/Lose回数が想定通りか確認する。
・条件を満たしwinners.addした際に、addしたPlayer名を画面に表示する。

以上の対応を行い、意図した動作をしている点、していない点を切り分けていくことをお勧めします。

頑張ってみてください。

投稿2016/05/18 12:50

編集2016/05/18 12:53
jawa

総合スコア3013

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

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

0

何を入力しても引き分けです!と出力されるのであればisEmpty()に、例えば戻り値などに問題があるのではないでしょうか
よろしければそちらも見せていただけませんか?
ところでこのジャンケンに負けはないのですか?

投稿2016/05/18 05:40

編集2016/05/18 05:44
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

gyro16

2016/05/18 05:44

private List<PlayerC> judgeJanken(PlayerC player1, PlayerC player2, PlayerC player3){ winners = new ArrayList<PlayerC>(); Te te1 = player1.showHand(); Te te2 = player2.showHand(); Te te3 = player3.showHand(); printHand(te1); System.out.print(" vs. "); printHand(te2); System.out.print(" vs. "); printHand(te3); System.out.print("\n"); Te[][] winPattern = { { new Stone(), new Scissors() }, { new Scissors(), new Paper() }, { new Paper(), new Stone() } }; Te[][] losePattern = { { new Stone(), new Paper() }, { new Scissors(), new Stone() }, { new Paper(), new Scissors() } }; Te[] hands = { te1, te2, te3 }; for(int i = 0; i < hands.length; i++){ winFlg = false; loseFlg = false; for(int j = 0; j < hands.length; j++){ Te[][] turn = {{ hands[i], hands[j] }}; for(int a = 0; a < winPattern.length; a++){ for(int b = 0; b < winPattern[a].length; b++){ Te poi = turn[0][0]; Te pattern = winPattern[a][b]; if(poi.equals(pattern)){ winFlg = true; } } } for(int a = 0; a < losePattern.length; a++){ for(int b = 0; b < losePattern[a].length; b++){ Te poi = turn[0][0]; Te pattern = losePattern[a][b]; if(poi.equals(pattern)){ loseFlg = true; } } } } System.out.println(winFlg);// System.out.println(loseFlg);// if((winFlg == true) && (loseFlg == false)){ switch(i){ case 0: winners.add(player1); break; case 1: winners.add(player2); break; case 2: winners.add(player3); break; default: break; } } } return winners; } 勝者のみをList<PlayerC> winnersに入れる。 いなければnull、Emptyになるロジックです。
退会済みユーザー

退会済みユーザー

2016/05/18 06:36 編集

私の読み間違えかもしれませんがswitch()の中のiが原因だと思います for文の中で宣言した変数はfor文の中でしか使えないはずですので、存在しない変数を参照してdefaultに行っているのではないでしょうか。 知識が浅いものでisEmptyの関数を忘れていました。もうしわけない。
gyro16

2016/05/18 06:52

変数iは、for文で使っていますが、そのfor文内でのif文からswitch文なので変数iのスコープ内です。
退会済みユーザー

退会済みユーザー

2016/05/18 07:55 編集

でしたら二次元配列の方法が間違っていて、勝ち負け両方のフラグがfalseになって飛ばされるのでは? 試しにフラグを"負けていなければ勝ち"だけにすれば常に勝つようになるのではないでしょうか http://www9.plala.or.jp/sgwr-t/c/sec09.html すみませんでした。teratailがもっとコードが読みやすくなる機能をつけてくれると助かるんですけどね…。
gyro16

2016/05/18 08:08 編集

負けlosePtternを除外すると、半分は正常に動きますが、あいこ、引き分け判定ができなくなりました。
gyro16

2016/05/18 09:06

for(int a = 0; a < winPattern.length; a++){ Te poiA = turn[0][0]; Te poiB = turn[0][1]; Te wpatternA = winPattern[a][0]; Te wpatternB = winPattern[a][1]; Te lpatternA = losePattern[a][0]; Te lpatternB = losePattern[a][1]; if((poiA.equals(wpatternA)) && (poiB.equals(wpatternB))){ winFlg = true; } else if((poiA.equals(lpatternA)) && (poiB.equals(lpatternB))){ loseFlg = true; } } こういうことですか。 それでもうまくいきませんが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問