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

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

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

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

Q&A

解決済

3回答

2443閲覧

重複しない乱数の数値を一つずつ取り出すにはどうしたらよろしいでしょうか?

whitehorse85921

総合スコア34

JavaScript

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

0グッド

0クリップ

投稿2020/07/30 04:45

前提・実現したいこと

例えば、
let num = Math.floor(Math.random() * 5 );とするとランダムな数値を一つずつ
取り出すように、重複しないランダムな数値を一つずつ取り出して使いたいのですが、
どうしたらよろしいでしょうか?
どなたか詳しい方ご教示お願いいたします。

■■な機能を実装中に以下のエラーメッセージが発生しました。

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

shift()を使うと、ランダムな重複しない配列から最初の方の数値を削除するため、
ひとつずつ表示できても、デバッグしていくとword = words[nums.shift()];のnumsの
要素数自体減ってしまいます。

エラーメッセージ

該当のソースコード

JavaScript

1const words = [ 2 'dream', 3 'sky', 4 'blue', 5 'middle', 6 'cloud', 7 ]; 8 9 const nums = [0,1,2,3,4]; 10 11 let word; 12 let r; 13 14 function question() { 15 for (let i = nums.length -1; i > 0; i--) { 16 r = Math.floor(Math.random() * (i + 1)); 17 18 let tmp = nums[i]; 19 nums[i] = nums[r]; 20 nums[r] = tmp; 21 } 22 let i; 23 word = words[nums.shift()]; 24 }

試したこと

shift()以外のメソッドを探したのですが、ほとんど要素を返すものではなかったため、うまくいきませんでした。

ここにより詳細な情報を記載してください。

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

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

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

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

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

yambejp

2020/07/30 04:51

> 重複しないランダムな数値 重複しない連続する0からはじまる整数をランダムにほしいのでしょうか?
whitehorse85921

2020/07/30 04:54

yambejpさん。 ありがとうございます。 0から始まる重複しないランダムな数値は出来ているので、その数値を一つずつ取り出して使いたいです。 分かりにくくてすみません。
ozwk

2020/07/30 05:55 編集

真の目的はwordsから1つずつランダムに値を取り出すことではありませんか?
whitehorse85921

2020/07/30 06:06

ozwkさん。 ありがとうございます。 はい、仰る通りでございます。
guest

回答3

0

そんなあなたにジェネレータはいかがですか?

js

1 function* question_g() { 2 for (let i = nums.length -1; i > 0; i--) { 3 r = Math.floor(Math.random() * (i + 1)); 4 5 let tmp = nums[i]; 6 nums[i] = nums[r]; 7 nums[r] = tmp; 8 } 9 for (let x of nums) { 10 yield words[x]; 11 } 12 } 13 14 15 16 let question = question_g(); 17 console.log(word = question.next().value); // question.next().value を取り出すごとに新しい値が取れる。 18 console.log(word = question.next().value); 19 console.log(word = question.next().value); 20 console.log(word = question.next().value); 21 console.log(word = question.next().value); 22 console.log(question.next().done); // もう値がない時には、question.next().done がtrueになる。

投稿2020/07/30 07:02

Lhankor_Mhy

総合スコア36960

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

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

whitehorse85921

2020/07/30 07:23

Lhankor_Mhyさん、ありがとうございました。 ジェネレーター初めて見ました。勉強になります。
guest

0

ベストアンサー

こういうことじゃないかな思うんですが…

JavaScript

1 2 3const words = [ 4 'dream', 5 'sky', 6 'blue', 7 'middle', 8 'cloud', 9 ]; 10 11 let word; 12 let r; 13 let cnt = 0; 14 15 // 最初にこれを呼び出しておく 16 function init(){ 17 for (let i = words.length -1; i > 0; i--) { 18 r = Math.floor(Math.random() * (i + 1)); 19 20 let tmp = words[i]; 21 words[i] = words[r]; 22 words[r] = tmp; 23 } 24 } 25 26 27 function question() { 28 word = words[cnt]; 29 cnt++; // cntが5になった場合の処理は別途何か書いてください 30 }

※今テストする環境がないので動くかわからないまま打っています

おそらく
同じ単語が出てこないのは、shift()の挙動で一回使った数値が消えているからです。
で、全単語打つと止まるのはnumsが空になってしまったからではないでしょうか?

シャッフルについては、numsを挟まなくてもwordsを直接並び替えて頭からとっていけばいいと思います。

投稿2020/07/30 06:54

q_sane_q

総合スコア610

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

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

whitehorse85921

2020/07/30 07:21

q_sane_qさん、ありがとうございます。 最後まで単語を打つことができましたし、タイプミスなく打つとperfectと出したかったのですが、それもできました。私のつたない質問の真意を読み取って下さり、また、修正コードも出して下さり、とても有難いです。 まだまだ私のプログラムは問題多いですが、難所はq_sane_qさんのおかげでクリアできたと思います。 ありがとうございました。
guest

0

javascript

1var num=5; 2const nums = Array(num).fill(null).map((x,y)=>[y,Math.random()]).sort((x,y)=>x[1]-y[1]).map(x=>x[0]); 3console.log(nums);

投稿2020/07/30 04:56

yambejp

総合スコア116734

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

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

whitehorse85921

2020/07/30 05:04

ありがとうございます。 これは重複しない乱数の数値を一つずつ出しているのでしょうか?
yambejp

2020/07/30 05:06

連続した0以上の整数をランダムに格納していますので あとは先頭から順番に取り出してください
whitehorse85921

2020/07/30 05:14

ありがとうございます。 このnumsを words = [ 'dream', 'sky', 'blue', 'middle', 'cloud', ]; words[]の四角かっこの中に入れて、word[1],word[0]などのようにしたいのですが word = words[nums];とするとこのタイピングゲームが動きませんでした。難しいです。
yambejp

2020/07/30 05:23

一つずつとりだすって自分で書いてませんでしたか? forで回すならforEachするなり好きにしてください いまのままだと最低でも word = words[nums[0]]
whitehorse85921

2020/07/30 05:28

すみません。forやforEachではうまくいきませんでした。 words[ここを動的に数値を変えたい]をやりたいので、words[nums[0]];でもうまくいきませんでした。 おいそがしいところすみませでした。。。
yambejp

2020/07/30 05:34 編集

なにが詰まっているのさっぱりわかりませんが・・・ const words = ['dream','sky','blue','middle','cloud',]; var nums = Array(words.length).fill(null).map((x,y)=>[y,Math.random()]).sort((x,y)=>x[1]-y[1]).map(x=>x[0]); while((num=nums.shift())!==undefined){ console.log(words[num]); }
whitehorse85921

2020/07/30 05:47

説明が下手ですみません。。。 一度にすべての単語を出すのではなくて、一つずつ単語をブラウザ上に出していってタイピングしていくイメージでした。 このソースをポートフォリオとして出したかったので、すべてのコードをお見せできずず見ません。 ありがとうございましたm(_ _)m
yambejp

2020/07/30 05:53

何に引っかかっているのでしょうか? 一つだけ取りだすなら、すでに回答したとおり console.log(words[nums[0]]); でできますよね?
whitehorse85921

2020/07/30 06:07

言葉足らずですみません。コンソール画面ではないブラウザ上の画面のことです。
q_sane_q

2020/07/30 06:12

多分ですけど question() を一回呼ぶ度に nums[0]、nums[1]... と取って行きたいってことじゃないでしょうか それをshift()使ってるせいでnumsが先頭要素から削れていってしまってるのが意図していない挙動という…
yambejp

2020/07/30 06:13

HTMLどこに、どのタイミングで表示するのですか? 一番雑なのはbody要素のinnerHTMLを書き換える ちゃんとやるなら表示用のHTML要素を予め用意しておき そのtextContentを書き換える
whitehorse85921

2020/07/30 06:15

q_sane_qさん。 ありがとうございます。 仰る通りでございます。
whitehorse85921

2020/07/30 06:18

yambejpさん、何度もお付き合いくださりありがとうございます。 ozwkさんや、q_sane_qさんが仰って下さったことをやりたいです。 誤解を与えてしまいすみません。
q_sane_q

2020/07/30 06:23

その前に question() の中にあるforでnumsの順番をシャッフルしてるんだと想いますが question()呼ぶたびにシャッフルしてたらnumsの末尾に行くまでに同じ数字が複数回出る可能性あると思うのですが それはその挙動でいいのでしょうか?
yambejp

2020/07/30 06:24

ご提示のquestion()がHTMLに出力するような仕様にはなっていませんが?
whitehorse85921

2020/07/30 06:29

q_sane_qさん、ありがとうございます。 デバッグしてみてシャッフル後のnumsを見てみたのですが、同じ数字が出ることはありませんでした。ただ、shift()をしているためnumsの要素数自体は減っています。
whitehorse85921

2020/07/30 06:34

yambejpさん、ありがとうございます。 別のところで、target.textContent = word;と出力しておりますので、question()が直接HTMLに出力するような仕様にはなってございません。
whitehorse85921

2020/07/30 06:37

q_sane_qさん、何度もすみません。 タイピングゲームをしてるうちは同じ単語が出てくることはありませんでしたが、全単語を全部正しく打つとプログラムが止まってしまうことがあります。
yambejp

2020/07/30 06:41

> 別のところで、target.textContent = word;と出力しております であればword = words[nums[0]] なのですから、ただしく表示されるはずです。 書かれていないところの仕様を説明することは難しいです
whitehorse85921

2020/07/30 06:46

yambejpさん、ありがとうございます。 仰る通りだと思います。 困らせるような質問をしてしまいすみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問