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

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

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

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Q&A

解決済

1回答

701閲覧

for文の確認をしていただきたいです

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

0グッド

0クリップ

投稿2021/05/01 05:46

前提・実現したいこと

作成したfor文が上手く動かない(重くてChromeが固まる)ので、どこが間違っているのか教えていただきたいです。

前提
ユーザーが指定した数字とコンピュータが生成した数字(それぞれ6個、コンピュータのみランダム数字をとして+1個)がどれだけ一致するか、一致具合を確率で表示させるためのコードです(htmlでの確率の表示はfor文の外で行っています)。
int_user_array はユーザーが入力した数字を配列として、別の場所できちんと格納できています。
入れ子のfor文では、1~43のランダム数字を重複させずに配列に格納する処理を行っています。

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

繰り返しの処理がどこかおかしく、膨大な回数が実行されているのかなと思うのですが、どこがおかしいかわからないです。

該当のソースコード

var win_count = {one: 0, two: 0, three: 0, four: 0, five: 0, lose: 0}; var traials_num = 100; var com_array = []; var min = 1, max = 43; var length = 7; function intRandom(min, max){ return Math.floor( Math.random() * (max - min + 1)) + min; } for(var j = 0; j < traials_num; j++){ for(var k = min; k <= length; k++){ while(true){ var tmp = intRandom(min, max); if(!com_array.includes(tmp)){ com_array.push(tmp); break; } } } // 一番後ろの数字をランダム数字として別枠に const random_num = com_array.pop(); // 配列の統合 var concat_array = int_user_array.concat(com_array); // 配列の重複削除 var delete_duplicate_array = Array.from(new Set(concat_array)); // 当たりチェック if(user_array.sort().join() == com_array.sort().join()){ win_count.one++; }else if(delete_duplicate_array.length == 7 && int_user_array.includes(random_num)){ win_count.two++; }else if(delete_duplicate_array.length == 7){ win_count.three++; }else if(delete_duplicate_array.length == 8){ win_count.four++; }else if(delete_duplicate_array.length == 9){ win_count.five++; }else{ win_count.lose++; } }

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

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

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

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

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

guest

回答1

0

ベストアンサー

この処理は終わらないと思います。

com_arrayに重複しないランダムな数値の配列を入れようとしてるように思えますが、

var traials_num = 100; var length = 7; for(var j = 0; j < traials_num; j++){ for(var k = min; k <= length; k++){

この2つのループで700回ループしています。
そしてランダム数値の範囲は

var min = 1, max = 43;

なので最大43個しか入ることができません。
そのため、43個入りきると、

while(true){ var tmp = intRandom(min, max); if(!com_array.includes(tmp)){ com_array.push(tmp); break; } }

com_array.includes(tmp)が常にTRUEしか返さなくなるので
このwhile文から抜け出せません。

解決法としては

  1. traials_num * lengthの値を43以下にすること
  2. maxの値を700以上にすること

になるかと思います。

投稿2021/05/01 06:54

編集2021/05/01 06:58
rinjinto

総合スコア170

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

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

rinjinto

2021/05/01 07:06

com_arrayの目的がわかっていませんが、1回ごとに削除していいなら for(var j = 0; j < traials_num; j++){ のループごとにcom_arrayを削除するという手もあります。
退会済みユーザー

退会済みユーザー

2021/05/01 08:49

ありがとうございます。 私の言葉が不足しており、やりたいことを上手くお伝えできてなかったようです。 com_arrayはコンピュータがランダムに重複なく生成した数字の配列で、for文の下で色々と手を加えて最終的にユーザーが入力した数字の配列と結合させて当たり判定に使います。 やりたいことが、 1、ランダムな数字(重複なし、1~43)をcom_arrayに7個格納⇦1つめのfor文 2、格納されたcom_arrayを使って以降の配列結合、当たり判定のif文 3、上の1と2の処理を100回繰り返し、どの当たりがどれくらいの頻度で訪れるかのチェック⇦2つめのfor文 以上の3点なのですが、この場合どこを修正すればよいでしょうか?
退会済みユーザー

退会済みユーザー

2021/05/01 08:55

while(true){ var tmp = intRandom(min, max); if(!com_array.includes(tmp)){ com_array.push(tmp); break; } } この部分では、1~43の数字をランダムに生成し、ダブらなかった時だけ配列に格納するように書いたつもりなのですが(7個ダブらなくなったら終了)、「43個入りきると...」というのはどういうことなのでしょうか? 聞いてばかりで申し訳ありませんが、よろしくお願い致します。
rinjinto

2021/05/01 13:36 編集

com_arrayが1回のループごとに初期化されていない(中に入れた数字を全て削除していない)のです。 for(var k = min; k <= length; k++){ while(true){ var tmp = intRandom(min, max); if(!com_array.includes(tmp)){ com_array.push(tmp); break; } } } j=0でこの処理が終わると、com_arrayには7個の数字が入ります。 ですが、com_arrayを初期化していない(中に入っている数字が全部残ったまま)ため、 j=1のループでcom_arrayに7個の数字が追加されて合計14個の数字が入ることになります。 そして、j=2では21個・・・・と増えていき、j=6のループ途中でcom_arrayに43個の数字が埋まってしまい、そこからwhile文が無限ループになります。 やりたいことを見ると、com_arrayを1回のループごとに初期化したいのだと思います。 そうすると、 else{ win_count.lose++; } の後に com_array=[]; を入れれば1回のjのループごとにcom_arrayの配列が空になります。 for(var j = 0; j < traials_num; j++){  for(var k = min; k <= length; k++){ (省略)  }else{   win_count.lose++;  }  com_array=[]; } こんな感じでしょうか。
退会済みユーザー

退会済みユーザー

2021/05/01 14:37

ご丁寧にありがとうございます。 非常にわかりやすく説明してくださったおかげで、理解ができ無事に解決致しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問