ある数を除いての乱数の出し方は?

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
shosho

ある数を除いての乱数の出し方は?

#1 投稿記事 by shosho »

皆さん初めまして。乱数の出し方に困ってます。

例えば、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回目以降の乱数の結果が、既出の数字だから、もう一度振りなおすのではなくて、既出の数字は、抜けた状態で、乱数を振る。同じ条件での、振りなおしなし。

というようなものです。

可能でしょうか? どなたかご指導よろしくお願いします。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: ある数を除いての乱数の出し方は?

#2 投稿記事 by hira »

こんな感じでしょうか。
例えば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の乱数を使って同様に。
この要領でいけばすでに出た数ははじめから選択に該当しません。

※完全に感覚でやっているので、効率悪いかもしれませんが…
Toshi
記事: 98
登録日時: 2005年7月19日(火) 19:47
お住まい: 山形県
連絡する:

#3 投稿記事 by Toshi »

コード: 全て選択


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

まず配列を順番通りに作ってから、適当な 2 ヶ所を交換します。
(定数 CHANGE を増やせば交換の回数が増えて、よりシャッフルされます)
これを配列の最初から見ていくと、見事に乱数になっています。
shosho

#4 投稿記事 by shosho »

hiraさん、Toshiさん、ありがとうございます。

伏せてある、100枚の数字カードを、一枚ずつ、開いて(表示して)ゆき、どういう順番で、表示されるか。というような、シミュレーションと、言えばいいのかもしれません。

それを私が、コンピューター上でやると、2回目以降の乱数の結果に、在ってはならないはずの、既出の数字が出てしまうことが多くあり、ごまかしに、その回だけ、やり直し、結果がよければ次へ、というようになってしまいます。まぁ、妥協すれば、それでもいいのですが、現実的にはありえず、シミュレーションとはなりません。

実は、今日、突然思い立って、Active Basicをダウンロードし、PC8001の画面を、思い出しつつの、プログラミングなので、まだ、よく理解で来てませんが、hiraさんのコードが、私の考えに沿う形に、なっているように思えます。
もう少し、勉強してみます。
Yoshi
記事: 27
登録日時: 2005年5月31日(火) 22:17
お住まい: 山口
連絡する:

#5 投稿記事 by Yoshi »

> 伏せてある、100枚の数字カードを、一枚ずつ、開いて(表示して)ゆき、どういう順番で、表示されるか。というような、シミュレーションと、言えばいいのかもしれません。

> 実は、今日、突然思い立って、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
Sinryow
記事: 141
登録日時: 2005年5月31日(火) 09:34
お住まい: 北海道
連絡する:

#6 投稿記事 by Sinryow »

私が考えたのは,以下のような方法です。

まず,カードを数字の順番でよいので並べます。
次に,そこから1枚ずつ順に取り出して山札に加えていきます。ただし山札のどこに加えるかは乱数で決めます。

例えばカードが「1」「2」「3」の3種だとして,
まず「1」は単に山札に加えるしかないです。
次の「2」は,「『1』の上」「『1』の下」のどちらかに置けます。ここでは「『1』の上」が選ばれたとします。
最後の「3」は,「『2』の上」「『2』と『1』の間」「『1』の下」のどこかに置けます。ここでは「『2』と『1』の間」が選ばれたとします。
以上で,カードは上から順に「2」「3」「1」と並んだことになります。

必ずランダムに並ぶことが保証されています。(確か。自分で考えた手法なのですが,以前自分で証明したようなしてないような)

↓にプログラムを載せます。
' ============================================================
' Sinryow Game Home Page - http://www.sinryow.net/
' Sinryow ActiveBasic Center - http://ab.sinryow.net/
' ============================================================
shosho

#7 投稿記事 by shosho »

Sinryouさん、ありがとうございます。

なるほど、逆の考え方なのですね。 良いヒントになります。
返信する