-4

I have created a Quiz application in Visual Basic.I have stored the questions in a text file and I'm using streamreader to read the lines.The text file looks like this

If x is the first of five consecutive odd numbers then what is their average ?
x
x+1
x+4
x+3
3
Which of the following number is divisible by 24 ?
76300
78132
80424
81234
3

The first line is the question,the lines 2 to 5 is the options and the 6th line is the answer key and there are more than 100 questions and I should print random questions and its corresponding choices each time I open the application and it should not repeat the same question.Can any one give me a code snippet for this?

Imports System.IO
Imports System.Runtime.InteropServices

Public Class Quiz
    Public ques As Integer = 1
    Dim Shuffle As Integer = 0
    Dim SCORE As Integer = 0
    Dim val As Integer = 30
    Public anskey As String
    Private currentQuestion As Integer
    Private listOfQuestions As List(Of Question) = New List(Of Question)
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
    End Function
    Public Sub Reset_all()
        val = 30
        SCORE = 0
        ProgressBar1.Value = 0
        Button3.Hide()
        ProgressBar1.Minimum = 0
        ProgressBar1.Maximum = 30
        Timer1.Enabled = True
        Using reader = New System.IO.StreamReader("Quiz.txt")
            Dim line = reader.ReadLine()
            While (Not String.IsNullOrWhiteSpace(line))
                Dim question = New Question
                question.Question = line
                question.Choice1 = reader.ReadLine()
                question.Choice2 = reader.ReadLine()
                question.Choice3 = reader.ReadLine()
                question.Choice4 = reader.ReadLine()
                question.Answer = reader.ReadLine()
                listOfQuestions.Add(question)
                line = reader.ReadLine()
            End While
        End Using

        If listOfQuestions.Count > 0 Then
            LoadQuestion(0)
        End If
    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Reset_all()
    End Sub

    Sub LoadQuestion(questionIndex As Integer)

        Dim question = listOfQuestions(questionIndex)
        currentQuestion = questionIndex
        If listOfQuestions.Count - 1 = currentQuestion Then

        End If
        With question
            Label3.Text = ques
            Label1.Text = .Question
            RadioButton1.Text = .Choice1
            RadioButton2.Text = .Choice2
            RadioButton3.Text = .Choice3
            RadioButton4.Text = .Choice4
            anskey = .Answer
        End With
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        If (SCORE > 0) Then
            SCORE -= 1
        End If
        If (currentQuestion > 0) Then
            If (ques > 0) Then
                ques -= 1
                LoadQuestion(currentQuestion - 1)
            End If
        End If
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If (anskey = "a" And RadioButton1.Checked = True Or anskey = "b" And RadioButton2.Checked = True Or anskey = "c" And RadioButton3.Checked = True Or anskey = "d" And RadioButton4.Checked = True) Then
            SCORE += 1
        End If

        If (currentQuestion < listOfQuestions.Count - 1) Then
            If (ques <= 99) Then
                ques += 1
                LoadQuestion(currentQuestion + 1)
            End If
        End If
    End Sub
    Private Sub Quiz_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        Dashboard.Show()
        Me.Hide()
    End Sub
    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
        ProgressBar1.Value += 1
        val -= 1
        Label2.Text = val & " Sec"
        If ProgressBar1.Value = ProgressBar1.Maximum Then
            Timer1.Enabled = False

        End If
        If ProgressBar1.Value > 23 Then
            SendMessage(ProgressBar1.Handle, 1040, 2, 0)
            Button3.Show()

        End If
        If ProgressBar1.Value = 30 Then

        End If
    End Sub

    Private Sub SubmitResult()
        MsgBox("You have Scored " + SCORE.ToString + " Out of 100")
    End Sub
    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Dim Re As Integer = MsgBox("Are you sure you want to submit?",
    vbYesNo, "Submit")
        If (Re = 6) Then
            SubmitResult()
            Try
                Me.Close()
                Dashboard.Show()
            Catch ex As Exception
            End Try
        End If
    End Sub

    Private Sub Label1_Click(sender As Object, e As EventArgs) Handles Label1.Click

    End Sub
End Class
Public Class Question

    Public Property Question As String
    Public Property Choice1 As String
    Public Property Choice2 As String
    Public Property Choice3 As String
    Public Property Choice4 As String
    Public Property Answer As String

End Class
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • 5
    *"Give me the code"* is not welcome here in SO. Please think in something, try something and code something. Once done please share with us your relevant code so we can help you. – ɐsɹǝʌ ǝɔıʌ Mar 06 '16 at 08:40
  • 2
    @ExtremeDimension - Please don't link off to external sites - put your code in your question. If the external site disappears or the URLs become broken then the question is too. – Enigmativity Mar 06 '16 at 10:22

4 Answers4

0
  • First, I would recommend using the File.ReadAllLines() function to get an array of lines in the text file with questions. Then you can access them easily.

  • If you observe, the index of the line of the question will be (n - 1) * 6, where n is the question number. Once you get that, the indices of the options are given by:

    i + 1
    i + 2
    i + 3
    i + 4
    

    where i = (n - 1) * 6. The answer key is given by:

    i + 5
    

That should get you started. If you get stuck, leave a comment :)

  • So you would do the first part by:

    Dim lines() As String = File.ReadAllLines("<yourQuestions.txt")
    
  • Then, you can generate a random number within the required range using:

    Dim questionNumber As Integer = Random.Next(1, (lines.Length / 6) + 1)
    
  • After that, you can retrieve the question, options and answer key by:

    Dim i As Integer = (questionNumber - 1) * 6
    Dim question As String = lines(i)
    Dim options() As String = {lines(i + 1), lines(i + 2), lines(i + 3), lines(i + 4)}
    Dim answerKey As String = lines(Integer.Parse(lines(i + 5)))
    

You can also consider creating a class Question:

Public Class Question

    Public Property Question As String
    Public Property Choice1 As String
    Public Property Choice2 As String
    Public Property Choice3 As String
    Public Property Choice4 As String
    Public Property Answer As String

    Public Sub New(q As String, c1 As String, c2 As String, c3 As String, c4 As String, ans As String)
         Question  = q
         Choice1 = c1
         Choice2 = c2
         Choice3 = c3
         Choice4 = c4
         Answer = ans
    End Sub

End Class

Then you can assign the properties.

Another alternative (might be better in performance, in fact, I think it should be) would be to use the File.ReadLines() function and use the Take() and Skip() extension methods of IEnumerable<T> (LINQ):

Dim questionNumber As Integer = Random.Next(1, (File.ReadLines("<yourQuestions.txt").Count() / 6) + 1)
Dim blockLines = File.ReadLines("<yourQuestions.txt").Skip((questionNumber - 1) * 6).Take(6)
Dim currentQuestion As New Question(blockLines(0), blockLines(1), blockLines(2), blockLines(3), blockLines(4), blockLines(blockLines(5)))
Fᴀʀʜᴀɴ Aɴᴀᴍ
  • 6,131
  • 5
  • 31
  • 52
  • [File.ReadLines](https://msdn.microsoft.com/en-us/library/system.io.file.readlines%28v=vs.110%29.aspx) is a better choice. – Enigmativity Mar 06 '16 at 09:00
0

I would make a class "question" like this:

public Class Question

public questionas String
public answer1 as String
public answer2 as String
public answer3 as String
public answer4 as String
public correctAnswer as integer

public sub new(que as string, a1 as string, a2 as string, a3 as string, a4 as string, answer as integer)
    question= que
    answer1=a1
    answer2=a2
    answer3=a3
    answer4=a4
    correctAnswer=answer
end sub


end Class

Now load all your questions in the programm like this:

Imports System
Imports System.IO

Class MainWindow
    private listQuestions as List(Of Question)

Public Sub window_loaded() handles MainWindow.loaded
    listQuestions = loadAllQuestions()        
End Sub



private function loadAllQuestions() as List(Of Question)
Dim str() As String
    Try
        ' Open the file using a stream reader.
        Using sr As New StreamReader("example.txt")
            Dim line As String
            ' Read the stream to a string and write the string to the console.

            line = sr.ReadToEnd()
            Str = line.Split(vbNewLine)
        End Using
    Catch e As Exception
        Console.WriteLine("The file could not be read:")
        Console.WriteLine(e.Message)
    End Try

   'So now put the questions in your list:

    dim list as new List(Of Question)

    For i = 0 to str.count - 1
        if (i+1) mod 5 = 0 then 'is divible without rest by 6
           list.add(new Question(str(i-5), str(i-4), str(i-3), str(i-2), str(i-1), str(i))
        end if

    next

    return list



end sub

'Load a random question:
private sub btNext_click() handles btNext.click()
    dim ranQuestion as Question

    dim r as new random

    ranQuestion = listFragen.item(r.next(0,listQuestions.count))


End Class

Hope i could help you. To prevent that the programm can show the same question again its your job :)

julienduchow
  • 1,026
  • 1
  • 11
  • 29
0

To start with, load your questions this way:

Dim questions = _
    File _
        .ReadLines("questions.txt") _
        .Select(Function (x, n) New With { .Line = X, .Index = n }) _
        .GroupBy(Function (xn) xn.Index \ 6, Function (xn) xn.Line) _
        .Select(Function (xs) New Question() With _
        { _
            .Question = xs(0), _
            .Choice1 = xs(1), _
            .Choice2 = xs(2), _
            .Choice3 = xs(3), _
            .Choice4 = xs(4), _
            .Answer = xs(5) _
        }) _
        .ToArray()

That'll give you an array for your questions:

questions

Next, you need to create a "queue.txt" file that contains the indices of your questions in a random order that you wish to display them in. Here's how to create your queue:

Dim rnd = New Random()

Dim queue = _
    Enumerable _
        .Range(0, questions.Length) _
        .OrderBy(Function (n) rnd.Next()) _
        .Select(Function (n) n.ToString()) _
        .ToArray()

File.WriteAllLines("queue.txt", queue)

Then when you load your program, you can read this file and choose the next question to ask, and save the file, skipping the first question for next time, like this:

Dim queue = File.ReadAllLines("queue.txt")

Dim questionToAsk As Question = questions(Integer.Parse(queue.First()))

File.WriteAllLines("queue.txt", queue.Skip(1))

It would be up to you to make sure that the file is created when it doesn't exist and to write the code that checks if you've asked all the questions and need to re-create the queue.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
0

Here are the basics of a class that uses XML.

Public Class QuestionAndAnswer

    'the container for all questions/answers
    Private ReadOnly qa As XElement = <QandA></QandA>
    'the container for a question and some number of possible answers
    Private ReadOnly ent As XElement = <entry></entry>
    'the question
    Private ReadOnly aquestion As XElement = <question></question>
    'an answer - the c attribute will be "y" for the correct answer
    Private ReadOnly ananswer As XElement = <answer c=""></answer>

    Private theQA As XElement

    Public Sub New()
        Me.theQA = New XElement(qa) 'set up
    End Sub

    Public Sub New(path As String)
        Me.theQA = XElement.Load(path)
    End Sub

    Public Sub Save(path As String)
        Me.theQA.Save(path)
    End Sub

    Private Function AddQuestion(theQuestion As String, correctAnsw As String) As XElement
        Dim e As New XElement(ent)
        Dim q As New XElement(aquestion)
        Dim a As New XElement(ananswer)
        q.Value = theQuestion
        a.Value = correctAnsw
        a.@c = "y"
        e.Add(q)
        e.Add(a)
        Me.theQA.Add(e)
        Return e
    End Function

    Public Function AddQuestion(theQuestion As String, correctAnsw As String,
                                ans1 As String) As XElement
        Dim e As XElement = Me.AddQuestion(theQuestion, correctAnsw)
        Dim a As New XElement(ananswer)
        a.Value = ans1
        e.Add(a)
        Return e
    End Function

    Public Function AddQuestion(theQuestion As String, correctAnsw As String,
                                ans1 As String, ans2 As String) As XElement
        Dim e As XElement = Me.AddQuestion(theQuestion, correctAnsw, ans1)
        Dim a As New XElement(ananswer)
        a.Value = ans2
        e.Add(a)
        Return e
    End Function

    Public Function AddQuestion(theQuestion As String, correctAnsw As String,
                                ans1 As String, ans2 As String, ans3 As String) As XElement
        Dim e As XElement = Me.AddQuestion(theQuestion, correctAnsw, ans1, ans2)
        Dim a As New XElement(ananswer)
        a.Value = ans3
        e.Add(a)
        Return e
    End Function

    Public Function AddQuestion(theQuestion As String, correctAnsw As String,
                                ans1 As String, ans2 As String, ans3 As String, ans4 As String) As XElement
        Dim e As XElement = Me.AddQuestion(theQuestion, correctAnsw, ans1, ans2, ans3)
        Dim a As New XElement(ananswer)
        a.Value = ans4
        e.Add(a)
        Return e
    End Function

    Private Shared prng As New Random
    Public LastQuestionAnswer As String

    Public Function RandomQuestion() As String
        Dim q As XElement = Me.SelectRandomQ
        If q IsNot Nothing Then
            Dim rv As New System.Text.StringBuilder
            rv.AppendLine(q.<question>.Value)
            rv.AppendLine()
            Dim ie As IEnumerable(Of XElement)
            ie = From qa In q.<answer>
                 Select qa

            ie = ie.OrderBy(Function() prng.Next(q.<answer>.Count))

            Dim x As Integer = 1

            For Each a As XElement In ie
                If a.@c = "y" Then
                    Me.LastQuestionAnswer = x.ToString
                End If
                rv.AppendFormat("{0}. {1}", x, a.Value)
                rv.AppendLine()
                x += 1
            Next
            rv.AppendLine()
            Me.LastQuestionAnswer = Me.LastQuestionAnswer.Insert(0, rv.ToString)
            Debug.WriteLine(Me.LastQuestionAnswer)
            Return rv.ToString
        End If
        Return ""
    End Function

    Private Function SelectRandomQ() As XElement
        If Me.theQA IsNot Nothing AndAlso Me.theQA.<entry>.Count > 0 Then
            Dim ie As IEnumerable(Of XElement)
            ie = From ent In Me.theQA.Elements
                 Where ent.@used <> "y"
                 Select ent
            Dim rv As XElement = ie(prng.Next(ie.Count))
            rv.@used = "y"
            Return rv
        End If
        Return Nothing
    End Function
End Class

A form with a richtextbox and a button shows it

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim foo As New QuestionAndAnswer
    foo.RandomQuestion()

    foo.AddQuestion("Which Vietnam War film directed by Francis Ford Coppola followed a screenplay based on famous adventure story Heart of Darkness?",
                    "Apocalypse Now",
                    "Good Morning Vietnam",
                    "Born on the Fourth of July",
                    "Band of Brothers")

    foo.AddQuestion("What was the name of the baseball pitcher that hit a bird with a pitch during a 2001 Spring Training game?",
                    "Randy Johnson",
                    "Mike Mussina",
                    "Roger Clemens",
                    "Greg Maddux",
                    "Johan Santana")

    foo.AddQuestion("The third largest desert in the world is the Sahara, what is the first?",
                    "Antarctic",
                    "Gobi",
                    "Sonoran")

    foo.AddQuestion("How many US presidents have died while in office?",
                    "8",
                    "6",
                    "7")

    foo.AddQuestion("If x is the first of five consecutive odd numbers > 0, then what is their average?",
                    "x + 4",
                    "x",
                    "x + 1",
                    "x + 3")

    Dim qa As New System.Text.StringBuilder
    foo.RandomQuestion()
    qa.AppendLine(foo.LastQuestionAnswer)
    qa.AppendLine()
    foo.RandomQuestion()
    qa.AppendLine(foo.LastQuestionAnswer)
    qa.AppendLine()
    foo.RandomQuestion()
    qa.AppendLine(foo.LastQuestionAnswer)
    RichTextBox1.Text = qa.ToString
End Sub
dbasnett
  • 11,334
  • 2
  • 25
  • 33