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

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

ただいまの
回答率

90.47%

  • Java

    14088questions

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

3人のジャンケンの勝敗判定で詰まりました。オブジェクト指向でジャンケンの手をクラスに変えるには?

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 4,103

gyro16

score 77

うーん、欲を言えば、オブジェクト指向でこなしたいです。
ヒントはもらっています。「ジャンケンの手をクラスにする」です。

オブジェクト指向でジャンケンの手のクラスにすると、どうなりますが、
extends 継承を使うにはどのように変えたらいいですか?
今はジャンケンの手はフィールドですね。

3人でのジャンケンの判定をしたいプログラムを作りたいのですが、詰まりました。

まず勝敗がつくパターンはジャンケンの手が2種類の時というのは分かりました。

①勝ったプレイヤーが2人の時、勝者のプレイヤー2人を返すメソッドで可能ではないような感じですし・・・

3人で勝敗がつくパターンは2人が同じ種類のジャンケンの手を出している
・・・2人が勝つパターンか、その他の1人が勝つパターン、です。

②同じ種類のジャンケンの手を出しているプレイヤーを判別認識させたい、です。

書籍のプログラムを改造しようと手を付けてみたものの、詰まってしまいました。

    //@param player1 判定対象プレイヤー1
    //@param player2 判定対象プレイヤー2
    //@return 勝ったプレイヤー。引き分けの時はnullを返す。
    private Player judgeJanken(Player player1, Player player2, Player player3){
        Player winner = null;
        //プレイヤー1の手を出す
        int player1hand = player1.showHand();
        //プレイヤー2の手を出す
        int player2hand = player2.showHand();
        int player3hand = player3.showHand();

        printHand(player1hand);
        System.out.print(" vs. ");
        printHand(player2hand);
        System.out.print(" vs. ");
        printHand(play3hand);
        System.out.print("\n");

        int[] hands = { player1hand, player2hand, player3hand };
        int type = 1;
        int maxType = 0;
        for(int i = 0;  i < hands.length; i++){
            for(int j = i + 1; j < hands.length ; j++){
                    if(hands[i] != hands[j]){
                        type++;
                    }
                    if(maxType < type){
                        maxType = type;
                    }
                    type = 1;
                }
            }
        }
        if(maxType == 2){
            if(hands[0] == Player.STONE && hands[1] ==Player.STONE && hands[2] == Player.SCISSORS){
                System.out.println(player1.getName() + "と" + player2.getName() + "が勝ちました!");
                player1.winCount_++;
                player2.winCount_++;
            } else if(hands[0] == Player.STONE && hands[1] == Player.SCISSORS && hands[2] == Player.STONE){
                System.out.println(player1.getName() + "と" + player3.getName() + "が勝ちました!");
                player1.winCount_++;
                player3.winCount_++;
            } else if(hands[0] == Player.SCISSORS && hands[1] == Player.STONE && hands[2] == Player.STONE){
                System.out.println(player2.getName() + "と" + player3.getName() + "が勝ちました!");
                player2.winCount_++;
                player3.winCount_++;
            }
と、こんな風に書いて行けばいいのは分かりました。
_____________________________
うーん、欲を言えば、オブジェクト指向でこなしたいです。
ヒントはもらっています。「ジャンケンの手をクラスにする」です。

オブジェクト指向でジャンケンの手のクラスにすると、どうなりますが、
extends 継承を使うにはどのように変えたらいいですか?
今はジャンケンの手はフィールドですね。

        /* if((player1hand == Player.STONE && player2hand == Player.SCISSORS)
            * ||(player1hand == Player.SCISSORS && player2hand == Player.PAPER)
            * ||(player1hand == Player.PAPER && player2hand == Player.STONE)){
            * winner = player1;
        * } else if(
            * (player1hand == Player.STONE && player2hand == Player.PAPER)
            * ||(player1hand == Player.SCISSORS && player2hand == Player.STONE)
            * ||(player1hand == Player.PAPER && player2hand == Player.SCISSORS)){
            * winner = player2;
        * }
        * //どちらでもない場合は引き分け(nullを返す)
        return winner;
    }

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • te2ji

    2016/05/14 12:56

    質問を変えないでもらえますか。後に他の人が見た時に参考にならなくなります。 質問が変わるのであれば、別の質問を立てて下さい。

    キャンセル

回答 6

+1

解決済みですので蛇足ですが…
https://teratail.com/questions/34165
こちらの私の回答に、ジャンケンのソースをあげています。参考になれば幸いです。

私のソースでは、ジャンケンの手はクラスになっています。
手自体に強弱を持たせず、ルールが手の強弱を決めるという発想です。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/16 13:01 編集

    自分はオブジェクト指向はまだものに出来ていませんが、ジャンケンの手のクラスをどのようにあつかうのかが分かりました。補足ありがとうございました。

    キャンセル

checkベストアンサー

0

オブジェクトで書くというのは、
そのオブジェクトがどういう性格なのかを決めて表現する、って事です。

↓例えば、このような感じで、内部情報に手と名前を持たせて、名前を取得する機能getName、じゃんけんする機能pon、手を取得する機能showHandという「性格」を表現してみる。

public class Player {

    private int _hand;
    private final String _playerName;

    public static final int SCISSORS = 1;
    public static final int STONE  = 2;
    public static final int PAPER  = 3;

    public Player(String playerName) {
        this._playerName = playerName;
    }

    public String getName() {
        return _playerName;
    }

    public void pon() {
        Random r = new Random();
        this._hand = r.nextInt(3) + 1; 
    }

    public int showHand() throws Exception {
        if(this._hand == 0) {
            throw new Exception("本メソッドを呼び出す前にジャンケンをしてください");
        }
        if(this._hand < 1 || this._hand  > 3) {
            throw new Exception("グーチョキパー以外の手が選択されています");
        }

        return this._hand;
    }

}

ポイントとしては、ゲーム進行とオブジェクトにしたいものをきっちり分けてあげて、
実装していく時に、ゲーム進行に実装すべきか、オブジェクトに実装すべきか、
整理・判断しながら進めていくと良いと思います。

ちなみに、ご参考までにゲーム進行の実装↓

public class GameProcess {

    private static final int MEMBER = 3;

    public static void main(String[] args) throws Exception {
        List<Player> players = new ArrayList<>();

        for(int i = 0; i < MEMBER; i++) {
            players.add(new Player(String.format("プレイヤー%d", i+1)));
        }

        while(players.size() > 1) {
            janken(players);
            printVS(players);
            players = judgeJanken(players);
        }

        Player winner = players.get(0);
        System.out.println(String.format("勝者:%s", winner.getName()));
    }

    private static void janken(List<Player> players) { 

        for(int i = 0; i < players.size(); i++) {
            Player player = players.get(i);
            player.pon();
        }
    }

    private static void printVS(List<Player> players) throws Exception {
        for(int i = 0; i < players.size(); i++) {

            if(i > 0) {
                System.out.print(" vs ");
            }

            Player player = players.get(i);
            String handName = null;
            if(player.showHand() == Player.PAPER) {
                handName = "パー";
            }
            if(player.showHand() == Player.SCISSORS) {
                handName = "チョキ";
            }
            if(player.showHand() == Player.STONE) {
                handName = "グー";
            }
            System.out.print(String.format("%s[%s]", player.getName(), handName));
        }

        System.out.println();
    }

    private static List<Player> judgeJanken(List<Player> players) throws Exception {
        List<Player> winners = new ArrayList();

        for(int i = 0; i < players.size(); i++) {
            Player p1 = players.get(i);
            boolean winFlg = false;
            boolean loseFlg = false;
            for(int j = 0; j < players.size(); j++) {

                if(i == j) continue;

                Player p2 = players.get(j);

                switch (p1.showHand()) {
                    case Player.PAPER:
                        winFlg = (p2.showHand() == Player.STONE);
                        loseFlg = (p2.showHand() == Player.SCISSORS);
                        break;
                    case Player.SCISSORS:
                        winFlg = (p2.showHand() == Player.PAPER);
                        loseFlg = (p2.showHand() == Player.STONE);
                        break;
                    case Player.STONE:
                        winFlg = (p2.showHand() == Player.SCISSORS);
                        loseFlg = (p2.showHand() == Player.PAPER);
                        break;
                    default:
                        // アサーション
                        break;
                }
            }

            if(winFlg || (!winFlg && !loseFlg)) {
                winners.add(p1);
            }
        }

        return winners;
    }
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/14 16:32

    勝者を複数返すやり方は分かりました。ありがとうございます。
    ジャンケンの手をフィールドではなく、STONEやSCISSORSやPAPERをクラスにすることは可能でしょうか?書籍にはヒントとしてジャンケンの手をクラスにする、とあったのですが、どうですかね?どういう意味でクラスにするかを知りたかったんです。

    キャンセル

  • 2016/05/15 10:07 編集

    winners.addのところは
    省略記法をつかうとうまく動きませんでした。

    if((winFlg == true) && (loseFlg == false){
    と丁寧に書かなければなりませんでした。

    あと同じ人の手同士を比較しないようにif文でcontinueをしていましたけど、
    やっていること、やりたいことは理解できますが、同じ人の同じ手同士を比較してもwinFlgもloseFlgも(勝ちも負けも)つかないので、省きました。
    余計なロジックがあると動作時にJVMで誤動作しやすいので省きました。

    やり方は学ばせて頂きました。ありがとうございました。

    追加訂正
    正常に動作するコードの一部
    ●正
    if((winFlg == true) && (loseFlg != true)){
    ●正
    case PlayerB.STONE:
    if(p2 == PlayerB.SCISSORS){
    winFlg = true;
    }
    if(p2 == PlayerB.PAPER){
    loseFlg = true;
    }
    ●正
    if(i == j) continue;

    キャンセル

0

*コードは読んでいません。
アルゴリズムとしては、以下が綺麗なのでは?
1,3人が同じ手 引き分け
2,3人が違う手 引き分け
3,2人が同じ1人だけ違う手 2種類の手のどちらかが勝ち。
さくっと書ける気がします。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/14 10:19 編集

    質問が更新されたんで、なんかマヌケな回答になってしまいましたね^^;
    またコードを見ないで回答しますが、以下でどうでしょう。(ちょっと修正)
    1,3人の手を配列に突っ込む。重複を削除した新配列を用意。
    2,配列の値が1種類 → あいこ
    3,配列の値が2種類 → 組み合わせ判定
    4,配列の値が3種類 → あいこ
    5,元の配列に判定結果を反映
    java書かないんで、配列の処理、簡単に実装できなかったらすみません。

    キャンセル

0

すみません。
勘違いしていました。

同じ手を出しているプレイヤーを識別したいなら、

hands[i] != hands[j]

ここを変更してみてはどうでしょうか。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

そもそも手は3の3乗通り、つまり27通りしかないので全列挙しても良いと思いますよ。

プログラムイメージ(動作未確認)
const int STONE = 0, SCISSORS = 1, PAPER = 2;
const String result[3][3][3] = 
{"引き分け", //石、石、石の場合
 "勝者:a,b", //石、石、鋏の場合
 "勝者:c", //石、石、紙の場合
 "勝者:a,c"//石、鋏、石の場合
…以下略
};

System.out.println(result[PlayerA.hand][PlayerB.hand][PlayerC.hand]);

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/14 12:40

    ありがとうございます。理解できました。

    キャンセル

0

"java じゃんけん enum"
で google 検索すると、いろいろなプログアム例を見つけることができます。

例えば、こんなコードを参考にしてみては?
http://blog.goo.ne.jp/hishidama/e/ee5bacfceb7179b942d3392bb83e21a6

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    フィールド変数を使用せずにクラス型配列の中身を表示

    /*  * 引数、パラメータ、戻り値を使用して  * SubTest19クラスでフィールド変数を使用しないよう、  * 修正して下さい。  *   *   * また、SubTest

  • 解決済

    【janken.RandomTacitcs cannot be resolved to a type...

    以下コードの下から4行目の部分で janken.RandomTacitcs cannot be resolved to a type とエラーが出ます。 どのように修正すればいいで

  • 解決済

    java  じゃんけんゲーム

    コード java public class Player {          //定数、変数     int player = 5;                     

  • 解決済

    java  じゃんけんゲーム 順位付け

    Player player_main[] = new Player[player]; for(int i = 0; i < player; i++){     player_mai

  • 解決済

    java

    アプレットとアプリケーション?の違いについてお聞きしたいです。 私の解釈が間違っているかもしれませんが、 アプリケーションの場合mainメソッドがあり public class

  • 解決済

    メソッドを使ったプログラムを作りたいです

    前提・実現したいこと Javaのメソッドを使う問題を解いています。 問題は以下の通りです。 ↓ 好物を元に動物の名前と特徴を出力するプログラム  ・作成するクラス 

  • 解決済

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

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

  • 受付中

    ジャンケンゲーム

    ジャンケンゲームを作ってます。 <ルール> コンピュータに3回負けたらゲーム終了! 負けるまでゲームは続く! 数字を入力するとループが止まりません。 あと、winlo

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

  • Java

    14088questions

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

  • トップ
  • Javaに関する質問
  • 3人のジャンケンの勝敗判定で詰まりました。オブジェクト指向でジャンケンの手をクラスに変えるには?