エクセルVBAでランダムに問題を出題するプログラムの強制停止後の挙動について

このQ&Aのポイント
  • エクセルVBAで作成したランダムに問題を出題するプログラムは、強制停止後に再度問題を始めると、停止した時の問題と同じ順序で出題される現象が発生します。
  • 強制停止さえしなければ問題なく動作するため、問題の発生は仕様の問題ではなく、コーディングに原因がある可能性があります。
  • コーディングを見直し、ランダムに問題を出題するたびに異なる順序で問題が出るように修正することをおすすめします。
回答を見る
  • ベストアンサー

乱数について。

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

質問者が選んだベストアンサー

  • ベストアンサー
  • ham_kamo
  • ベストアンサー率55% (659/1197)
回答No.1

乱数とは一見でたらめな数字を作り出すように見えて、実は内部的にはある元の数値を元に複雑な計算をしてランダムな数値を生成し、生成された乱数を元にまた次の乱数が生成されるような仕組みになっています。 したがって、その「元の数値」というのがいつも同じであれば、毎回同じ乱数が生成されることになります。 それを避けるために、プロシージャの先頭に Randomize という一文を入れてみてください。これは乱数発生ルーチンを初期化する命令で、先の説明で書いた「元の数値」をTimer関数の戻り値(つまり現時刻を表す数値)に設定します。こうすると、実行するたびに時刻は変化するので、乱数も毎回違う値になります。

Abideby
質問者

お礼

アドバイスありがとうございます! 見事に解決しました!本当に助かりました!! Randomizeって凄いですねぇ・・・。 どうもありがとうございました!

関連するQ&A

  • Rnd関数について

    今Rnd関数を使って問題を作ろうとしているのですが, 40問中から重複なしに20問ランダムに出題するというものを作ろうとしています。 しかし,重複を無くすためのプログラムの仕方がわかりません。 ついこの間,VBを始めたばかり(プログラムはVBが始めて)なので, できれば詳しい解説を書いてほしいです。 今現在考えているのはこんなのです↓ Private Function RandomCnt() As Long '********************************* '* ランダムで問題の番号を取得 * '********************************* '一時的にランダムで取得した問題番号を格納 Dim RandomNo As Long RandomNo = Int((MaxRec * Rnd) + 1) 'ランダムで番号を取得 Do While volQuizNo(RandomNo) = True 'まだ出していない問題が見つかる間 RandomNo = Int((MaxRec * Rnd) + 1) 'ランダムで番号を取得 Loop volQuizNo(RandomNo) = True '出題問題のチェック RandomCnt = RandomNo End Function

  • FLASH CS5でnow loadingでランダム再生を読み込みたい

    FLASH CS5でnow loadingでランダム再生を読み込みたい FLASH CS5で10枚の画像(表示されいるのは1枚で、左右に隣の画像が少し見える感じ)があり、その下に右、左のボタンがありを押していくと、画像が切り替わっていくアニメなのですが 開始のフレームをアクセスする度に変わるランダムにしたいです。(開始の画像が入るたびに変わる) そのためにnow loadingですべてを読み込ませてからスタートさせないとなのですが、 1フレーム目に以下のタグを入れました。 このやり方だと、エラーがでます。 //再生停止 stop(); //イベントリスナーを登録 //(毎フレーム時間で実行,実行関数 goRnandom) this.addEventListener(Event.ENTER_FRAME,goRnandom); //関数 goRnandom の定義 function goRnandom(evt:Event):void { //変数 per にロードされたパーセントを取得 var per:Number = this.loaderInfo.bytesLoaded / this.loaderInfo.bytesTotal * 100; // //もしロードパーセンテージが 100 に達すれば if (per >= 100) { //登録したイベントリスナーを削除 this.removeEventListener(Event.ENTER_FRAME, goRnandom); //変数 rnd_num に 0以上1未満 のランダムな数を代入 var rnd_num:Number = Math.random(); if (rnd_num < 10 / 100) { gotoAndPlay(2); } else if (rnd_num < 10/100) { gotoAndPlay(8); } else if (rnd_num < 10/100) { gotoAndPlay(14); } else if (rnd_num < 10/100) { gotoAndPlay(20); } else if (rnd_num < 10/100) { gotoAndPlay(26); } else if (rnd_num < 10/100) { gotoAndPlay(32); } else if (rnd_num < 10/100) { gotoAndPlay(38); } else if (rnd_num < 10/100) { gotoAndPlay(44); } else if (rnd_num < 10/100) { gotoAndPlay(50); } else { gotoAndPlay(57); } } } どこか間違っている箇所はあるのでしょうか? 教えてください。

    • ベストアンサー
    • Flash
  • キーボードについて

    素人です。またお願いします。 ●Pause/Break Pauseはプログラムの動作を一時停止するのに使います。 Breakはプログラムを強制終了するのに使います。 と、答えているのですが、(Pause/Break)のキーを押しても変わらないのはどうしてでしょうか。 教えてくださいお願いします。

  • javascript 乱数が取得できない

    はじめまして。 一月ほど前から「パズルネット ソフィア」 http://www.pori2.net/js/number/4.html というサイトでjavascriptの基礎を学んでいるのですが、乱数 を扱う段階になって自分の作成したプログラム(以下) <html> <head> </head> <body onload="Mondai()"> <form name="quiz"> <input type="text" value="" > <input type="button" value="赤" onclick="Push(0)"> <input type="button" value="青" onclick="Push(1)"> <input type="button" value="黄" onclick="Push(2)"> <input type="button" value="緑" onclick="Push(3)"> <input type="button" value="白" onclick="Push(4)"> </form> <script type="text/javascript"> <!-- var col=new Array("red","bleu","yellow","green","white"); var Rnd; function Mondai(){ Rnd=Math.floor(Math.random() * 5 ); document.quiz.element[0].value=col[Rnd]; } function Push(num){ var n=parseInt(num); if( n==Rnd ){ Mondai(); }else{ alert("違います。"); } } // --></script> </body> </html> を実行してもテキストボックス内に何の値も表示されず 、ボタンを押しても「違います。」とだけしか出てきません。 ブラウザはfirefoxを使用しており、javascriptの設定もonに なっています。 カンマや鍵括弧などの記号にも打ち間違いがないかサンプル プログラムを参考にしながら確認してみたのですが、どこにも おかしな点はありませんでした。 サンプルプログラムは下記のとおりで、こちらは正常に実行されます。 <body onload="Mondai()"> <form name="quiz"> <input type="text" value=""> <input type="button" value="赤" onclick="Push(0)"> <input type="button" value="青" onclick="Push(1)"> <input type="button" value="黄" onclick="Push(2)"> <input type="button" value="緑" onclick="Push(3)"> <input type="button" value="白" onclick="Push(4)"> </form> <script type="text/javascript"> <!-- //色名の英単語を配列に入れる var col=new Array("red","blue","yellow","green","white"); //乱数を入れる変数 var Rnd; //テキストボックスに問題文(色名)を表示する関数 function Mondai(){ //0~4までの乱数を発生させる Rnd=Math.floor( Math.random() * 5 ); document.quiz.elements[0].value=col[Rnd]; } //正誤判定関数 function Push(num){ //引数を数字に変換 var n=parseInt(num); //正解なら次の問題を表示、間違っていたらアラートを表示する if ( n == Rnd ){ Mondai(); }else{ alert("違います!"); } } // --> </script> どなたかアドバイスをいただけないでしょうか? よろしくお願いします。

  • Excel VBAの割り算の記述に関して

    各シートにA列とB列の計算した結果をC列に出力するようなExcel VBAの記述をしたいのですが、 シートAには、計算する個数を入力します。 開発タブよりフォーム コントロールのボタンを選択します。 ボタンを押すと シートBには、A列とB列のそれぞれの値の和の結果をC列に シートCには、A列とB列のそれぞれの値の差の結果をC列に シートDには、A列とB列のそれぞれの値の積の結果をC列に シートEには、A列とB列のそれぞれの値の商の結果をC列に シートEの割り算の計算ですが、小数点を出力したい。 割り算がうまく出力してくれません。"/"を使えば良いと思うのですが、異なる結果が出て困っています。以下の記述のどこが間違っているのでしょうか。 Sub 問題作成() Dim count As Long Dim input_training As Long Dim left_num As Long Dim right_num As Long Dim answer_num As Long input_training = Range("A1").Value ' 加算 Worksheets("SheetB").Range(("A2"), ("C100000")) = "" ' 減算 Worksheets("SheetC").Range(("A2"), ("C100000")) = "" ' 積 Worksheets("SheetD").Range(("A2"), ("C100000")) = "" ' 商 Worksheets("SheetE").Range(("A2"), ("C100000")) = "" Randomize For count = 1 To input_training left_num = Int(1000 * Rnd) right_num = Int(1000 * Rnd) answer_num = left_num + right_num Worksheets("SheetB").Cells(1 + count, 1) = left_num Worksheets("SheetB").Cells(1 + count, 2) = right_num Worksheets("SheetB").Cells(1 + count, 3) = answer_num Next ' 減算 For count = 1 To input_training left_num = Int(1000 * Rnd) right_num = Int(1000 * Rnd) answer_num = left_num - right_num Worksheets("SheetC").Cells(1 + count, 1) = left_num Worksheets("SheetC").Cells(1 + count, 2) = right_num Worksheets("SheetC").Cells(1 + count, 3) = answer_num Next ' 積 For count = 1 To input_training left_num = Int(1000 * Rnd) right_num = Int(1000 * Rnd) answer_num = left_num * right_num Worksheets("SheetD").Cells(1 + count, 1) = left_num Worksheets("SheetD").Cells(1 + count, 2) = right_num Worksheets("SheetD").Cells(1 + count, 3) = answer_num Next ' 商 For count = 1 To input_training left_num = Int(1000 * Rnd) right_num = Int(1000 * Rnd) answer_num = left_num / right_num Worksheets("SheetE").Cells(1 + count, 1) = left_num Worksheets("SheetE").Cells(1 + count, 2) = right_num Worksheets("SheetE").Cells(1 + count, 3) = answer_num Next End Sub

  • 問題: 以下の2つのプログラムを実装し、時間計算量を実験的に評価せよ。

    問題: 以下の2つのプログラムを実装し、時間計算量を実験的に評価せよ。     (1)1から1万までの整数ちをランダムに1千個生成するプログラム     (2)シェルソートプログラム 質問内容   プログラム()をやったんですが、「時間計算量を実験てきに評価せよ」というのは分かりません。 教えてください。 /* ランダムプログラ*/ #include<stdio.h> #include<stdlib.h> #include<time.h> #define N 1000 void main(){ FILE *fp; int i,rnd; fp=fopen("data.dat","w"); srand((int)time(NULL)); for(i=1;i<=N;i++){ rnd = (int)rand()% 10000 + 1; fprintf(fp,"%d\n ", rnd); } fclose(fp); } /* シェルソートプログラム*/ #include <stdio.h> #include <stdlib.h> #define DATA_NUM 1000 void ShellSort(int num[ ], int n) ; void InsSort(int num[ ], int gap, int n); void ShowData(int num[ ], int n); void main(void); /* n 個のデータのシェルソートを行う */ void ShellSort(int num[ ], int n) { int gap; for (gap = n / 2; gap > 0; gap /= 2) InsSort(num, gap, n); } /* n 個のデータの単純挿入ソートを行う */ void InsSort(int num[ ], int gap, int n){ int i, j, temp; for (i = gap; i < n; i ++) { for (j = i - gap; j >= 0; j -= gap) { /* このループで */ if (num[j] <= num[j + gap]) /* j 番目とj + gap 番目と比較 */ break; /* ここにbreak;を挿入。*/ else { temp = num[j]; /* 要素の入れ替え */ num[j] = num[j + gap]; num[j + gap] = temp; ShowData(num,DATA_NUM); /* 途中経過を表示 */ } } } printf("\n"); /* InsSort( ) を抜ける時改行 */ } /* n 個のデータの表示 */ void ShowData(int num[ ], int n) { while (n--) printf("%d ", *num++); printf("\n"); } void main(void) { FILE *fp; int data[DATA_NUM]; int i; fp = fopen("data.dat","r"); if(fp == NULL){ printf("data.dat cannot be opened"); exit(1); } for(i=0;i<DATA_NUM;i++){ if(fscanf(fp,"%d",&data[i])== NULL){ break; } } printf("ソート前\n"); ShowData(data, DATA_NUM); printf("\n"); /* シェルソート */ ShellSort(data, DATA_NUM); printf("\n"); printf("ソート後\n"); ShowData(data,DATA_NUM); printf("\n"); fclose(fp); }

  • ランダムで画像を表示させるには?

    環境はFlashCS5で、アクションスクリプト3.0を使用しています。 5枚の画像(インスタンス名:mc0~mc4)をランダムで表示させるムービーを制作しているのですが、 下記のスクリプトですと、ランダムで画像が表示されるのですが、画像の切り替えがループになってしまって、次から次へとランダムで画像が切り替わります。フレーム1に下記のスクリプトを記述し、フレーム1にムービーインスタンス「mc0」から「mc4」を配置しています。 function randomShowMC():void { for (var i:int=0; i<5; i++) { this["mc" + i].visible = false; } var rnd:int = Math.floor(Math.random() * 5); this["mc" + rnd].visible = true; } randomShowMC(); var myTimer:Timer = new Timer(3000); myTimer.addEventListener(TimerEvent.TIMER ,function(){randomShowMC()}); myTimer.start(); このスクリプトを改良?改造?して、ランダムの画像が1回のみ…つまり、おみくじみたいに、(mc0~mc4の画像を)ランダムで1回のみ画像を表示させたいのです…表示後の画像が切り替わらずそのままで停止させたいのです。 又は、ムービーインスタンス「mc0」から「mc4」の画像をランダムで表示させ、最初に表示された、その画像で停止させるスクリプトを新規に記述しても構いませんので、ご指導・アドバイスをお願い致します…。 どなたか、解る方がいましたらランダム画像表示で1回表示のみのループしないスクリプトを教えてください。よろしくお願い致します…。

    • ベストアンサー
    • Flash
  • VC# 強化学習

    VC#2010で強化学習のプログラムを作ろうと考えているのですが、 実行すると「NullReferenceExceptionはハンドルされませんでした。 オブジェクト参照がオブジェクト インスタンスに設定されていません。」 というエラーが出てプログラムが動きません。 ソースは static public Random rnd; static void Main(string[] args) { double[][] Qtable; //Qtable double Q_max = 0;//Q値の最大値 double reward = 0; //報酬 double alpha = 0.5;//学習係数 double gamma = 0.9;//減衰係数 int epsilon = 10;//行動を無作為に選ぶ確率[%] int trial_max = 100;//試行回数 int num_a = 2;//行動の数 int num_s = 2;//状態の数 int a = 0;//行動 int s = 0;//状態 int sd = 0;//行動の実行によって遷移する状態 int i, j; //メモリー空間の確保 Qtable = new double [num_s][]; for (i = 0; i < num_s; i++) { Qtable[i] = new double[num_a]; } //Q値の初期化 for (i = 0; i < num_s; i++) { for (j = 0; j < num_a; j++) { Qtable[i][j] = 0; Console.WriteLine("Q[{0}][{1}]={2}\n", i, j, Qtable[i][j]); } } //試行開始 for (i = 0; i < trial_max; i++) { //行動の選択 a = epsilon_greedy(epsilon, s, num_a, Qtable); a = 1; //行動の実行 reward = vending_machine(s, a, sd); //sdにおけるQ値の最大値を求める Q_max = max_Qval(sd, num_a, Qtable); //Q値の更新 Qtable[s][a] = (1 - alpha) * Qtable[s][a] + alpha * (reward + gamma * Q_max); s = sd; Console.WriteLine("i={0}\n", i); if (reward > 0) { Console.WriteLine("成功\n", a); } if (reward == 0) { Console.WriteLine("失敗\n", a); } } //Qtableの表示 for (i = 0; i < num_s; i++) { for (j = 0; j < num_a; j++) { Console.WriteLine("{0} ", Qtable[i][j]); } Console.Write("\n"); } return; } static double vending_machine(int s, int a, int sd) { double reward; if (a == 0) { if (s == 0) sd = 1; if (s == 1) sd = 0; reward = 0; } else { if (s == 1) { sd = s; reward = 10; } else { sd = s; reward = 0; } } return reward; } static double max_Qval(int s, int num_a, double [][] Qtable) { double max; int i = 0; max = Qtable[s][0]; for (i = 1; i < num_a; i++) { if (Qtable[s][i] > max) { max = Qtable[s][i]; } } return max; } static int select_action(int s, int num_a, double [][] Qtable) { double max; int i = 0; int[] i_max; i_max = new int[num_a]; int num_i_max = 1; int a; i_max[0] = 0; max = Qtable[s][0]; for (i = 1; i < num_a; i++) { if (Qtable[s][i] > max) { max = Qtable[s][i]; num_i_max=1; i_max[0]=i; } else if (Qtable[s][i] == max) { num_i_max++; i_max[num_i_max - 1] = i; } } int seed = Environment.TickCount; rnd = new Random(seed++); a = i_max[rnd.Next(num_i_max)]; return a; } static int epsilon_greedy(int epsilon, int s, int num_a, double [][] Qtable) { int a; if (epsilon > rnd.Next(100)) { //無作為に行動を選択 a = rnd.Next(num_a); } else { //最大のQ値を持つ行動を選択 a = select_action(s, num_a, Qtable); } return a; } のような感じです。 どなたか分かる方がいれば、教えていただけるとありがたいです。 よろしくお願いします。

  • 1から9までの数値をランダムに発生させたい

    ●質問の主旨 INT関数及びRND関数を使い、「0から9」までの 数値をランダムに発生させるのではなく、「1から9」 までの数値をランダムに発生させるには、下記のコードを どのように書き換えれば良いでしょうか? ●質問の補足 下記コード及び画像のように九九の計算問題を 作成したいと思っています。今のコードでは 「0から9」までの数値が発生するのは、分かっていたので If ThenステートメントやSelect Caseステートメントを 使って、0の数値が発生するときは「1」とみなすというような 記述もしてみましたが、上手くいきませんでした。 ご存知のかたよろしくお願いします。 なお使用機種はWindowsVista、Excel2007を使用しています。 私はVBAをはじめて3カ月程度です。 ●コード Option Explicit Const ORG_RW As Integer = 4 '問題の開始行 Const DST_RW As Integer = 8 '問題の終了行 Const NUM1_CLM As Integer = 1 '問題の数値1の列 Const NUM2_CLM As Integer = 3 '問題の数値2の列 Const ANSW_CLM As Integer = 5 '問題の解答の列 Private Sub CommandButton1_Click() 'Checkボタン Dim i As Integer 'カウンタ変数 For i = ORG_RW To DST_RW'問題の開始行から問題の終了行まで If Cells(i, NUM1_CLM).Value * Cells(i, NUM2_CLM).Value = Cells(i, ANSW_CLM).Value Then Cells(i, ANSW_CLM).Font.Color = vbBlue '問題が正解のときは文字が青色 Else Cells(i, ANSW_CLM).Font.Color = vbRed '問題が正解のときは文字が赤色 End If Next i End Sub Private Sub CommandButton2_Click() 'Resetボタン Dim i As Integer 'カウンタ変数 For i = ORG_RW To DST_RW Cells(i, ANSW_CLM).ClearContents '解答が消去される Cells(i, ANSW_CLM).Font.Color = vbBlack '解答が消去されたときは文字が黒色 ' 解答が消去されたときは0~9までのランダムな数値が発生     Cells(i, NUM1_CLM).Value = Int(Rnd * 10) '解答が消去されたときは0~9までのランダムな数値が発生 Cells(i, NUM2_CLM).Value = Int(Rnd * 10) Next i End Sub

  • while for/ if else/do while文を使い”640968592”の各数字を独立させて取り出すことは可能でしょうか?

    忙しい中失礼します。 今以下のようなプログラミングを組もうとしています。 1.”640968592”といった9桁の数字を入力→scanfで入力(これは出来ます) 2.各桁の数字を独立させて取り出す:”6” ”4” ”0” ”9” ”6”・・・といった具合に(これも一応出来ます) 3.偶数桁は2倍する   2桁目:4x2=8   4桁目:9x2=18   6桁目:8x2=16   8桁目:9x2=18 そして、私の場合、以下のようなプログラムになるのですが、これがなんとも不細工な感じがし、スマートにプログラムを変更したいと思っています。 抱えている問題:while for/ if else/do while文などを用いて、下記のプログラムを書き直すことは可能なのでしょうか?例え出来たとしても、文int=num1~num35までの定義も減らすことは可能なのでしょうか? 手も足も出ない・・・ プログラム内容 #include <stdio.h> #include <stdlib.h> #include <math.h> int main() { int num1,num2,num3,num4; /*8 9桁目*/ int num5,num6; /*7桁目*/ ・ ・ ・ int num15,num16; /*2桁目*/ int num17; /*1桁目*/ int num19,num20,num21,num22,num23,num24,num25; int num26,num27,num28,num29,num30,num31,num32; int num33,num34,num35; printf("Write the SIN: "); scanf ("%d", &num1); num2=num1 / pow(10, 8); //9桁目 num3=num1 / pow(10, 7); //8桁目 num4=num3 % 10; num5=num1 / pow(10, 6); //7桁目 num6=num5 % 10; ・ ・ ・ num15=num1/pow(10, 1); //2桁目 num16=num15%10; num17=num1%10; //1桁目 num19=num4*2; //8桁目計算 num20=num19/10; num21=num19%10; num22=num20+num21; ・ ・ ・ num31=num16*2; //2桁目計算 num32=num31/10; num33=num31%10; num34=num32+num33; system("pause"); return 0; } こんなのが直ぐにプログラムとして早く組めるようになりたい・・・ どうしても頭に浮かばないのです。アドバイス等あればお願いします。 <使用環境:フリーソフト(Borland?)C ANSI C>

専門家に質問してみよう