• 締切済み

【乱数】任意の範囲、固定個数、重複しない乱数

テニスのダブルス組み合わせ用のスクリプトを考えております。 ネットでいろいろ探して試してみましたが Javascript初心者で、寄せ集めでは限界がありますので質問させてください(;^_^A 【何をしたいのか】 ・テキストボックスで任意の数字(整数)で範囲と行数を指定。 ・結果は数値4個固定とし、4個で1グループ。この4個内は重複がないように。 ・4個1グループを指定の行数分求める。 ・このとき、なるべくならすでに出た数字は後回しにしたい。例えば1~10の範囲としたら、1~10すべて出るまでは一度出た数字は後回しになるように。 ・小さい範囲で大きな行数を指定すれば、必ず同じ組み合わせが出ることは了承。 ・結果は下記のようにしたい。 1,6,8,3 2,4,5,10 9,7,2,3 ・ ・ 3,6,8,1(1行目と同じ組み合わせだが順不同なので可、またはまったく同じのが出ても可) 【現在の状況】 ネットで拾ったサンプルから、何をどのように書き換えたらいいのかわからずです(;^_^A 【サンプルの提示】 ■範囲の乱数■ <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript"> <!-- function gen_random(num1, num2) { retval=Math.random(); document.write(Math.floor(retval * (num2 - num1)) + eval(num1)); } //--> </SCRIPT> </HEAD> <BODY> <center> <table border=1 cellpadding=4> <form name=myform> <tr><td bgcolor=#ffffe4 align=center> <font color=blue> 乱数の範囲 </td></tr> <tr><td align=center> <input type=text name=d1 size=2 maxlength=2> ~ <input type=text name=d2 size=4 maxlength=4> </td></tr> <tr><td align=center> <input type=button name=btn1 value=乱数発生 onClick=gen_random(myform.d1.value,myform.d2.value)><br> </td></tr> </form> </table> </center> </BODY> </HTML> ---------------------------------------- ■30個を5行ずつ出している <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript"> var i; for(i=1 ; i <=30 ;i++) { document.write(Math.floor(Math.random()*10) +"<BR>"); if(i%5 == 0) document.write("<HR>"); } </SCRIPT> </HEAD> <BODY> </BODY> </HTML> --------------------------------------------------------- ■重複しない、しかも後回しになる?■ <HTML> <HEAD> <SCRIPT LANGUAGE="JavaScript"> //once_rand: min以上max未満の重複しない乱数を生成するためのオブジェクト function once_rand(min,max){   this.cnt=max-min;   this.arr=[];   //乱数候補を配列に格納   for(var i=0;i<this.cnt;i++){this.arr[i]=min++;} } //乱数を取り出すメソッド once_rand.prototype.next=function(){   if(this.cnt<=0){     //もう乱数候補が残っていない     return undefined;   }   //乱数を取り出す位置を決定   var idx=Math.floor(Math.random()*(this.cnt));   //乱数を取り出す   var rand_val=this.arr[idx];   //重複しないように最後尾の要素で上書き(今のthis.arr[this.cnt-1]は次回以降使われない)   this.arr[idx]=this.arr[this.cnt-1];   //残りの乱数候補が減少   this.cnt--;   return rand_val; } //テスト var rand1 = new once_rand(1,15); //1以上15未満 var str=rand1.next(); while(1){   var rand_val=rand1.next(); //乱数を取り出す   if(rand_val == undefined){break;}   str += ","+rand_val; } alert(str); </SCRIPT> </HEAD>

みんなの回答

noname#84373
noname#84373
回答No.7

<div id="p">あっさりってどうなのよ;_;</div> <script type="text/javascript"> //全角空白は半角空白かタブに変換のこと //@cc_on Array.prototype.shuffle_FY = function () {  var n = this.length;  var r;  var w;    while (n) {   r = Math.random() * n |0;   w = this[--n];   this[n] = this[r];   this[r] = w;  }  return this; } var max = 10; var member = []; var i = 1; var nx = []; var text = []; var g = 10; var o; var c = 0; var t; var lt=[]; for (;i <= max; nx.push(i++)); while (g) {  if (member.length < 4) {   while (o = nx.shift()) member.push(o)   member = member.shuffle_FY();  }  t = member.shift(); nx.push(t); lt.push(t);  c++;  if (c==4) {   c = 0;   text.push(lt.join(', '));   lt = [];   g--;  } } document.getElementById('p').innerHTML = text.join('<hr>'); </script>

すると、全ての回答が全文表示されます。
noname#84373
noname#84373
回答No.6

ご指摘ありがとうございます。あれから他のページの回答も 参考にさせてもらい、偏りがあることを知りました。 手を抜いちゃだめってことなんですかね^^;

すると、全ての回答が全文表示されます。
  • Gotthold
  • ベストアンサー率47% (396/832)
回答No.5

> member = member.sort(function () { return Math.random() > 0.5 ? 1 : -1 }); シャッフルするために比較関数に乱数を使うパターンはたまに見るけど、 推移律が満たされない比較関数をsortに渡すってどうなんだろう? 停止性とか大丈夫なのかな。 あとこの方法だと全ての組み合わせが等確率で出現しないと思う。 ランダムソート(笑)とは - 西尾泰和のはてなダイアリー http://d.hatena.ne.jp/nishiohirokazu/20071121/1195641084 ↑は今調べて見つけたページだけどランダムソート(笑)は言い得て妙だと思った。 とりあえずシャッフルアルゴリズムにはFisher-Yatesを薦めとく。

すると、全ての回答が全文表示されます。
noname#84373
noname#84373
回答No.4

さらに訂正。 <div id="p"></div> <script type="text/javascript"> var max = 10; var member = []; var i = 1; var nx = []; var text = []; var g = 10; var o; var c = 0; var t; var lt=[]; for (;i <= max; nx.push(i++)); while (g) {  if (member.length < 4) {   while (o = nx.shift()) member.push(o)   member = member.sort(function () { return Math.random() > 0.5 ? 1 : -1 });  }  t = member.shift(); nx.push(t); lt.push(t);  c++;  if (c==4) {   c = 0;   text.push(lt.join(', '));   lt = [];   g--;  } } document.getElementById('p').innerHTML = text.join('<hr>');

Tobykun
質問者

お礼

ありがとうございました!! マルチポスト怒られました(;^_^A アセアセ・・・ 今後は気をつけるようにします。 本当にありがとうございました♪

すると、全ての回答が全文表示されます。
noname#84373
noname#84373
回答No.3

連続でごめん。今日はやっぱりボケてる。 var max = 10; var member = []; var i = 1; var nx = []; var text = []; var g = 10; var o; var c; for (;i <= max;member.push(i++)); while (g--) { member = member.sort(function () { return Math.random() > 0.8 ? 1 : -1 }); while (o = nx.shift()) member.push(o); c = 4; while(c--) nx.push(member.shift()); text.push(nx.join(', ')); } document.getElementById('p').innerHTML = text.join('<hr>'); マルチ突っ込まれるぞ!^^;

すると、全ての回答が全文表示されます。
noname#84373
noname#84373
回答No.2

さっそくミス発見。 <div id="p"></div> <script type="text/javascript"> var max = 10; var member = []; var i = 0; var nx = []; var text = ''; var g = 10; for (;i < max;) member.push(i++); while (g--) { member = member.sort(function () { return Math.random() > 0.8 ? 1 : -1 }); for (i=0;i<4;i++) member.push(nx.shift()); nx = []; for (i=0;i<4;i++) nx.push(member.shift()); text += nx.join(', ') + '<hr>'; } document.getElementById('p').innerHTML = text; </script>

すると、全ての回答が全文表示されます。
noname#84373
noname#84373
回答No.1

つっこまれそうだなぁ~! 数値が0.8のところは、本来0.5なんだけど うまく説明できないけど微調整して・・・。 <div id="p"></div> <script type="text/javascript"> var max = 10; var member = []; var i = 0; var nx = []; var text = ''; var g= max; for (;i < max;) member.push(i++); while (g--) { member = member.sort(function () { return Math.random() > 0.8 ? 1 : -1 }); while(nx[0]) member.push(nx.shift()); nx = []; for (i=0;i<4;i++) nx.push(member.shift()); text += nx.join(', ') + '<hr>'; } document.getElementById('p').innerHTML = text;

すると、全ての回答が全文表示されます。

関連するQ&A