Math.random()を使って配列をシャッフルする方法について解説

HOME
更新日:2017.03.02
HOMEJavaScript入門 > 配列をシャッフルする

配列をシャッフルする

ここでは、乱数を使って配列の要素を入れ替える方法について解説します。 問題文をランダムに出題したい場合などに使うことができます。

前のページでも、問題文(カラー名の英単語)をランダムに表示する方法を見ましたが、 同じ問題文が何度も続けて表示されることもあったと思います。 それを避けるために、配列そのものをシャッフルして、 その後その配列を順に表示すればダブることがありません。

配列をシャッフルする

配列をシャッフルする方法ですが、一番分かり易いのは以下の方法でしょう。

  1. まず乱数を使って、配列のどれか1つの要素を決めます
  2. それを配列の1番最初の要素と入れ替えます
  3. これを繰り返すことでシャッフルできます

では、以下のスクリプトをHTMLのBODY内に記入してみて下さい。

<form name="quiz">
<input type="text" value="">
<input type="button" value="出題" onclick="mondai()">
</form>

<script>

//カラー名を格納する配列colの作成
var col = new Array("red","blue","yellow","green","white");

//配列の大きさに合わせて適当な回数繰り返す
for ( i = 0 ; i < 20 ; i++ )
{
  //0~4までの乱数を作成し、変数Rndに格納する
  var rnd = Math.floor(Math.random()*5);
  
  var str1 = col[0];    //配列colの最初の要素
  var str2 = col[rnd];  //配列colの乱数で決定した要素

  //配列の各要素を入れ替える
  col[rnd] = str1;
  col[0]   = str2;
}

var cnt = 0; //何問出題したかカウントする変数  

function mondai(){
  if( cnt < 5 )
  {
    document.quiz.elements[0].value = col[cnt];
    cnt++;
  }else{
    //全問(5問)終了したら、そのことを表示してボタンを押せなくする
    document.quiz.elements[0].value = "全問終了";
    document.quiz.elements[1].disabled = true;
  }  
}

</script>

<サンプル>

シャッフルスクリプトの解説

では上記スクリプトを詳しく見ていきたいと思います。 最初のカラー名を格納する配列colは、前ページと同じにしました。

続いてfor文を使い、配列colをシャッフルします。 配列の要素によって繰り返し回数を調整することができます。 今回は20回シャッフルしています。

for文の中で最初に、0~4までの整数の乱数を作成し、変数rndに代入します。

次に、配列の最初の要素と、乱数で決定した要素をそれぞれ変数str1,str2に代入します。 そして、各要素を入れ替えます。下のリンクをクリックすると、 どのようにシャッフルされているか確認できます。

シャッフルの確認(別窓)

(確認ページを見ると分かるように、変数rndが0の時はシャッフルされません。 従って乱数を1~4までの範囲にするか、0の時は最後の要素と入れ替える等の処理をすると、 効率よくシャッフルできます。色々と工夫してみてください)。

今度は問題を出題する部分を見ていきます。 最初に出題した回数を格納するグローバル変数cntを宣言し、初期値0を代入しておきます。

次に関数modai()の中で、最初に出題数をif文でチェックします。 5問未満であれば、問題を表示します。そして出題数の変数cntを1増加させます。 5問全部表示していたら、 テキストボックスに「全問終了」と表示して、ボタンを禁止状態にします。

これでシャッフルの説明は終わりですが、 配列自体をシャッフルしているので前のページのような正誤判定はできません。 幾つか方法がありますが、 例えば以下のように正解の文字列を格納した配列をもう一つ作っておくと、 それを使って判断できます。


//正解の文字列を入れた配列をもう一つ作成
var seikai = new Array();
seikai = new Array("red","blue","yellow","green","white");

//配列colだけをシャッフル(上述)

//正誤判定は、テキストボックスの文字列とseikai[]を比較
function push(num){
  num = parseInt(num);
  if( document.quiz.elements[0].value == seikai[num] )
  {
    //正解の処理
  }
}