• ベストアンサー

Rnd関数について

TanakaShinyaの回答

回答No.2

私のよく使うアルゴリズムは次のようなものです。 まず、問題番号のIndexを入れたテーブルを作成します。 Const c_MaxQuizNum = 40 ' 全問題数 Const c_QuizNum = 20 ' 出題数 Dim QuizIndex(c_MaxQuizNum) As Integer ' 問題の Index 格納用 Dim QuizLastNum as Integer ' 問題の残り数 Dim TmpRndm As Integer ' 選択された値 Dim RandomNo As Integer ' 選択された問題番号 Dim i As Integer For i = 1 To c_MaxQuizNum  QuizIndex(i) = i '初期値を格納 Next これを利用し、重複しない問題番号を取り出すことが可能です。 QuizLastNum = c_MaxQuizNum ' 問題の残り数初期化 For i = 1 To c_QuizNum  TmpRndm = Int((QuizLastNum * Rnd) + 1) ' 1~QuizLastNum の乱数  RandomNo = QuizIndex(TmpRndm) ' 問題番号を取得  QuizIndex(TmpRndm) = QuizIndex(QuizLastNum) ' 問題の選択肢をつめる  QuizLastNum = QuizLastNum - 1 ' 問題の残り数を減らす  ' 以降、ユーザ処理 Next つまり、簡単な例として c_MaxQuizNum = 5 としたとき、 QuizIndex には、 1 , 2 , 3 , 4 , 5 が順に入っています。 QuizLastNum には c_MaxQuizNum = 5 が入っていますね。 ここで、出題用の For ループ処理を始めると TmpRndm は 1~5 のいずれかの整数が入ります。 よって、RandomNo には 1 , 2 , 3 , 4 , 5 のいずれかが選ばれるわけです。 そして、ここからがミソなのですが、今仮に TmpRndm に 3 が選ばれるとします。 QuizIndex(TmpRndm) = QuizIndex(QuizLastNum) の処理により、QuizIndex には、 1 , 2 , 5 , 4 , 5 が入るわけです。 そして、QuizLastNum の値を 1 減らします。 すると 2 回目の For ループは どうなるでしょうか? TmpRndm は QuizLastNum を減らしたため 1~4 のいずれかの整数が入ります。 よって、RandomNo には 1 , 2 , 5 , 4 のいずれかが選ばれ、 先ほど出題した 3 は選択されません。 重複を無くし、かつ効率の良い方法でしょう? このアルゴリズムおわかりいただけましたでしょうか?

nox_neo
質問者

お礼

どうもありがとうございました。 いろいろなエラーもKojiSさんのアルゴリズムと見比べてみて 両方のアルゴリズムともにうまくいくようになりました。 話は違うんですが,なんかアルゴリズムって響きがいいですよね? TanakaShinyaさんに聞いてなんか気に入ってよく使っています。

nox_neo
質問者

補足

プログラムの意味はよくわかりました。 でも,「以降ユーザー処理」をどのようにしたらいいのかわかりません。 それと,RandomNoをどのように使ったらいいのかもわかりません。 まだ,配列もわからない状態で,やれ「インデックス~」とか「定数式がひつようです」とかエラーが大量に出てくる始末です。 何とか,自分で工夫してRandomNoのところをQuizrecord(20)とかいう配列にして QuizIndex(TmpRndm) から来るランダムな数値を格納して20までループして Quizrecord(20)を問題の順序に使用かとしたのですが,同じ乱数が同じ順序で出てきます。(8,9,7,5,2とか,これが何度も出る。)そのあたりもちょっとわかりにくい説明ですが,アドバイスいただけないでしょうか。お願いします。

関連するQ&A

  • rnd関数の使い方教えてください。

    初歩的かも知れませんが、よろしお願いします。 仕様環境:Access2007 Win7 ・・・・・ 只今、新規レコードに自動的にランダムな数字が割り振られるように テストしています。 調べたところ「rnd関数」というものを使うということが解りました。 試験用のデータベースを簡単に作り テーブルの項目(フィールド)も簡単にしました。 テストテーブル ------------------- ID(オートナンバー) 名前(テキスト型) 住所(テキスト型) 乱数(テキスト型)または(数値型)←あとで説明しますが。。 ------------------- 乱数のフィールドにある「規定値」にrnd関数を入力しテーブルを保存しようとすると、 「テーブルレベル入力規則の未定義の関数名です。。」と エラーが出てしまいます。テキスト型でも数値型でもです。 rnd関数は、、 int((200-100+1)*rnd+100) ↓入力してエンターを押すと Int((200-100+1)*Rnd()+100)となります。 つまり100から200までの間の数字をランダムに割り振ろうと挑戦しています。 ちなみにテーブルから「乱数」フィールドを消して、フォームにテキストボックスを作り、 コントロールソースに入力しても「未定義です」のようなエラーがでます。(関数の前に”=”もつけたのですが) また規定値に入力しビューで見ると「#Name?」となります。 クエリにrnd関数のフィールドを作ってフォームにつなげても出来ません。 (集計で「演算」にして作ってみたりしたのですが。。) まるっきりrnd関数の使い方がわかりません(汗)。 VBA(モジュール)は使わず、フィールドプロパティなど基本的な機能かマクロでやりたいです。 また重複しないようにしたいのです。 漠然とした相談ですが、どの場面(テーブルやクエリやフォーム)でどう使うか教えてください、 新規レコードにランダムな番号(複数桁で)割り振られるようにしたいです。 宜しくお願いします。

  • Rnd関数って

    VBのRnd関数を使って次のようにフォーム上に値を返させたときに疑問が沸いたのですが。 sub イベント() Dim Data As Single Randomize Data = Rnd() Text1.Text = Data Text2.Text = Int(Data * 100) end sub この何回かイベントを実行すると例えば text1  text2 0.367   36 0.782   78 8.591   8 の様に値が返されてきます。 ここで2つ不思議なのが HELPでRnd関数を調べると、0以上1未満の範囲の値を返します。となっているのに、なぜ8.591の様な値が出てくるのか? さらに8.591を100かけて小数点以下切り捨てると859になるはずが、なぜ8になるのか? 理由がわかる方教えてください。

  • 乱数について(Rnd関数)

    すみません。質問があります。 VBAを用いてパチスロシミュレータを作成しているのですが 乱数が偏っている気がしてなりません。 乱数はRnd関数を用いて0~65535の範囲で生成しています。 もちろん初期化時にRandomizeも用いています。 毎ゲーム開始時にそのゲームで必要な乱数を4つ r1 = Int(Rnd() * 65536) r2 = Int(Rnd() * 65536) r3 = Int(Rnd() * 65536) r4 = Int(Rnd() * 65536) というように生成しています。 それらの乱数を用いて複雑なモード移行などを行っているのですが、 ある条件下でr1のあるビットが1になりやすいというような現象が起こります。 乱数に法則性があることは不思議ではないんですが、Rnd関数による乱数っていうのは多少複雑な処理をしただけでこのような不具合が出る可能性があるのでしょうか。 私のプログラムに問題があるとは思うのですが、「もしかして、乱数のせいかも?」という疑念を抱いてデバッグするのはつらいものがあるので。 ですので、 ・変な使い方をすれば目に見えて偏る可能性もある。 という意見の方はその「変な使い方」というのを具体的に教えていただけないでしょうか? また、そのような意見の方がしばらくいらっしゃらない場合はRnd関数による乱数は実用上問題なく使えると解釈したいと思います。 よろしくおねがいします。

  • ランダムに絵を切り替えたい

    同じ位置にイメージを3枚置きます。 コマンドボタンを押すとそれがランダムに切り替えるようにしたいです。 image1 image2 image3 とイメージがあります。 int(rnd*3)と番号を作って、それを  image(番号).visible.trueに持っていくところが わかりません。 名前の結合? 説明不足ですが、何かお分かりの方がいましたら教えてください。 よろしくお願いします。

  • 乱数について。

    こんばんは。 よろしくお願いします。 エクセルVBAでランダムに問題を出題するプログラムを下記のような命令を使い作りました。(スタートボタンを押すと10問出題されるようになってます) Int((num - 1 + 1) * Rnd() + 1) 一応、通常は問題なく動作するのですが、Ctrl + Pauseなどで強制停止したあとに、もう一度問題を始めると、強制停止した時の問題と同じモノが同じ順序で出題されます。 例えば、まず普通に開始したとして、6問目の時に強制停止するとします。 そしてまた新たにスタートすると、全く同じ問題が同じ順序で出題されるのです。6問目まで全く同じです。 強制停止さえしなければ、全く問題なく動作するのですが、これは何故なのでしょう? 仕様の問題なのでしょうか?それとも僕のコーティングが悪いのでしょうか? アドバイスよろしくお願いします。

  • javaの配列部分ででエラーがでます。

    javaの配列部分ででエラーがでます。 マインスイーパを作っており爆弾の位置を決めるところでエラーの原因がわからず困っています。 9×9で、 ランダムでかぶらないように10個の爆弾を置くプログラムを作りたいです。 Random rnd=new Random(); int[][] mine=new int[8][8]; for(int i=0;i<=9;i++){ int yoko=(rnd.nextInt()>>>1)%9; int tate=(rnd.nextInt()>>>1)%9; if(mine[yoko][tate]!=10)mine[yoko][tate]=10; //爆弾があるところは10 else i--; } よろしくお願いします。

    • ベストアンサー
    • Java
  • GetLongPathName関数について

    VB6でTempフォルダをGetTempPath関数で取得するとショートファイル名でパスが返るので、 取得したショートファイル名をGetLongPathName関数でロングファイル名にしようと しているのですが上手く出来ません。 Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" _ (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long Private Declare Function GetLongPathName Lib "kernel32" Alias _ "GetLongPathNameA" (lpszShortPath As String, lpszLongPath As String, _ cchBuffer As Long) As Long Dim nName As String Dim Ret As Long Dim Buf As String nName = String$(260, vbNullChar) Ret = GetTempPath(Len(nName), nName) nName = Left$(nName, InStr(nName, vbNullChar) - 1) Buf = String$(260, vbNullChar) Ret = GetLongPathName(nName, Buf, 260) Buf = Left$(Buf, InStr(Buf, vbNullChar) - 1) Tempフォルダはショートファイル名(C:\DOCUME~1\Owner\LOCALS~1\Temp\)は 取得されますがGetLongPathName関数でロングファイル名が 返りません、戻り値は0が返ってしまいます。 コードが間違えているのか、元々取得出来ないのか分かりませんが ご存知の方教えて下さいますようお願い致します。 尚、可能ならばFindFirstFile関数でロングファイル名を取得するのではでなくて GetLongPathNameで取得したいと思っています。

  • VB6でのmmioOpen関数の使い方

    VB6でwaveファイルから音の波形を取得するプログラム を作りたいと思っているのですが、mmioOpen関数の使い方 が分からずに困っています。とりあえず現在の状況を書くと、 Private Declare Function mmioOpen Lib "winmm.dll" Alias "mmioOpenA" (ByVal szFileName As String, lpmmioinfo As MMIOINFO, ByVal dwOpenFlags As Long) As Long Private Declare Function mmioClose Lib "winmm.dll" (ByVal hmmio As Long, ByVal uFlags As Long) As Long Private Type MMIOINFO dwFlags As Long fccIOProc As Long pIOProc As Long wErrorRet As Long htask As Long cchBuffer As Long pchBuffer As String pchNext As String pchEndRead As String pchEndWrite As String lBufOffset As Long lDiskOffset As Long adwInfo(4) As Long dwReserved1 As Long dwReserved2 As Long hmmio As Long End Type Dim p1 As MMIOINFO Dim h As Long Dim closewav As Long Private Sub Command1_Click() openfilename = "C:\sample.wav" 'WAVEファイルを開く h = mmioOpen(openfilename, p1, MMIO_READ) MsgBox h If h <> 0 Then MsgBox "WAVEファイルのオープンに失敗" End If 'WAVEファイルを閉じる closewav = mmioClose(h, MMIO_FHOPEN) MsgBox closewav End Sub だれか分かる方がいれば、間違っている箇所、やり方などを教えてください。 よろしくお願いします。

  • 乱数がうまくランダムされない

    コマンドボタンを押すごとに画像をランダムに表示したいのですが 決まった順番で表示されてしまいます。 (画像はMy Picturesに440個入っています。) Sub ボタン_Click() Dim i As Long '画像をランダムに表示 i = Int((440 - 1 + 1) * Rnd + 1) Forms("フォーム1").ボタン.Picture = "D:\My Documents\My Pictures\画像" & i & ".ico" Debug.Print i End Sub コマンドボタンを何回かクリックし 上記のコート゛を実行してイミディエイトウインドウで確認すると 311 235 255 128 133 341 7 335 359 となります。 何回やってもこの順番です。 なんの規則かわかりません。 確かにランダムなのですが 本当にランダムにするのはどうすればいいでしょうか? 「i = Int((440 - 1 + 1) * Rnd + 1)」 ここに原因があると思うのですが どうすればいいでしょう? よろしくお願いします。

  • VC6.0で作成したDLLでVBからの配列を受け取る方法

    VC++でDLLを作成しています。 VBから呼び出しで、配列を渡し、その配列の値を VCで使用したいのです。 通常変数でテストして、うまくいっているのですが、 配列に変更したところ、値がうまく渡りません。 どなたかお分かりになられる方いらっしゃいましたら お力をお貸し願えないでしょうか? 変数で成功しているプログラム VB6.0 標準モジュール Declare Function fncTest Lib "fncTest.dll" (a As Long) As Long フォーム Private Sub Test_Click() dim i as integer i = fncTest(1) End Sub VC++6.0 fncTest.h fncTest_API int _stdcall fncTest(int); fncTest.cpp fncTest_API int _stdcall fncTest(int a) { a = a+1; return a; } fncTest.def     省略 変数aを配列に変更して作ってみたもの(配列bにVBからの配列aの値を入れようとしていますが、 うまくいっていません。) VB6.0 標準モジュール Declare Function fncTest Lib "fncTest.dll" (ByRef a() As Long) As Long フォーム Private Sub Test_Click() Dim i As Integer Dim hairetu(7) As Long Dim values As Variant For i = 0 To 7 hairetu(i) = i Next i values = fncTest(hairetu()) End Sub VC++6.0 fncTest.h fncTest_API int _stdcall fncTest(int*); fncTest.cpp fncTest_API int _stdcall fncTest(int* a) { int b[7]; int i; for (i = 0;i <= 7;i++){ b[i] = a[i]; } return 0; } 以上よろしくお願いします。