コードの説明
例えば、既に第1位に"さそり座"、第2位に"うお座"が選ばれていて、これから第3位を選ぶ場合を考えます。このとき、配列rank
の中身は["さそり座", "うお座"]
となっています。
まず、乱数un_r
を使い、第3位となる星座の候補をランダムに選びます。ここでは、"うお座"が選ばれたとします。つまり、seiza[un_r]=="うお座"
です。
次に、while文を使って配列rank
の要素を先頭から順番に見ていき、size[un_r]
と一致したらループを途中で抜けるようにします。この例ですと、
n==0
… rank[0]=="さそり座"
はsize[un_r]
と一致しないので、n
を1増やす
n==1
… rank[1]=="うお座"
はsize[un_r]
と一致するので、while文を抜ける
となります。
こうすることで、while文を回した後に、
n < seiza.length
なら、while文を途中で抜けた = 重複がある
n == seiza.length
なら、while文を途中で抜けなかった = 重複がない
のように重複を判定することができます。
この例では重複があることが分かったので、何もせずにfor文の始めに戻り、再び星座の候補をランダムに選びます。ここでは"ふたご座"が選ばれたとします。そして先ほどと同様にwhile文を回すと、今度は重複がないと分かるので、i
の値を1増やし、選んだ星座をrank
に追加します。
以上のことを、i
が12になるまでfor文を回すことで、第1位から第12位までの星座を重複のないように選んでいます。
JavaScript
1 for (i=0 ;i < seiza.length;){ //第12位が選ばれるまで繰り返す
2
3 n = 0;
4 un_r = Math.floor( Math.random() * seiza.length); //星座をランダムに選ぶ
5 color_r = Math.floor( Math.random() * color.length); //ラッキーカラーをランダムに選ぶ
6
7 //rankの先頭から順番に、重複がないか調べる
8 while(n < seiza.length){
9 if (seiza[un_r] != rank[n]){n++;}
10 else {break;} //重複がある場合はループを抜ける
11 }
12
13 //重複がないならランキングに追加
14 if (n >= seiza.length){
15 i++;
16 //(中略)
17 rank.push(seiza[un_r]);//配列に星座を追加
18 }
19 }
補足
どのように動作しているのか分かりにくいという場合は、以下のようにプログラムの該当箇所でログを出力してみるとよいでしょう。重複がある場合に、while文が途中で終了していることが分かると思います。
コード例:
JavaScript
1 console.group(`第${i+1}位`);
2 console.log(`seiza[${un_r}]==${seiza[un_r]}`);
3 while(n < seiza.length){
4 console.log(`rank[${n}]==${rank[n]}`);
5 if (seiza[un_r] != rank[n]){n++;}
6 else {console.log('重複'); break;}
7 }
8 console.groupEnd();
ログ出力例(Chrome):

コードの問題点
さて、このコードには致命的な欠陥があります。それは、上記のログ出力例からも分かる通り、配列rank
で範囲外参照が起きていることです。
while文の条件式を見ると、n < seiza.length
となっています。rank
の長さはseiza
の長さより小さいですから、重複が無い場合に、n
はrank
の末尾の要素の添え字よりも大きくなってしまい、範囲外参照が起きています。
JavaScriptは範囲外参照したときundefinedを返してくれますが、エラーやバグの原因になりかねないので、してはいけません。rank
の各要素を調べるのですから、n < rank.length
としましょう。
修正例:
JavaScript
1 for (i = 0; i < seiza.length;){
2 un_r = Math.floor( Math.random() * seiza.length);
3 color_r = Math.floor( Math.random() * color.length);
4
5 n = 0;
6 while(n < rank.length){ //修正
7 if (seiza[un_r] != rank[n]){n++;}
8 else {break;}
9 }
10
11 if (n == rank.length){ //修正
12 i++;
13 //(中略)
14 rank.push(seiza[un_r]);
15 }
16}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/02/17 14:09