I am trying to make a multiple choice revision program, but I am having some issues with how I should get my program to generate another question, which I have stored in a database, after the user answers the first generated question? Can someone show me an example of a code or something along those lines please?
Imports System.Data.OleDb
Public Class QUI
'Define all the variables which are meant to be in use'
Dim ConnectString As String = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=projectdatabase.accdb")
Dim DataReader As OleDbDataReader
Dim cmd As New OleDbCommand
Dim connection As New OleDbConnection
Dim noofq As Integer
Dim q(noofq) As String
Dim questionnum As Integer
'Asks the user to input a number to d
Private Sub QUI_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Asks the user to input a number to decide how many questions they want to answer'
noofq = InputBox("Input the number of questions you want. You can choose from 1 to 10.")
'A counter starting from one to the number of questions the user has inputted'
For i = 1 To noofq
Next
'Open the connection to the database'
connection.ConnectionString = ConnectString
connection.Open()
'Sets the question number to one'
questionnum = 1
Label1.Text = "Question " & questionnum & " of " & noofq
'Retrieves the question and answers from the database'
cmd.CommandText = "SELECT question, Answer1, Answer2, Answer3 FROM 1Questions"
cmd.Connection = connection
DataReader = cmd.ExecuteReader
'Assigns the values from the database to each of the labels and buttons'
If DataReader.HasRows Then
DataReader.Read()
Lblquestion.Text = DataReader.Item("Question")
RadioButtonA1.Text = DataReader.Item("Answer1")
RadioButtonA2.Text = DataReader.Item("Answer2")
RadioButtonA3.Text = DataReader.Item("Answer3")
DataReader.Close()
End If
connection.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles btnCheck.Click
If RadioButtonA1.Checked And questionnum = 1 Then
MsgBox("Correct Answer")
Else
MsgBox("Incorrect Answer")
End If
End Sub
End Class
CodePudding user response:
In the question table, if you add a column representing the question code, then you can generate random numbers to choose from the questions. It is also possible to add features such as not repeating the same question. That is if I understood your question well
CodePudding user response:
Apparently you did not take my advice and turn on Option Strict. Please do so now.
This is what you database table should look like. The QuestionID
should be an auto-number column and the CorrectAnswer
column should contain the name of the radio button that will contain the correct answer.
Your main problem is that you have retrieved all the data from the 1Questions table but you only read the first record. You would have to connect to the database again to retrieve another question. This is a bad idea.
We will retrieve all the data you need and put it in a DataTable
which is like an in memory table. To start the database objects will be declared and disposed in Using blocks. This is necessary so their Dispose
methods will be called. You do not declare these objects outside of the method where they are used. You can pass the connection string directly to the constructor of the Connection
and pass the CommandText
and Connection
directly to the constructor of the Command
.
I have changed the sql string to include the primary key of the table. I had to guess at the field name so change that to the real name. I also added a field for the correct answer. That may need to be added to the table. The last part of the sql string has an Order By
clause that will return random questions each time it is run.
The important point here is that the database connection is closed and disposed. All the data we need for the quiz is in the DataTable
.
I used a BindingSource
so we can display the data and easily move through the questions.
Private ConStr As String = ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=projectdatabase.accdb")
Private intNumOfQuestions As Integer
Private questionnum As Integer
Private BndScr As BindingSource
Private Sub QUI_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim strnoofq = InputBox("Input the number of questions you want. You can choose from 1 to 10.")
If Integer.TryParse(strnoofq, intNumOfQuestions) AndAlso intNumOfQuestions > 0 AndAlso intNumOfQuestions < 11 Then
Dim dt As New DataTable
Using cn As New OleDbConnection(ConStr),
cmd As New OleDbCommand($"SELECT Top {intNumOfQuestions} QuestionID, Question, Answer1, Answer2, Answer3, CorrectAnswer
FROM 1Questions
ORDER BY Rnd(-Timer()*[QuestionID])", cn)
cn.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
questionnum = 1
Label1.Text = $"Question {questionnum} of {strnoofq}"
BndScr = New BindingSource()
BndScr.DataSource = dt
Lblquestion.DataBindings.Add("Text", BndScr, "Question")
Lblquestion.DataBindings.Add("Tag", BndScr, "CorrectAnswer")
RadioButtonA1.DataBindings.Add("Text", BndScr, "Answer1")
RadioButtonA2.DataBindings.Add("Text", BndScr, "Answer2")
RadioButtonA3.DataBindings.Add("Text", BndScr, "Answer3")
Else
MessageBox.Show("Please enter valid number Of questions.")
End If
End Sub
Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click
If GetSelectedRadioButton(Me).Name = Lblquestion.Tag.ToString Then
'Correct Answer
Else
'Wrong Answer
End If
If intNumOfQuestions = questionnum Then
'End of quiz
Else
BndScr.MoveNext()
questionnum = 1
End If
End Sub
Public Function GetSelectedRadioButton(Container As Control) As RadioButton
Dim rb = Container.Controls.OfType(Of RadioButton)().FirstOrDefault(Function(r) r.Checked = True)
Return rb
End Function
It is up to you how to keep score.