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

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

ただいまの
回答率

90.47%

  • Java

    14091questions

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

  • 配列

    534questions

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

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,119

gyro16

score 77

前提・実現したいこと

クラスの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;
    }
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

0

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

Teの実装例

enum Te {

    Stone, Scissors, Paper;

}

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

import static local.Te.*;
import java.util.*;

final class App {

    public static void main(String[] args) throws Exception {
        JudgeC j = new JudgeC();
        j.startJanken(new PlayerC("AAA"), new PlayerC("BBB"), new PlayerC("CCC"));
    }

}

final class JudgeC {

    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) + "回戦目】");

            List<PlayerC> winners = judgeJanken(player1, player2, player3);

            if (winners.isEmpty()) {
                System.out.println("引き分けです!");
            }
            else {
                Iterator<PlayerC> it = winners.iterator();
                while (it.hasNext()) {
                    PlayerC winner = it.next();
                    System.out.println(winner.getName() + "が勝ちました!");
                    winner.notifyResult(true);
                }
            }
        }
        System.out.println("【ジャンケン終了】");

        //        judgeFinalWinner(player1, player2, player3);
    }
    private List<PlayerC> judgeJanken(PlayerC player1, PlayerC player2, PlayerC player3) {
        List<PlayerC> 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 = { { Stone, Scissors }, { Scissors, Paper }, { Paper, Stone } };
        Te[][] losePattern = { { Stone, Paper }, { Scissors, Stone }, { Paper, Scissors } };
        Te[] hands = { te1, te2, te3 };

        for (int i = 0; i < hands.length; i++) {
            boolean winFlg = false;
            boolean loseFlg = false;
            for (int j = 0; j < hands.length; j++) {
                Te[][] turn = { { hands[i], hands[j] } };
                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;
                    }
                }
            }
            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;
    }

    private void printHand(Te te) {
        System.out.print(te);
    }

}

class PlayerC {

    private String name;
    private boolean result;

    PlayerC(String name) {
        this.name = name;
    }

    public Te showHand() {
        List<Te> hands = new ArrayList<>(Arrays.asList(Stone, Scissors, Paper));
        Collections.shuffle(hands);
        return hands.get(0);
    }

    void notifyResult(boolean b) {
        this.result = b;
    }

    String getName() {
        return name;
    }

}

enum Te {

    Stone, Scissors, Paper;

}

結果

【ジャンケン開始】
【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 { /* 誰かが勝ち */ }で済みます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/18 14: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 15:27 編集

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

    キャンセル

  • 2016/05/18 15:52

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

    キャンセル

  • 2016/05/18 16:12 編集

    でしたら二次元配列の方法が間違っていて、勝ち負け両方のフラグがfalseになって飛ばされるのでは?
    試しにフラグを"負けていなければ勝ち"だけにすれば常に勝つようになるのではないでしょうか
    http://www9.plala.or.jp/sgwr-t/c/sec09.html

    すみませんでした。teratailがもっとコードが読みやすくなる機能をつけてくれると助かるんですけどね…。

    キャンセル

  • 2016/05/18 17:00 編集

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

    キャンセル

  • 2016/05/18 18: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;
    }
    }
    こういうことですか。
    それでもうまくいきませんが。

    キャンセル

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名を画面に表示する。

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

頑張ってみてください。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

関連した質問

同じタグがついた質問を見る

  • Java

    14091questions

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

  • 配列

    534questions

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