Written in Japanese(Shift-JIS)
2013. 2. 1
INASOFT

/トップ/目次/管理人のひとこと(ブログ)/当選者選択プログラムの作成

2091072 (+0257)[+0192]

管理人のふたこと Tweet

当選者選択プログラムの作成




公開日:2013/01/29
公開日:2013/01/30 補足と訂正
公開日:2013/02/01 シャッフルの方法

今月、恒例のINASOFT読者アンケート&プレゼント企画を実施しました。

この中で、抽選をどのような方法で行うか、考えました。

過去の抽選では、そのときそのときでマイブームな人………例えば、直近でフォロワーになった人だったり、特別仲のよい友人だったり、サークルのリーダーだったり、家族だったり、会社の先輩だったりしたこともありました。

さて、現在のマイブームは、パソコンからその地位を奪いつつあるiPadなのですが、ぜひともiPadさんに抽選をやってもらいたいと思いました。

しかし、iPadさんに抽選をやってもらうということは、iPadさんで自作プログラムが動かなければなりません。これだけのために、アップルストアに申請を出すのは手間がかかりすぎです。

というわけで、手軽に標準ブラウザSafariで動く、JavaScriptでプログラムを組むことにしました。

さて、アルゴリズムとしては、次の通り。

  1. 投稿に対し、適当に被らないような番号を降ります。ここは、人間のお仕事。
  2. 投稿数をプログラムに与え、さらに当選本数もプログラムに与えます。
  3. プログラムは投稿数が要素にそのまま入った配列を作ります。
  4. 配列をシャッフルします。ここが肝心なところですが、配列をシャッフルするJavaScriptのプログラムなら、ネット上にゴロゴロ転がっているはず、とも考えました。
  5. シャッフルされた配列の先頭から、当選本数分だけ、要素を画面表示します。
アルゴリズムの図解(手順3〜5)

簡単そうです。

実際、テキトーに作ったら、IEではきちんと動きました。

が、なぜかSafariでは動かず。あれあれ?と思い次。Firefoxでも動かず。

ネットで調べたところ、原因はすぐにわかりました。とりあえず、書いたプログラムを御覧ください。


<html>
 <head>
  <title>抽選プログラム</title>

<script type="text/javascript">
Array.prototype.shuffle = function() {
    var i = this.length;
    while(i){
        var j = Math.floor(Math.random()*i);
        var t = this[--i];
        this[i] = this[j];
        this[j] = t;
    }
    return this;
}

function c_lot() {
  total_num = Number(document.getElementById('total').value);
  tosen_num = Number(document.getElementById('tosen').value);
  
  if (total_num <= 0) {
    alert("全体数には1以上の値を指定してください。");
    return;
  }
  else if (tosen_num <= 0) {
    alert("当選数には1以上の値を指定してください。");
    return;
  }
  else if (total_num < tosen_num) {
    alert("全体数は当選数以上である必要があります。");
    return;
  }
  
  ret = confirm("抽選を行います。よろしいですか?");
  if (ret == true){
     ary = new Array(total_num);
     for(i=0 ; i<total_num ; ++i) {
        ary[i] = i + 1;
     }
     ary.shuffle();
     result_text = "■当選結果 = ";
     for(i=0 ; i<tosen_num ; ++i) {
        if (i > 0) {
           result_text += ", "
        }
        result_text += "No."+ary[i];
     }
     temp = document.getElementById("result");
     temp.innerHTML = result_text;
  }
}
</script>

 </head>
 <body>
  <h1>抽選プログラム</h1>
  <form name="chusen">
   全体数:<input type="text" size="10" name="total" id="total" value="10" /> 
   当選数:<input type="text" size="10" name="tosen" id="tosen" value="6" />
   <input type="button" value="抽選" onClick="c_lot();" />
  </form>
  <br><br><br>
  <b><font color="#ff0000">
  <div id="result">
  <small>(ここに結果が表示されます)</small>
  </div>
  </font></b>
 </body>
</html>

赤で書かれた部分が、原因を修正したところです。

document.getElementByIdは、その名の通り、IDを使ってフォーム要素から値を取り出す動きをするわけですから、該当する<input>にはID属性が指定されていなければなりません。IEではなぜか、name属性さえあれば読めてしまうのですが、それは罠。

また、Number() で囲まないと、フォームから取り出された値は「文字列」と認識されてしまいますから、その後の大小比較のif文の動きがおかしくなります。具体的には、"10" < "6" という事態が起こりえます(文字列は辞書式による大小比較を行う)。

なるほど。そういうわけですね。

しかし、JavaScriptの、動作環境ごとでの動きの違いって、厄介ですね。

とくに、IEの異端っぷりは異様。

その反面、このプログラムはNintendo3DSでもスマートフォンでも、ブラウザ搭載機種ならなんでもどこでも動きます。なんだか、未来を感じさせてくれますね。

よい勉強になりました。




実際のプログラムはこちら↓

全体数: 当選数:


(ここに結果が表示されます)

※半角数字以外を入れた場合などに対する検定は入れていないので、あまりイジメないでください。
※このスクリプトは alert() や confirm() を使っているため、ダイアログ表示のできない携帯電話では、正常に動作しません。


2013/01/30 補足と訂正
2013/02/01 シャッフルの方法

そういえば、シャッフルを行っている関数 shuffle について、全然解説していなかったですね。

この関数は、余所様のサンプルコードを拝借したモノですが、シンプルによくできています。
この関数は、「配列クラス」にメンバ関数を追加するような感じで実装されています。こうしておくと、このスクリプト内の配列に対し、シャッフル関数を実行できます。「配列クラス」と言ってしまうと軽く語弊があるわけですが、ここでの理解はその程度で。

では、関数の中の解説を。

random(n) は、0以上n未満の数を、ランダムに返す関数です。基本的には小数で返ります。
random(100)なら0以上100未満の数がランダムで返ります。

floor(n) は、与えられた数を超えない最大の整数を返す関数です。
floor(1.1)なら1を返すし、floor(0.5)なら0を返すし、floor(-1.2)なら-2が返ります。

これを使って、0以上指定数未満の整数をランダムに得ることができます。
ここまでが、ループ内1行目にやっていること。

ループ内2行目からループ内4行目は、変数値のスワップ(入れ替え)をやっています。tはテンポラリ(一時的な)変数と言うことでしょう。
配列の末尾と、上のランダムで決められた数(ただし、その末尾よりも左側にあるもの)を交換します。そして、配列の末尾の位置を1つずつずらしながら、それより左側の要素とランダムに交換します。末尾の位置が0に到達したらおしまい。

これで、配列内の要素のシャッフルが完成です。



本ページへは、自己責任の範囲内であれば自由にリンクしていただいて構いません。
本ページに掲載されている内容は、自由にお使いいただいて構いませんが、必ずしも筆者が内容を保証するものではありませんので、ご利用に際しては自己の責任においてお使いいただきますよう、お願いいたします。
このページのURLやアンカーは、サーバ運営・サイト運営・ページ運営・その他の都合により無告知で一時的あるいは永遠に消滅したり、変更したりする可能性がありますので、あらかじめご了承下さい。
本ページは、公開から1年半経過後の任意のタイミングで削除される予定です。本ページの内容は複製・公開していただいて構いません。


/トップ/目次/管理人のひとこと(ブログ)/当選者選択プログラムの作成