皆さん初めまして。乱数の出し方に困ってます。
例えば、1から100の範囲で最初の乱数を出し、90が出たとします。
そして、次は、1から100の範囲なのですが、90という数字を除いた99個の数の中からの乱数を出したい...
この繰り返しで、変らないのは、1から100までの範囲。しかし、繰り返すほど、乱数の選択できる数が少なくなってゆき、既に出てしまった数字は、次からは、乱数の選択に該当しない。
説明が、ややこしくなってしまいましたが、
1から5の範囲の乱数。(実際は100でやってみたい)
1,2,3,4,5
3が出た。
1から5の範囲の乱数、しかし、1,2,4,5 が乱数に利用可能な数字。
4が出た。
1から5の範囲の乱数、しかし、1,2,5 が、次の乱数に利用可能な数字。
というような感じです。
2回目以降の乱数の結果が、既出の数字だから、もう一度振りなおすのではなくて、既出の数字は、抜けた状態で、乱数を振る。同じ条件での、振りなおしなし。
というようなものです。
可能でしょうか? どなたかご指導よろしくお願いします。
ある数を除いての乱数の出し方は?
Re: ある数を除いての乱数の出し方は?
[ここをクリックすると内容が表示されます]
こんな感じでしょうか。コード: 全て選択
#prompt
Const RANDMAX=100
Dim Flag[ELM(RANDMAX)] As Long,i As Long,j As Long
Dim RndNum As Long
ZeroMemory(Flag,SizeOf(Long)*RANDMAX)
Randomize
For i=1 To RANDMAX
RndNum=Fix(Rnd()*(RANDMAX+1-i))
For j=1 To RANDMAX
If Flag[j-1]=0 Then
If RndNum=0 Then
Print j
Flag[j-1]=1
Exit For
End If
RndNum=RndNum-1
End If
Next
Next
例えば1から5であれば、まず0~4の乱数を生成し、例えば2が出たなら
1 2 3 4 5
2 1 0
で「3」が選ばれます。
次は0~3の乱数を生成し、3が出たら
1 2 3 4 5
3 2 x 1 0
というように、すでに出た数をとばして数え「5」が選ばれます。
その次は0~2の乱数を使って同様に。
この要領でいけばすでに出た数ははじめから選択に該当しません。
※完全に感覚でやっているので、効率悪いかもしれませんが…
[hira]
http://hira.hopto.org/
http://hira.hopto.org/
コード: 全て選択
Const CHANGE=100
Dim Array[ELM(100)] As Long
Dim i As Long
Dim n1 As Long
Dim n2 As Long
Dim t As Long
For i=1 To 100
Array[i-1]=i
Next
Randomize
For i=1 To CHANGE
n1=Int(Rnd()*100)
n2=Int(Rnd()*100)
t=Array[n1]
Array[n1]=Array[n2]
Array[n2]=t
Next
(定数 CHANGE を増やせば交換の回数が増えて、よりシャッフルされます)
これを配列の最初から見ていくと、見事に乱数になっています。
hiraさん、Toshiさん、ありがとうございます。
伏せてある、100枚の数字カードを、一枚ずつ、開いて(表示して)ゆき、どういう順番で、表示されるか。というような、シミュレーションと、言えばいいのかもしれません。
それを私が、コンピューター上でやると、2回目以降の乱数の結果に、在ってはならないはずの、既出の数字が出てしまうことが多くあり、ごまかしに、その回だけ、やり直し、結果がよければ次へ、というようになってしまいます。まぁ、妥協すれば、それでもいいのですが、現実的にはありえず、シミュレーションとはなりません。
実は、今日、突然思い立って、Active Basicをダウンロードし、PC8001の画面を、思い出しつつの、プログラミングなので、まだ、よく理解で来てませんが、hiraさんのコードが、私の考えに沿う形に、なっているように思えます。
もう少し、勉強してみます。
伏せてある、100枚の数字カードを、一枚ずつ、開いて(表示して)ゆき、どういう順番で、表示されるか。というような、シミュレーションと、言えばいいのかもしれません。
それを私が、コンピューター上でやると、2回目以降の乱数の結果に、在ってはならないはずの、既出の数字が出てしまうことが多くあり、ごまかしに、その回だけ、やり直し、結果がよければ次へ、というようになってしまいます。まぁ、妥協すれば、それでもいいのですが、現実的にはありえず、シミュレーションとはなりません。
実は、今日、突然思い立って、Active Basicをダウンロードし、PC8001の画面を、思い出しつつの、プログラミングなので、まだ、よく理解で来てませんが、hiraさんのコードが、私の考えに沿う形に、なっているように思えます。
もう少し、勉強してみます。
> 伏せてある、100枚の数字カードを、一枚ずつ、開いて(表示して)ゆき、どういう順番で、表示されるか。というような、シミュレーションと、言えばいいのかもしれません。
> 実は、今日、突然思い立って、Active Basicをダウンロードし、PC8001の画面を、思い出しつつの、プログラミングなので、まだ、よく理解で来てませんが、hiraさんのコードが、私の考えに沿う形に、なっているように思えます。
Toshiさんのほうがより分かりやすいと思いますが?
お店でトランプを買ってきた時は最初は全部並んでますよね。
例えばふたを開けると一番上はスペードのエースでつぎが2,3,4・・・と続きます。
そのまま遊ぶことは出来ないからよくカードをシャッフルする必要があるんです。
> 実は、今日、突然思い立って、Active Basicをダウンロードし、PC8001の画面を、思い出しつつの、プログラミングなので、まだ、よく理解で来てませんが、hiraさんのコードが、私の考えに沿う形に、なっているように思えます。
Toshiさんのほうがより分かりやすいと思いますが?
お店でトランプを買ってきた時は最初は全部並んでますよね。
例えばふたを開けると一番上はスペードのエースでつぎが2,3,4・・・と続きます。
コード: 全て選択
Dim Array[ELM(100)] As Long
For i=1 To 100
Array[i-1]=i
Next
コード: 全て選択
Dim n1 As Long
Dim n2 As Long
Dim t As Long
Randomize
For i=1 To CHANGE
n1=Int(Rnd()*100)
n2=Int(Rnd()*100)
t=Array[n1]
Array[n1]=Array[n2]
Array[n2]=t
Next
今日も元気にABLife
私が考えたのは,以下のような方法です。
まず,カードを数字の順番でよいので並べます。
次に,そこから1枚ずつ順に取り出して山札に加えていきます。ただし山札のどこに加えるかは乱数で決めます。
例えばカードが「1」「2」「3」の3種だとして,
まず「1」は単に山札に加えるしかないです。
次の「2」は,「『1』の上」「『1』の下」のどちらかに置けます。ここでは「『1』の上」が選ばれたとします。
最後の「3」は,「『2』の上」「『2』と『1』の間」「『1』の下」のどこかに置けます。ここでは「『2』と『1』の間」が選ばれたとします。
以上で,カードは上から順に「2」「3」「1」と並んだことになります。
必ずランダムに並ぶことが保証されています。(確か。自分で考えた手法なのですが,以前自分で証明したようなしてないような)
↓にプログラムを載せます。
まず,カードを数字の順番でよいので並べます。
次に,そこから1枚ずつ順に取り出して山札に加えていきます。ただし山札のどこに加えるかは乱数で決めます。
例えばカードが「1」「2」「3」の3種だとして,
まず「1」は単に山札に加えるしかないです。
次の「2」は,「『1』の上」「『1』の下」のどちらかに置けます。ここでは「『1』の上」が選ばれたとします。
最後の「3」は,「『2』の上」「『2』と『1』の間」「『1』の下」のどこかに置けます。ここでは「『2』と『1』の間」が選ばれたとします。
以上で,カードは上から順に「2」「3」「1」と並んだことになります。
必ずランダムに並ぶことが保証されています。(確か。自分で考えた手法なのですが,以前自分で証明したようなしてないような)
↓にプログラムを載せます。
[ここをクリックすると内容が表示されます]
コード: 全て選択
#N88BASIC
' 1 から Cards までのカードをランダムに並べる
Dim Cards As Long
Dim CardPos As *Long
Dim i As Long, p As Long
Dim j As Long
Randomize
' カードの数を入力する
While Cards<=0
Input "カードの数>", Cards
Wend
' カードの配列を記憶するためのメモリーを確保
CardPos=malloc(Cards*SizeOf(Long))
' カードを順番に挿入していく
For i=1 To Cards
' 挿入する位置を決定する
p=Int(Rnd()*i)
' 挿入する
memcpy(VarPtr(CardPos[p+1]), VarPtr(CardPos[p]), (i-p-1)*SizeOf(Long))
CardPos[p]=i
' 表示する
For j=0 To i-1
Print CardPos[j];"";
Next
Print
Next
free(CardPos)
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================