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

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

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

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

Q&A

解決済

4回答

424閲覧

javascriptで配列にwhileで代入するとループが抜けられなかった。

liflect

総合スコア14

JavaScript

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

0グッド

0クリップ

投稿2018/06/06 21:03

編集2018/06/06 22:05

二次元配列にmarkを5個入れようと思ったら、下記のコードではループが抜けられなかったのです。console.logで出力すると、全部markで埋まった配列が出力されるんですが、なんでそうなるのかが、よく分かりません。どこに問題があるのでしょうか?

javascript

1let mark = "O"; 2let length = 3; 3function makeArray(){ 4 let i = 0; 5 let x; 6 let y; 7 let markArray = (new Array(length)).fill((new Array(length)).fill("")); 8 while(i < 5){ 9 x = Math.floor(Math.random()*length); 10 y = Math.floor(Math.random()*length); 11 if(!markArray[x][y]){ 12 markArray[x][y] = mark; 13 i++; 14 } 15 console.log(markArray); 16 } 17 return markArray; 18} 19let markArray = makeArray(); 20console.log(markArray);

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

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

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

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

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

m.ts10806

2018/06/06 21:18

変数markはどこで定義されて何が入っているのでしょうか。このまま実行すると未定義エラーが出ます。
liflect

2018/06/06 21:20

書き忘れました。'O'が入っています
m.ts10806

2018/06/06 21:48

ゴールの形がよく見えてないですが、抜けられないのはiがカウントアップされていないに他なりません。i,x,yをwhileの中で出力してもらえれば分かるかと。そもそも何をしているか分かっていますか? >let markArray = (new Array(length)).fill((new Array(length)).fill(mark));
liflect

2018/06/06 22:04

訂正します。markArray = (new Array(length)).fill((new Array(length)).fill(""));
m.ts10806

2018/06/07 00:08

既に書いていますが、ゴールを明記してください。「二次元配列にmarkを5個入れようと思った」だけでは最終形が見えません。無限ループが抜けさえすれば良いのか、それともやりたい形があるのか。やりたい形があるならそれは何なのか。無限ループを抜けたいだけならiのカウントアップが行われていないだけなのでそこを見れば良いですし。
liflect

2018/06/07 09:15

ループを抜けてmarkが5個入った二次元配列を返すことです。
m.ts10806

2018/06/07 09:45

文字での説明ではなく例えば配列をコンソールで出力した結果のような形とかそういう意味です。「5個はいった二次元配列」だけではほぼ無限に答えがあります。
m.ts10806

2018/06/07 09:50

解決されたんですね。良かったです。今後は「確実に伝わる表現」を心掛けてください。文章で伝えるには限界があることも多いです。
guest

回答4

0

ベストアンサー

面白いことに、markArray[0]とmarkArray[1]は同一オブジェクトになっています。

let markArray = (new Array(length)).fill((new Array(length)).fill("")); console.log(markArray[0] === markArray[1]); // true console.log(markArray[0] === markArray[2]); // true

↑なので、

markArray[x][y] = mark;

↑この処理はxの値に関係なく、yの値にのみ依存して実行されます。
その結果、

if(!markArray[x][y]){ markArray[x][y] = mark; i++; }

↑このブロック内に到達できるのは最大3回。
whileループの継続条件「while(i<5)」からは絶対に抜け出せない、ということになります。

let markArray = (new Array(length)).fill((new Array(length)).fill(""));

↑「Array.fill(object)」を実行すると配列の各要素に「object」そのものを埋め込むようです。
stackoverflowでもトピックに上がってました)
一度、空要素で埋めてからmapするとobjectのコピーが埋め込まれます。

let markArray = (new Array(length)).fill().map(v=>(new Array(length)).fill("")); console.log(markArray[0] === markArray[1]); // false console.log(markArray[0] === markArray[2]); // false

投稿2018/06/07 01:01

tkturbo

総合スコア5572

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

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

liflect

2018/06/07 09:18

分かりやすく教えてくれてありがとうございました。
guest

0

一応参考までに

javascript

1let mark = "O"; 2let length = 3; 3let tmp = makeArray(mark,length); 4console.dir(tmp); 5function makeArray(mark,length){ 6 let i = 0; 7 let ret = (new Array(length)).fill(null).map(function(x){return new Array(length).fill("")}); 8 while(i < 5){ 9 let x = Math.floor(Math.random()*length); 10 let y = Math.floor(Math.random()*length); 11 ret[x][y] =mark; 12 i++; 13 } 14 return ret; 15} 16

投稿2018/06/07 01:47

yambejp

総合スコア114829

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

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

0

多次元配列の宣言がよくなかったようです。
書きか出たら、おそらく意図しているような動作になりました。

改修前

js

1 let markArray = (new Array(length)).fill((new Array(length)).fill("")); 2

改修後

js

1 let markArray= new Array(length); 2 for(let i=0;i<length;i++){ 3 markArray[i]=new Array(length).fill(""); 4 }

改修後(全体)

let mark = "O"; let length = 3; function makeArray(){ let i = 0; let x; let y; //let markArray = (new Array(length)).fill((new Array(length)).fill("")); let markArray= new Array(length); for(let i=0;i<length;i++){ markArray[i]=new Array(length).fill(""); } while(i < 5){ x = Math.floor(Math.random()*length); y = Math.floor(Math.random()*length); if(!markArray[x][y]){ markArray[x][y] = mark; i++; } console.log(markArray); } return markArray; } let markArray = makeArray(); console.log(markArray);

出力結果

(3) ["", "", "O"] (3) ["O", "O", "O"] (3) ["", "O", ""]

投稿2018/06/06 23:32

yuyabu

総合スコア63

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

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

liflect

2018/06/07 09:19

確かに動くようになりました。
guest

0

ただ単に

javascript

1if(!markArray[x][y]){ 2 markArray[x][y] = mark; 3 i++; 4}

この部分が実行できていないだけでは?
if文の条件を見直すと解決すると思います

投稿2018/06/06 22:16

yuyabu

総合スコア63

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

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

liflect

2018/06/06 22:27

console.logで全部markで埋まった配列が出力されるのでその部分は実行されているはずだと思ってるんですが?
yuyabu

2018/06/06 22:59 編集

ソースを確認したところ件のブロックは3回しか実行できていないようです。つまりiが3で止まりi>5とならない。
yuyabu

2018/06/06 22:50 編集

おそらくジャグ配列の使い方が間違っています ``` et mark = "O"; let markArray = (new Array(length)).fill((new Array(length)).fill("")); markArray[2][0] = mark; console.log(markArray) ``` 上記のコードを実行したところ ``` (3) [Array(3), Array(3), Array(3)] 0 : (3) ["O", "", ""] (3) ["O", "", ""] (3) ["O", "", ""] ``` となってしまいました。 多分`markArray[2][0] = mark;`で2,0を指定しているから ``` (3) ["", "", ""] (3) ["", "", ""] (3) ["O", "", ""] ``` となってほしいはずですよね 3回の書き込みで全ての要素がmarkになってしまい、それ以上、件のifブロックを通らないことによりiが5以上にならないことが原因で無限ループになっているようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問