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

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

新規登録して質問してみよう
ただいま回答率
85.49%
JavaScript

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

Q&A

解決済

2回答

1762閲覧

Javascript ゲーム フィッシャーイェーツ乱数

williamsArk

総合スコア46

JavaScript

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

0グッド

1クリップ

投稿2019/02/15 13:58

以前似たような質問をさせていただきました。重複しない乱数処理を以下の国旗ゲームで練習しています。
おかげさまでsortを用いた乱数は使えるようになりましたが、この乱数は穴があると教えていただきました。なので、フィッシャーイェーツの乱数を練習したいのですが、以下のようにすると機能しません。おそらく以下のShuffleとsetQuestionに問題があると思うのですが、アドバイスいただけますか?

var Shuffle = function(arr) { var i, j, temp; arr = flags.slice(); i = flags.length; if (i === 0) { return arr; } while (--i){ j = Math.floor(Math.random() * (i + 1)); temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } return arr; } function setQuestion() { if(flags.length <= 0) { alert('お疲れ様でした。問題は以上です。あなたのスコアは ' + score + '点です。') } flag = Shuffle(flags); question.children[0].src = 'img/' + flag[0]; answer = flag[1]; }

念の為、この下に全体コードを貼らせていただきます。

(function() { 'use strict'; var question = document.getElementById('question'); var btn = document.getElementById('btn'); var input = document.getElementById('input'); var check = document.getElementById('check'); var timerLabel = document.getElementById('timer'); var scoreLabel = document.getElementById('score'); var pass = document.getElementById('pass'); var answer = ''; var score = 0; var timerId; var isPlaying = false; var timer; var flag; var previous = []; var flags = [ ['Nepal.png', 'ネパール'], ['India.png', 'インド'], ['Netherland.png', 'オランダ'], ['Chili.png', 'チリ'], ['Morocco.png', 'モロッコ'], ['Luxembourg.png', 'ルクセンブルク'], ['Singapore.png', 'シンガポール'], ['Pakistan.png', 'パキスタン'], ['Azerbaijan.png', 'アゼルバイジャン'], ['Jamaica.png', 'ジャマイカ'], ['Belgium.png', 'ベルギー'], ['Guana.png', 'ガーナ'], ['SierraLeone.png', 'シエラレオネ'], ['Korea.png','韓国'], ['Japan.png','日本'], ['China.png','中国'], ['Mongolia.png','モンゴル'], ['Philippines.png', 'フィリピン'], ['Italy.png', 'イタリア'], ['Egypt.png', 'エジプト'], ['Australia.png','オーストラリア'], ['NewZealand.png', 'ニュージーランド'], ].sort(() => Math.random() - 0.5); function init() { isPlaying = false; timer = 100; score = 0; scoreLabel.innerHTML = ''; scoreLabel.className = ''; timerLabel.className = ''; timerLabel.innerHTML = timer; btn.className = ''; check.className = 'invisible'; } init(); function updateTimer() { timerId = setTimeout(function() { timer--; if(timer <=10) { timerLabel.classList.add('danger'); } timerLabel.innerHTML = timer; if(timer <= 0) { alert('Game Overです。お疲れ様でした。あなたのスコアは ' + score + '点です。'); clearTimeout(); init(); return; } updateTimer(); }, 1000); } var Shuffle = function(arr) { var i, j, temp; arr = flags.slice(); i = flags.length; if (i === 0) { return arr; } while (--i){ j = Math.floor(Math.random() * (i + 1)); temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } return arr; } function setQuestion() { if(flags.length <= 0) { alert('お疲れ様でした。問題は以上です。あなたのスコアは ' + score + '点です。') } flag = Shuffle(flags); question.children[0].src = 'img/' + flag[0]; answer = flag[1]; } btn.addEventListener('click', function() { if (!isPlaying) { btn.classList.add('invisible'); check.classList.remove('invisible'); isPlaying = true; updateTimer(); setQuestion(); } }); check.addEventListener('click', function() { if(input.value !== '' && isPlaying) { score += (input.value === answer)? 1: -1; if(score < 0) { scoreLabel.classList.add('danger'); } else { scoreLabel.className = ''; } scoreLabel.innerHTML = score; input.value = ''; input.focus(); setQuestion(); } }); pass.addEventListener('click', function() { if(!isPlaying) { return; } setQuestion(); }); })();

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2019/02/16 00:38

『機能しません』とは具体的には何が起きていますか? エラーメッセージがあるならエラーメッセージをご提示ください。
Lhankor_Mhy

2019/02/16 01:03

Netherland.png が存在しない、というエラーのようです。 『機能しません』とは具体的には「画像が見えない」ということだったのですか?
williamsArk

2019/02/16 01:15

すいません。そういうことです。うまく画像が表示されません。フィーシャーのやり方をするまでは映ってたので多分何らかがおかしいと思います
Lhankor_Mhy

2019/02/16 01:19

それとは関係ないだろうなあ、という感じがしてます。 あと、エラーメッセージ内に本名っぽいものが混じってますが、大丈夫ですか?
williamsArk

2019/02/16 01:22

基本的に気にしませんが、一応削除依頼させていただきました。ご指摘ありがとうございました
think49

2019/02/16 02:01

コメントは編集出来ます。履歴も参照されません。
think49

2019/02/16 02:52

"williamsArk 2019/02/16 09:58 編集 あ" では意味が分かりません。後で読んだ人が時系列を追えるように修正して下さい。この質疑応答は質問者のみが参考にするものではなく、共有情報となります。
williamsArk

2019/02/16 03:08

承知いたしました。覚えている限り訂正しました。
guest

回答2

0

js

1flag = Shuffle(flags);

この部分ですが、Shuffle関数の戻り値は、

js

1 arr = flags.slice(); 2//... 3 return arr;

とあるように、flagsをシャッフルしたものであり、flags[0]ではないです。
なので、flag[0]の中身に'Nepal.png'を期待しているかもしれませんが、そうではなくて['Nepal.png', 'ネパール']が入っています。

解決方法ですが、flag[0][0]を参照するか、Shuffle関数の戻り値をarr[0]にするといいかもしれません。

ただ、これ、たぶん、普通の乱数と同じくかぶるんじゃないですか?

投稿2019/02/16 01:34

Lhankor_Mhy

総合スコア36057

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

williamsArk

2019/02/16 01:51

おおすごい。動きました。ありがとうございました。ただ確かに重複してしまいますね。spliceとか必要でしょうかね
Lhankor_Mhy

2019/02/16 03:02

まあ、そんな感じですけど、arr 変数に破壊的操作をしても Shuffle 関数内でシャローコピーをしているので無駄っぽいですね。仮引数をそのまま使う感じなら上手くいくのではないでしょうか。
think49

2019/02/16 03:48

現在の流れで非破壊ソートを期待するなら、シャローコピーの代わりに Array#map で flags[0][0] を複製する方法も有ります。 個人的には、データの持ち方を二次元配列から new Map に変更して、Map#values() から配列化してソートする方法を採用しますが…。
williamsArk

2019/02/16 04:45

二次元配列からnew Mapなど難易度が高そうな言葉が多いですね。一個一個噛み砕いていく必要がありそうです。ありがとうございました。
Lhankor_Mhy

2019/02/16 05:07

> think49さん どっちが早いのか興味深いところですね。 Arrayの実装が、参照のリストや配列であるなら、さほど差がつかないような気もします。 > williamsArkさん ややこしい話をしてすみません。 要は、 arr = flags.slice(); ↑これを削除して、 return arr.pop(); ↑戻り値をこうすれば動くんじゃないかな、という話です (動作確認してません)
guest

0

ベストアンサー

関数 setQuestion が呼ばれるたびにシャッフルする必要はない。関数 init で済ませる
配列 flags をシャッフルして flag に配列としてコピーしているのよね。
なので flags.length ではなくflag.length を評価するようにする
変数 anser に代入するときは、元の配列である flag から1つ減らす必要がある
[,anser] = flag.shift ();
みたいにする。

余計なことかもしれないが、
関数 Shuffle の変数 i の使い方に無駄がある。
グローバル変数が沢山あって脳内で解釈しながら理解するのが辛い。
プログラムコードにインデントしてほしい。
HTMLも見てみたいな。
img の src に代入するときは alt にも代入してほしい。
すると画像がなくても確認できるから。(本当はやらなきゃいけないこと)
音声でゲームをしている人には、聞こえちゃいますがw

さらに余計なこと、
もし旗が1万種類あったとして、旗の情報を1万個並び替えるより、インデックス番号だけの
配列をソートしたほうが負担が少ないかな。

どうでもよいこと、
ソートによるシャッフルの件だけど、偏りがあるのはしょうがない。
それを逆手にとって出題傾向をなんとなくだけど制御できるのではないか?
旗の数が増えると効率が落ちるけれど、それで十分だと、私も思います。

冒頭で'use strict'という見慣れない文字列を見たが、それらしいの使ってる?w

ちょっと興味がわいたのでソートによるシャッフルを調べてみた。
簡単な問題順に定義して、並び替えると出題傾向を弄れる?
コードがやっつけなのは勘弁!(今になってSVGが習い立てなもんで)
ちょろめと火狐では大きく違うね!こりゃ~つかえないか?

html

1<!DOCTYPE html> 2<html lang="ja"> 3<title>?</title> 4<meta charset="utf-8"> 5<style> 6table tbody:first-of-type { display: none; } 7</style> 8 9<body> 10 11<table border="1"> 12 <caption><em>arry.sort (()=>Math.random() - X)</em> のX値による0番の移動した出現分布の累積 13 <tbody><tr><th><td><svg width="800" height="120" xmlns="http://www.w3.org/2000/svg"></svg> 14</table> 15 16<script> 17const 18 N = 100, 19 A = Array (N).fill().map ((_,i)=>i), 20 S = 0.3, 21 E = 0.7, 22 R = 1000,//繰り返し回数 23 C = 0, // 0番がどこに移動するか 24 25 table = document.querySelector ('table'), 26 tbody = table.querySelector ('tbody:first-of-type'), 27 rect = document.createElementNS ('http://www.w3.org/2000/svg', 'rect'), 28 setAtr = (e,o)=>[...Object.entries(o)].forEach(([a,b])=>e.setAttribute(a,b)); 29 30setAtr (rect, { width: 8, style: 'fill:rgb(0,0,255)'}); 31 32function sikakuka (n, ary) { 33 let tb = table.appendChild (tbody.cloneNode (true)); 34 let [th, svg] = tb.querySelectorAll ('th, svg'); 35 th.textContent = "x = " + n.toFixed (3); 36 ary.forEach ((a, i) =>setAtr (svg.appendChild (rect.cloneNode (false)), {x: i*8, y:120-a, height: a})); 37} 38 39 40for (let i = S; i < E; i += .025) { 41 let c = Array (N).fill (0); 42 for (let j = 0; j < R; j++) { 43 let a = A.slice (); 44 a.sort (()=>Math.random () - i); 45 c[a.indexOf (C)]++; 46 } 47 sikakuka (i, c); 48} 49 50</script> 51

投稿2019/02/15 22:20

編集2019/02/16 07:08
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

williamsArk

2019/02/16 00:57

すいません。詳細な説明ありがとうございました。ただ用語が難しいですね。もしよろしければaltの代入についてもう少し教えていただけませんか?
退会済みユーザー

退会済みユーザー

2019/02/16 02:45

think49 さん、ご丁寧にありがとね。<babu_**2..... ^^; ステップアップしてる質問者さんを静観せずに居られなくなって、ついでしゃばった。 HTMLではその構造にも使われている要素にも意味を持たせるべき。 その使われている画像がいったい何を意味するのか?明示させなければならない。 視覚障害者だって何かしらのブラウザ等で聞いているかもしれないでしょ!?
williamsArk

2019/02/16 03:10

お二方ともかなり役立つ情報ありがとうございました。後ほど確認させていただきまして、また質問がありましたらお尋ねするかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問