プロが教えるわが家の防犯対策術!

現在私は画像のような4択の問題を解答し最後に何問正解していたかを表示するプログラムを作成しています。

解答を選択して「次の問題」ボタンをクリックすれば次の問題に移行する・・・というような流れです。

データテーブルに「問題(Question)」「選択肢(Answer1~4)」「解答(SelectAnswr)」「正解(CorrectAnswer」「正解の解説(Explanation)*今質問中では使用させません」を格納しています。

最終的な目標はデータテーブルに問題を300問用意しその中からランダムに100問出題して最後に結果を表示するプログラムを作成することです。

今どうすればランダムに出題しつつ同じ問題が出題されないようにするプラグラムを組めばいいのか壁にぶつかっています。

下記が「次の問題」ボタンのプログラムです。


Private Sub NextQuestion_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NextQuestion.Click

' i が -1 のとき(つまり、初回のクリック)
If i = -1 Then
'選択肢を選択可能にする
GroupBox1.Enabled = True

'NextQuestionのテキスト変換
NextQuestion.Text = "次の問題"
' i が -1以外のとき(つまり、回答後のクリック)
Else
'正誤確認
If Answer1.Checked = True Then
DataSet1.DataTable1(i).SelectAnswer = "ア"
ElseIf Answer2.Checked = True Then
DataSet1.DataTable1(i).SelectAnswer = "イ"
ElseIf Answer3.Checked = True Then
DataSet1.DataTable1(i).SelectAnswer = "ウ"
ElseIf Answer4.Checked = True Then
DataSet1.DataTable1(i).SelectAnswer = "エ"
End If

If DataSet1.DataTable1(i).SelectAnswer = DataSet1.DataTable1(i).CorrectAnswer Then
total = total + 1
End If

End If

i += 1 ' i をインクリメント(出題を次に進める)

' i が10になった = 回答が10問終わった
If i = 10 Then
MsgBox("あなたの正解数は10門中" & total & "問です!")
Me.Close()
Else
'問題の読み込み
Question.Text = DataSet1.DataTable1(i).Question
Answer1.Text = DataSet1.DataTable1(i).Answer1
Answer2.Text = DataSet1.DataTable1(i).Answer2
Answer3.Text = DataSet1.DataTable1(i).Answer3
Answer4.Text = DataSet1.DataTable1(i).Answer4

'ラジオボタンを初期位置に戻す
Answer1.Checked = True
End If


End Sub

*変数iはPublicで宣言しています。
*最終目標は100問出題なのですが今は10問で動くプログラムを作成しています。

わかるかたがいましたら知恵をかしてください。
お願いします。

「4択問題のプログラムでランダムに出題する」の質問画像

A 回答 (6件)

まず「次の問題に進む時、問題の参照にiを使わず、乱数で求めた0~299の値を使う」と言うように変更しましょう。



そして「初期化時や無回答で次の問題に進んだ時の、解答(SelectAnswr)にセットする値を工夫する事で、未出題か出題済みか判定する」と言う処理をして、問題の重複を避けましょう。

ヒントだけ。

ヒントは以下の通り。

ヒント1.
「解答(SelectAnswr)」に入る値を「回答された"ア"~"エ"」「無回答でスキップした"S"」「まだ出題してない""」の3種類にする。
(無回答でのスキップが出来ない、つまり、選択肢のどれかを選ばないと「次の問題」ボタンが押せない、と言う処理の場合「無回答でスキップした"S"」は不要)

ヒント2.
最初の初期化時に「300件全部、解答(SelectAnswr)の値を""にして、すべて未出題」にする。

ヒント3.
出題時に問題を参照する時「DataSet1.DataTable1(i).ほげほげ」のように「(i)」で参照するのをやめる。
代わりに、乱数で「解答(SelectAnswr)の値が、まだ出題してない""になっている問題」を探す。
つまり「乱数で0~299の値を作り、解答(SelectAnswr)の値が""なら、その乱数が出題番号になり、解答(SelectAnswr)の値が""じゃないなら乱数の作り直し」をすればよい。

ヒント4.
変数の「i」は「最初は-1」「1題出題するごとに1を足す」「100題目が終わったら終了」の目的以外には使わない。
つまり「DataSet1.DataTable1(i).ほげほげ」っていう書き方を全部無くす。

ヒント5.
選択肢を選ばずに「次の問題」を押してしまった場合「解答(SelectAnswr)」の値が「まだ出題してない""」のまま次に進んでしまっては困るので、次に進む前に「解答(SelectAnswr)の値を"S"にする」と言う処理をして「出題済み」にする。
(無回答でのスキップが出来ない、つまり、選択肢のどれかを選ばないと「次の問題」ボタンが押せない、と言う処理の場合、この処理は不要)

ヒントは以上。

なお、この方法は「300問中100問」などのように、最後の100問目に近い時も未出題の問題が多い場合は問題ありませんが「すべての問題を出題する」などの場合、最後の問題に近くなると未出題の問題が減り「残りの問題が乱数にヒットせず、次の問題に進む際に時間がかかる」と言う欠点があるので注意して下さい。今回のように「300問中100問」であれば問題はありません。
    • good
    • 0
この回答へのお礼

とても助かりました。ありがとうございます。

お礼日時:2009/10/20 12:01

BindingSourceは使い勝手が悪いかも ・・・


BindingSourceがユーザーに見えてしまっていると問題の移動自体が自由に行えてしまいます
これは抑制したほうがいいように思います

CurrnecyManagerを導入してこれで出題位置を特定したほうがいいように思います

300問中100問出題などとするのであれば DataTableに問題,回答選択子,正解などのほかに 出題順序用のフィールドを設けて
この出題順序フィールドに乱数を代入しソートした結果を使って見てはいかがでしょう
    • good
    • 1

訂正


問題文=worksheets("問題シート").cells(問題番号,2)
worksheets("問題シート").cells(問題番号,1)=1

あら、余計だったかな
    • good
    • 0

問題は「300問の中から重複無く問題を選ぶ」ということだと解釈します。


300問の問題はどこかのシートに書かれているはずですね。
一部しかコードは書きませんが、
初期化でその空いている列をクリアーする。A列とする
その後問題を選ぶたびに過去に出したかチェックする

'問題選択
問題番号=選択番号()
問題文=worksheets("問題シート").cells(選択番号,2)
worksheets("問題シート").cells(選択番号,1)=1

Function 選択番号() As Integer
  Dim ix1 As Integer
  Randomize  
  ix1 = Int((Rnd * 10) + 1)
  While worksheets("問題シート").Cells(ix1, 1) = 1
    ix1 = Int((Rnd * 10) + 1)
  Wend
  選択番号=ix1
End Function
    • good
    • 0

あああ!


chie65535さんごめんなさい・・・m(__)m
せっかくのヒントなのに邪魔してしまいました。
    • good
    • 0

問題の入ってるデータテーブルってPublicなものですか?


そうであるならば、「既に使用した(Used)」というような列を作って、

Private Sub NextQuestion_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles NextQuestion.Click

' 前の問題の答え合わせや、いろんな処理(割愛します)

Dim rnd As New Random
Dim Qindex As Intege

while

' データテーブルから問題の番号を選ぶ処理
Qindex = rnd.Next(0, 300)

' 選んだ問題が既に使用されたものかチェック
if DataSet1.DataTable1(i).used = 0 then
' 初めて使要する問題ならループを抜ける
DataSet1.DataTable1(i).used = 1
exit loop
end if

loop

End sub

こんな感じでしょうか?動作確認して無いので不備はあるかもです。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!