閑話休題

前回までのあらすじ

クイズの問題を「ランダムで出題する」というロジックを
組む場合、単純に「発生させた乱数の番号の問題を出題」
とすると、仮に1が連続して10回発生した場合、1問目の
問題が10回重複して出題されてしまうという問題が発生。

で、一度出題した問題は出題対象から外すため、フラグを
用意して、「もう出題しちゃいましたよ」フラグが立って
いる番号は無視し、再度乱数を発生させるとした場合には
レスポンスが低下するという別の問題が発生した。


んでだ、考え方を変え、ロジックをごっそり変更して見た。
今回はそんなハナシ。


えーとトランプをイメージして下さい。
クイズの問題をカードに置き換えて、スペードのAから
Kまで13枚のカードをランダムで表示するというプログラムを
組むとした場合、今までのやり方は下記の様な感じで、
スペードとハート2組のスートを用意して…


スペード(表示するカード)
A 2 3 4 5 6 7 8 9 10 J Q K
ハート(表示を制御するカード)
A 2 3 4 5 6 7 8 9 10 J Q K


乱数で1が発生した場合、スペードのAを表示。さらに
ハートのAを裏返す。


スペード(表示するカード)
A 2 3 4 5 6 7 8 9 10 J Q K
ハート(表示を制御するカード)
□ 2 3 4 5 6 7 8 9 10 J Q K


2枚目のカードを表示する際も乱数を発生させ、その
番号のハートのカードを確認。表向きならスペードの
カードを表示しハートのカードを裏返す、裏面が表示
(既に表示したカード)されていれば、乱数発生に戻る。


この方法の場合、全てのカードを表示させるのに最短では
13回の乱数を発生させれば終わりだが、最長は…無限。


人間様がこれと同じコトを行なう場合、当然そんなことは
しない…よね?
まずはトランプを裏返してシャッフルし、先頭から順に
めくって行くんじゃないかな?で13枚めくっておしまい。


それをプログラムにすれば良いんじゃないの?


まずはAからKまでのカードを用意
A 2 3 4 5 6 7 8 9 10 J Q K

乱数を13回発生させ、その回数の番号のカードと発生した
乱数の番号のカードを入れ替える。

最終的にシャッフルされたカードを、1番目から順に表示する。

ハイ、発生させる乱数は13回のみ、しかもシャッフルする
のは最初の1回だけなので、表示ごとのレスポンスの低下も
当然なし。


仮に1が連続して13回発生したとしても同一カードが重複して
表示される心配も無し。


えーと、1が連続して13回発生した場合をシミュレートして
みますか…。


1回目に1が発生。(1枚目と1枚目を入れ替え)変化なし
A 2 3 4 5 6 7 8 9 10 J Q K
2回目に1が発生。(2枚目と1枚目を入れ替え)
2 A 3 4 5 6 7 8 9 10 J Q K
3回目に1が発生。(3枚目と1枚目を入れ替え)
3 A 2 4 5 6 7 8 9 10 J Q K
4回目に1が発生。(4枚目と1枚目を入れ替え)
4 A 2 3 5 6 7 8 9 10 J Q K


…13回目には…まぁシャッフルされてないのと同じになるんだけど、
あくまで極端な例(レアケース)なんでOKってことで。


このトランプの考えの、カードの部分をクイズ問題に置き換えれば
どうすれば良いか判るよね。


Dim numArray() As Integer '配列を用意します
Dim workNum As Integer
Dim i As Integer
Dim j As Integer

'ここにファイルに格納されている問題の数を
'取得する処理を記述する。

lowerbound = 1
upperbound = ??? '取得した問題数を代入

ReDim numArray(lowerbound To upperbound)
Randomize

'配列に1から順に数値を格納する
For i = lowerbound To upperbound
  numArray(i) = i
Next i

'i番目と発生した乱数番目の値を入れ替える
For i = lowerbound To upperbound
  j = Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
  workNum = numArray(i)
  numArray(i) = numArray(j)
  numArray(j) = workNum
Next i

これでシャッフル完了。
あとは配列numArray()の先頭から最後までに格納されている番号の
問題を出題すればおしまい。


'配列を先頭から最後までなめる
For i = lowerbound To upperbound
  'numArray(i)に格納されている数字番目の問題を読み込む
  'ファイルのオープン部とかは割愛してるんでこのままでは動かないよ
  Get #1, numArray(i), strQuestion
Next i


んでは今回はここまで。