プログラミング入門で JavaScriptのじゃんけんゲームをつくっております。
これまでコンピュータの出す手は、ランダム関数を利用してきました。
これをコンピュータが過去の戦績を参照して、出す手を考える、とすることは可能でしょうか。
たとえば、
・全3回対戦
・1,2回戦はランダムで
・3回戦は、過去2回で人間が出さなかった手に勝てる手を出す
(過去に出さなかったので3回戦で出す可能性が高い..はず)
などです。
JavaScriptに、
sessionStorageやlocalStorageという機能があり
データをローカル環境に保存することまでは調べました。
この機能を使って、上記のような戦績分析型(?)は作れるものでしょうか。
機能の理解で初歩的なところから間違っておりましたらすみません。
よろしくお願い申し上げます。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
こんにちは。
ご質問の中の
・3回戦は、過去2回で人間が出さなかった手に勝てる手を出す
の実装とは、ちょっと違うことをレスします。
コンピュータの勝率をアップさせることを、このプログラムの
性能向上と考えると、人がじゃんけんをするときに、どういう
クセがあるか?というデータを「戦績分析」するロジックに
いろいろ組み込んでいくことになると思いますが、
こんなまとめサイトがありました。
上記から行けるサイトのひとつ
には、以下のような調査結果が書かれています。
2009年6月20日の日本経済新聞土曜版「日経プラスワン」に、
桜美林大学
の芳沢光雄教授による「ジャンケンに関する研究結果」が掲載されました。
芳沢教授が学生725人を集めて、のべ11567回ジャンケンさせたところ、
人間の手の出し方はグー、キョキ、パーそれぞれ1/3とはならなかったそうです。
当時の記事には、以下のように書かれています。
最も多いのはグーで4054枚(35.0%)、次はパーで3849回(33.3%)、
最も少ないのはチョキで、3664回(31.7%)と、かなりのバラツキが出た。
統計的にはグーが出やすく、チョキが出にくい。だから、パーを出せば
勝ちやすいというわけだ。
上記のようなデータもふまえつつ、とはいえ、実際に手を出してやる
じゃんけんと、WEBの画面で選ぶのとはまた違うので、たくさんの対戦
のデータを蓄積して、どういうパターンで出せば人間に勝てるのかの
戦略を、(流行り言葉でいってみれば)機械学習的に向上させていく
ようなロジックを考えるのも面白そうですね。
以上、ちょっとした思いつきでした。
投稿2015/05/06 18:34
編集2015/05/07 07:40総合スコア9058
0
ベストアンサー
動作するものを作成してみました。
グー、チョキ、パーを0,1,2で、_historyに格納しています。
次の勝負では一番少ない手に勝つ手をコンピュータが選びます。comChoice()の箇所です。
動作確認する際は、UTF-8で保存してお試しください。
グーチョキパーの履歴を残したのは、3回連続の場合にどうするとか、一定のパターンにマッチしたらどうするとか、そういった戦術を後から組み込むことも考慮してみました。
lang
1<!doctype html> 2<html lang="ja"> 3<head> 4<meta charset="utf-8"> 5<title>じゃんけん</title> 6<script> 7(function(w,d){ 8 var _history = []; 9 var _scoreCom = 0; 10 var _scoreMan = 0; 11 var _scoreDraw = 0; 12 var _guCyoPar = ['グー','チョキ','パー']; 13 var _judge = ['引き分け','勝ち','負け']; 14 15 w.addEventListener('load',function(){init();},false); 16 function init() { 17 for (var i = 0; i < 3; i++) { 18 (function(i){ 19 d.getElementById('hand' + i).addEventListener('click',function(){pon(i);},false); 20 })(i); 21 } 22 } 23 function comChoice() { 24 if (_history.length < 2) { 25 return Math.floor(Math.random() * 3); 26 } 27 var manHistory = countHistory(); 28 var few = (manHistory[0] < manHistory[1]) ? 0 : 1; 29 few = (Math.min(manHistory[0],manHistory[1]) < manHistory[2]) ? few : 2; 30 var com = (few == 0) ? 2 : few - 1; 31 return com; 32 } 33 function countHistory() { 34 var manHistory = []; 35 manHistory[0] = 0; 36 manHistory[1] = 0; 37 manHistory[2] = 0; 38 for (var i = 0; i < _history.length; i++) { 39 manHistory[_history[i]]++; 40 } 41 return manHistory; 42 } 43 function pon(man) { 44 var com = comChoice(); 45 _history.push(man); 46 var manHistory = countHistory(); 47 var result = []; 48 result.push('コンピュータ:' + _guCyoPar[com]); 49 result.push('自分の手:' + _guCyoPar[man]); 50 result.push('勝敗:' + _judge[judge(com,man)]); 51 result.push('コンピュータの勝ち数:' + _scoreCom); 52 result.push('自分の勝ち数:' + _scoreMan); 53 result.push('引き分け数:' + _scoreDraw); 54 result.push('自分のグーの数:' + manHistory[0]); 55 result.push('自分のチョキの数:' + manHistory[1]); 56 result.push('自分のパーの数:' + manHistory[2]); 57 output(result); 58 } 59 function output(result) { 60 d.getElementById('output').innerHTML = ''; 61 for (var i = 0; i < result.length; i++) { 62 var div = d.createElement('div'); 63 div.innerHTML = result[i]; 64 d.getElementById('output').appendChild(div); 65 } 66 } 67 function judge(com,man) { 68 if (com == man) { 69 _scoreDraw++; 70 return 0; 71 } 72 if (com == 0 && man == 2 || com == 1 && man == 0 || com == 2 && man == 1) { 73 _scoreMan++; 74 return 1; 75 } else { 76 _scoreCom++; 77 return 2; 78 } 79 } 80})(window,document); 81</script> 82</head> 83<body> 84<h1>じゃんけん</h1> 85<button type="button" id="hand0">グー</button> 86<button type="button" id="hand1">チョキ</button> 87<button type="button" id="hand2">パー</button> 88<div id="output"></div> 89</body> 90</html>
投稿2015/05/06 18:01
編集2015/05/06 18:19総合スコア1151
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
作れるか作れないかで言えば、作れるでしょう。
・3回戦は、過去2回で人間が出さなかった手に勝てる手を出す
これを素直にコード化すればよいだけです。
例えば、ユーザーの出した手が一度目はグー、二度目がパーだとして
lang
1var selected = []; 2selected.push("グー"); 3selected.push("パー");
などと書けます。
3回目のコンピュータの手は
lang
1// それぞれの出した回数を求める 2var gu_count = selected.filter(function(e){ return e === "グー" }).length; 3var ck_count = selected.filter(function(e){ return e === "チョキ" }).length; 4var pa_count = selected.filter(function(e){ return e === "パー" }).length; 5 6// 選ばれた回数が一番少ないものを求める 7// name に手を、count に選ばれた回数を持ったオブジェクトの配列を作る 8var min = [ 9 { name: "グー", count: gu_count }, 10 { name: "チョキ", count: ck_count }, 11 { name: "パー", count: pa_count } 12] 13// count の少ない順にソート 14.sort(function(a, b){ 15 return a.count - b.count; 16})[0]; // 0番目、つまり一番少なかった手のオブジェクトを選択する 17 18// 一番少なかったもの(min.name) が 19// 「グー」なら「パー」 20// 「チョキ」なら「グー」 21// 「パー」なら「チョキ」 22// を選択する 23var computersNext; 24switch (min.name) { 25 case "グー": 26 computersNext = "パー"; break; 27 case "チョキ": 28 computersNext = "グー"; break; 29 case "パー": 30 computersNext = "チョキ"; break; 31}
こんな感じですか。上記はあくまで例なので、方法なら他にもいくらでもあるはずです。
たぶん私なら「グーを0」「チョキを1」「パーを2」のように数値化して計算すると思います。
投稿2015/05/06 17:08
総合スコア870
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/05/08 10:59
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/05/08 11:54