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

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

ただいまの
回答率

90.47%

  • GsACADEMY

    14questions

    セカイを変えるエンジニア【GEEK】を養成する 授業料後払いのエンジニア養成学校です。 ①一流企業によるメンター指導 基本習得後は2ヶ月間メンターの個別指導でサービス完成を目指します。 ②480万円までの起業支援出資 起業志望者をサムライインキュベートが支援(審査あり)します。 ③初心者歓迎・授業料後払い 丸暗記ではなく、創りながら。初心者のための授業料後払い制度です。

  • JavaScript

    17008questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

JavaScript ランダムではない"じゃんけん"について

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,743

M_Kasahara

score 9

プログラミング入門で JavaScriptのじゃんけんゲームをつくっております。

これまでコンピュータの出す手は、ランダム関数を利用してきました。

これをコンピュータが過去の戦績を参照して、出す手を考える、とすることは可能でしょうか。

たとえば、
・全3回対戦
・1,2回戦はランダムで
・3回戦は、過去2回で人間が出さなかった手に勝てる手を出す
(過去に出さなかったので3回戦で出す可能性が高い..はず)

などです。

JavaScriptに、
sessionStorageやlocalStorageという機能があり
データをローカル環境に保存することまでは調べました。

この機能を使って、上記のような戦績分析型(?)は作れるものでしょうか。

機能の理解で初歩的なところから間違っておりましたらすみません。

よろしくお願い申し上げます。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+2

動作するものを作成してみました。
グー、チョキ、パーを0,1,2で、_historyに格納しています。
次の勝負では一番少ない手に勝つ手をコンピュータが選びます。comChoice()の箇所です。
動作確認する際は、UTF-8で保存してお試しください。

グーチョキパーの履歴を残したのは、3回連続の場合にどうするとか、一定のパターンにマッチしたらどうするとか、そういった戦術を後から組み込むことも考慮してみました。

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>じゃんけん</title>
<script>
(function(w,d){
    var _history = [];
    var _scoreCom = 0;
    var _scoreMan = 0;
    var _scoreDraw = 0;
    var _guCyoPar = ['グー','チョキ','パー'];
    var _judge = ['引き分け','勝ち','負け'];

    w.addEventListener('load',function(){init();},false);
    function init() {
        for (var i = 0; i < 3; i++) {
            (function(i){
                d.getElementById('hand' + i).addEventListener('click',function(){pon(i);},false);
            })(i);
        }
    }
    function comChoice() {
        if (_history.length < 2) {
            return Math.floor(Math.random() * 3);
        }
        var manHistory = countHistory();
        var few = (manHistory[0] < manHistory[1]) ? 0 : 1;
        few = (Math.min(manHistory[0],manHistory[1]) < manHistory[2]) ? few : 2;
        var com = (few == 0) ? 2 : few - 1;
        return com;
    }
    function countHistory() {
        var manHistory = [];
        manHistory[0] = 0;
        manHistory[1] = 0;
        manHistory[2] = 0;
        for (var i = 0; i < _history.length; i++) {
            manHistory[_history[i]]++;
        }
        return manHistory;
    }
    function pon(man) {
        var com = comChoice();
        _history.push(man);
        var manHistory = countHistory();
        var result = [];
        result.push('コンピュータ:' + _guCyoPar[com]);
        result.push('自分の手:' + _guCyoPar[man]);
        result.push('勝敗:' + _judge[judge(com,man)]);
        result.push('コンピュータの勝ち数:' + _scoreCom);
        result.push('自分の勝ち数:' + _scoreMan);
        result.push('引き分け数:' + _scoreDraw);
        result.push('自分のグーの数:' + manHistory[0]);
        result.push('自分のチョキの数:' + manHistory[1]);
        result.push('自分のパーの数:' + manHistory[2]);
        output(result);
    }
    function output(result) {
        d.getElementById('output').innerHTML = '';
        for (var i = 0; i < result.length; i++) {
            var div = d.createElement('div');
            div.innerHTML = result[i];
            d.getElementById('output').appendChild(div);
        }
    }
    function judge(com,man) {
        if (com == man) {
            _scoreDraw++;
            return 0;
        }
        if (com == 0 && man == 2 || com == 1 && man == 0 || com == 2 && man == 1) {
            _scoreMan++;
            return 1;
        } else {
            _scoreCom++;
            return 2;
        }
    }
})(window,document);
</script>
</head>
<body>
<h1>じゃんけん</h1>
<button type="button" id="hand0">グー</button>
<button type="button" id="hand1">チョキ</button>
<button type="button" id="hand2">パー</button>
<div id="output"></div>
</body>
</html>
`

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/05/08 20:14


    ありがとうございました。
    自分でもうまく動かすことができました。

    昨日、今日とリファレンス本を片手に
    読み解いていました。

    正直申しあげて、
    まだ理解しきれていないところもありますが、
    引き続き取り組んでいきます。

    いずれはグーチョキパーの履歴を使って、
    さらに新しい戦術パターンを組み込めるところまで
    できるようなりたいです。


    漠然とこんなことが出来たら良いなと思って投げかけたところ
    わずか数時間で、実際にカタチにできる方がいるのに驚きました。

    プログラミングの威力をあらためて実感しています。

    夜分にも関わらず
    こんなに長いコードを書いて下さり
    本当にありがとうございました。

    キャンセル

+2

作れるか作れないかで言えば、作れるでしょう。
・3回戦は、過去2回で人間が出さなかった手に勝てる手を出す
これを素直にコード化すればよいだけです。

例えば、ユーザーの出した手が一度目はグー、二度目がパーだとして
var selected = [];
selected.push("グー");
selected.push("パー");
などと書けます。

3回目のコンピュータの手は
// それぞれの出した回数を求める
var gu_count = selected.filter(function(e){ return e === "グー" }).length;
var ck_count = selected.filter(function(e){ return e === "チョキ" }).length;
var pa_count = selected.filter(function(e){ return e === "パー" }).length;

// 選ばれた回数が一番少ないものを求める
// name に手を、count に選ばれた回数を持ったオブジェクトの配列を作る
var min = [
    { name: "グー",   count: gu_count },
    { name: "チョキ", count: ck_count },
    { name: "パー",   count: pa_count }
]
// count の少ない順にソート
.sort(function(a, b){
    return a.count - b.count;
})[0]; // 0番目、つまり一番少なかった手のオブジェクトを選択する

// 一番少なかったもの(min.name) が
// 「グー」なら「パー」
// 「チョキ」なら「グー」
// 「パー」なら「チョキ」
// を選択する
var computersNext;
switch (min.name) {
    case "グー":
        computersNext = "パー"; break;
    case "チョキ":
        computersNext = "グー"; break;
    case "パー":
        computersNext = "チョキ"; break;
}
こんな感じですか。上記はあくまで例なので、方法なら他にもいくらでもあるはずです。
たぶん私なら「グーを0」「チョキを1」「パーを2」のように数値化して計算すると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/05/08 19:59


    丁寧にコードを教えてくださり
    ありがとうございます。

    '//'で各コードの意味するところを
    書いていただいたのがとても助かりました。

    昨日、今日とリファレンス本を片手に
    一行づつ読み解いていきました。

    手と回数を持ったオブジェクトの配列を作り
    count の少ない順にソートし
    一番少なかった手のオブジェクトを選択する

    というのは全く思いつきませんでした。

    まだ教えていただいたコードを読み解くので精一杯ですが
    とても勉強になりました。

    心より御礼申し上げます。

    キャンセル

+2

こんにちは。

ご質問の中の
・3回戦は、過去2回で人間が出さなかった手に勝てる手を出す 
の実装とは、ちょっと違うことをレスします。

コンピュータの勝率をアップさせることを、このプログラムの
性能向上と考えると、人がじゃんけんをするときに、どういう
クセがあるか?というデータを「戦績分析」するロジックに
いろいろ組み込んでいくことになると思いますが、
こんなまとめサイトがありました。

じゃんけんで勝つ確率を飛躍的にあげるコツ

上記から行けるサイトのひとつ

ジャンケンで勝つ確率を上げる簡単な方法

には、以下のような調査結果が書かれています。

2009年6月20日の日本経済新聞土曜版「日経プラスワン」に、桜美林大学
の芳沢光雄教授による「ジャンケンに関する研究結果」が掲載されました。
芳沢教授が学生725人を集めて、のべ11567回ジャンケンさせたところ、
人間の手の出し方はグー、キョキ、パーそれぞれ1/3とはならなかったそうです。
当時の記事には、以下のように書かれています。

最も多いのはグーで4054枚(35.0%)、次はパーで3849回(33.3%)、
最も少ないのはチョキで、3664回(31.7%)と、かなりのバラツキが出た。
統計的にはグーが出やすく、チョキが出にくい。だから、パーを出せば
勝ちやすいというわけだ。

上記のようなデータもふまえつつ、とはいえ、実際に手を出してやる
じゃんけんと、WEBの画面で選ぶのとはまた違うので、たくさんの対戦
のデータを蓄積して、どういうパターンで出せば人間に勝てるのかの
戦略を、(流行り言葉でいってみれば)機械学習的に向上させていく
ようなロジックを考えるのも面白そうですね。

以上、ちょっとした思いつきでした。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/05/08 20:54


    ひきつづきありがとうございます。

    リンク先のサイトをさっそく拝見しました。
    これは面白いですね。

    実際に手をだしてやるじゃんけんで、
    所作の多いチョキが少なくなるのは
    なんとなく実感できます。

    おなじように
    WEBの画面で左右に3つボタンが並んでいたら
    無意識に一番左のボタンを多くクリックしてしまいそうです。
    ひじを開かず右手のマウスを動かす距離が短くてすむからです。


    「機械学習」とか「人工知能」という言葉には
    字面からひとを惹きつける力があります。

    わたしも昨年から今年にかけて
    本を読んだり、NHKスペシャルを見たりして、かなり素直に影響を受けています。

    今回、じゃんけんのプログラムをつくろうとしたとき
    最初に考えたのが「コンピュータが過去の戦績を分析して手をだす」
    だったのはその影響かもしれません。

    考えたロジックを
    実際にカタチにできる力を早く身につけたいです。

    ありがとうございました





    キャンセル

0

じゃんけんの手を出すパターンは、個人によって違うでしょう。
また、あまり単純な思考だとすぐにはめられかねません。
こういった時に有効なのは、どのように考えるか自体を、過去のデータからコンピュータに学習させる方法です。
パーセプトロンやニューラルネットワークと呼ばれ、対戦相手に応じて学習する能力も授けることができます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

関連した質問

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

  • GsACADEMY

    14questions

    セカイを変えるエンジニア【GEEK】を養成する 授業料後払いのエンジニア養成学校です。 ①一流企業によるメンター指導 基本習得後は2ヶ月間メンターの個別指導でサービス完成を目指します。 ②480万円までの起業支援出資 起業志望者をサムライインキュベートが支援(審査あり)します。 ③初心者歓迎・授業料後払い 丸暗記ではなく、創りながら。初心者のための授業料後払い制度です。

  • JavaScript

    17008questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。