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

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

ただいまの
回答率

87.61%

ジャンケン:相手の手のパターンを判別する方法

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 3,127

score 13

前提・実現したいこと

JAVAでジャンケンのプログラムを作っています。
相手は様々なパターンで手を繰り出してきます。
こちらが入力してジャンケンをするプログラムではなく、こちらも自動で手を返すプログラムを組んで戦わせる形です。

その際、グーで勝つと3ポイント、チョキは4ポイント、パーは5ポイント入ります。
一万回繰り返し、最後にポイントの高かったほうが勝ち。

出来ないのは、こちらの出した手に勝てる手を次のターンに出す(例えばこちらがグーのとき、相手は次のジャンケンのときにパーを出す)相手(A)等の判別方法です。
こちらは一つのプログラムの中で、先述したAのような相手、こちらの出した手と全く同じものを次のターンに出す相手B、完全ランダムに手を出す相手Cとジャンケンをしなくてはいけません。

戦う相手はランダムなため、しっかりと判別できないと負けてしまう事も考えられます。
どうすればA,B,Cの相手を判別できるでしょうか?

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

エラーメッセージ

該当のソースコード

改変不可能
import java.util.*;

class J1Practice {
    static int Win1 = 0, Win2 = 0;
    static int Score1 = 0, Score2 = 0;

    static final int GUU   = 1;
    static final int TYOKI = 2;
    static final int PAA   = 3;

    public static void main(String args[]){
        int k, p1, p2, tmp;

        // プレイヤー1のオブジェクトを生成
        J1Fighter f1 = new Parrot();
        // プレイヤー2のオブジェクトを生成
        J1Fighter f2 = new Smart();

        p1 = p2 = tmp = 0;
        // 1万回じゃんけんを実行
        for (k = 0; k < 10000; k++ ) {
            p1 = f1.Janken(k, p2);        // プレイヤー1の手
            p2 = f2.Janken(k, tmp);        // プレイヤー2の手
            tmp = p1;

            if ((p1 < GUU) || (p1 > PAA)) {    // プレイヤー1の反則負け
                Score2 = 99999;
            }
            if ((p2 < GUU) || (p2 > PAA)) {    // プレイヤー2の反則負け
                Score1 = 99999;
            }
            if ((Score1 == 99999) || (Score2 == 99999)) break;

            // じゃんけんの判定
            if (p1 == GUU) {
                if (p2 == TYOKI) {
                    ++Win1;
                    Score1 += 3;
                } else if (p2 == PAA) {
                    ++Win2;
                    Score2 += 5;
                }
            } else if (p1 == TYOKI) {
                if (p2 == PAA) {
                    ++Win1;
                    Score1 += 4;
                } else if (p2 == GUU) {
                    ++Win2;
                    Score2 += 3;
                }
            } else if (p1 == PAA) {
                if (p2 == GUU) {
                    ++Win1;
                    Score1 += 5;
                } else if (p2 == TYOKI) {
                    ++Win2;
                    Score2 += 4;
                }
            }
        }

        if (Score1 > Score2) System.out.println(f1.getName() + "の勝ちです");
        else if (Score1 < Score2) System.out.println(f2.getName() + "の勝ちです");
        else System.out.println("引き分けです");

        System.out.println("       " + f1.getName() + " vs " + f2.getName());
        System.out.println("Score  [ " + Score1 + " : " + Score2 + " ]");
        System.out.println("W i n  [ " + Win1   + " : " + Win2 + " ]" );
    }
}

こちらが改変できるプログラム
class Player1 extends J1Fighter {
        int op[] = new int[10000];
        int g,c,p;
        int i,r;

    Player1() {
        setName("Player1");
        g = c = p = 0;
        for(i=0; i<10000; i++)op[i]=0;
    }

    int Janken(int no, int last) {
        }
}

こちらは改変できませんが一応
class J1Fighter {

    static final int GUU   = 1;
    static final int TYOKI = 2;
    static final int PAA   = 3;

    private String name = null;
    private String pict = null;

    int Janken(int no, int last) {
        return(0);    // 反則負け
    }

    void setName(String n) {
        name = n;
    }

    String getName() {
        return name;
    }

    void setPict(String f) {
        pict = f;
    }

    String getPict() {
        return pict;
    }
}

試したこと

課題に対してアプローチしたことを記載してください

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

より詳細な情報

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+5

基本はずっとパーで勝ち続けられれば高い点数になります。
最も高い点数が出せるのは相手がCのランダムで全てグーを出し、こちらがずっとパーを出した場合になります。
しかしながらそれは現実的ではありませんので、できるだけ早く相手を確定し勝ち続けられれば最も良いことになります。
つまりできるだけ高い点数を出そうと思うと、相手がAかBだとできるだけ早く確定させ、相手の手に対応した手を出し続ける。もし相手がCだと確定したら、そのタイミングでパーを出し続ける。という戦略が最も良いことになります。

それを前提に考えてみますが、ちなみにA,Bは初手に何を出すのでしょうか?

■1戦目
1-1.最初にパーを出す

■2戦目
2-1.次もパーを出す。相手は1戦目の自分の手によって手を決めてくる。
※1戦目の相手の手は、Cはランダムだとしても、A,Bが何を出すかが分からないので情報不足。ここでは、A,Bも1戦目はランダムで手を出してくるものとし、相手が自分の手によって出す手を決定するのは2戦目終了以降である3戦目以降に判別できるとしています。1戦目に相手が出す手にルールがあるのであればそれにしたがって2戦目の処理は変化します。

■3戦目
3-1.手を出す前に相手の手が分かる。受け取った相手の手で相手を判定する。
3-2.相手がグーを出した場合 :C確定。Cが確定したので以後ずっとパーを出し続ける。
3-3.相手がパーを出した場合 :BかC。Bだと仮定し次はチョキを出す。
3-4.相手がチョキを出した場合:AかC。Aだと仮定し次はグーを出す。

■4戦目以降
3戦目同様のロジックを用いて、前に自分と相手が出した手を判定しながら相手を確定させ、次の手を決定する。

という流れになると思います。
自分が3戦目に勝てたらC確定、そのあたりの判定条件を掴めるかがポイントかと思います。

Player17のJankenメソッドは第2引数に相手の1つ前の手を受け取ります。
そこで上記の判定を入れて自分の手を決めていくことになりますね。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+2

10秒ほど考えました。
質問内のコードは読んでいません。

1.1回目に適当な手を出し判別。
2.ABに該当した場合は、2回目以降はそれぞれに勝てる手を出す。
3.ABに該当しなかった場合(C確定)は、2回目以降はずっとパーを出す。

【追記】
4.2の途中でC確定した場合は3に切り替える。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

適当な手を出して

  • AかC
  • BかC
  • C

のどれに該当するか判定

XかCパターンの場合はXに勝てる手を出す。
途中でCに該当した場合パーに切り替え

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

相手のアルゴリズムの判定方法自体は、自分自身の次の手をAのアルゴリズムでやることで
勝ちがつづけば相手はBと判定
アイコがつづけば相手はAと判定
上記以外だったらC判定です。

A、Bなら勝ち確定です。

で、相手がCだったらパーを出し続けるのがセオリーですが、
確立に偏りがない前提なので、あまりに負けがつづくようなら、
こちらもグーを出すように別のアルゴリズムにしないとですね。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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