I am making a quiz as part of my assignment for my computer science class and the aim is to make a flash quiz where keywords and their definitions are loaded in from text files. From previous recommendations on Daniweb I have created an associative array. I import the two files like so:

Public Keywords As String() = IO.File.ReadAllLines("C:\Users\Matt\Documents\keywords.txt")



Public Definitions As String() = IO.File.ReadAllLines("C:\Users\Matt\Documents\definitions.txt")

My dictionary looks like this:

 Dim Dict As New Dictionary(Of String, String)



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

        Dict.Add(Keywords(0), Definitions(0))
        Dict.Add(Keywords(1), Definitions(1))
        Dict.Add(Keywords(2), Definitions(2))
        Dict.Add(Keywords(3), Definitions(3))
        Dict.Add(Keywords(4), Definitions(4))
        Dict.Add(Keywords(5), Definitions(5))
        Dict.Add(Keywords(6), Definitions(6))
        Dict.Add(Keywords(7), Definitions(7))
        Dict.Add(Keywords(8), Definitions(8))
        Dict.Add(Keywords(9), Definitions(9))
        Dict.Add(Keywords(10), Definitions(10))
        Dict.Add(Keywords(11), Definitions(11))
        Dict.Add(Keywords(12), Definitions(12))
        Dict.Add(Keywords(13), Definitions(13))
        Dict.Add(Keywords(14), Definitions(14))

        LabelKeyword.Text = Dict(KeyArray)
        RadioButtonDef1.Text = Dict(DefArray)
        RadioButtonDef2.Text = Dict(DefArray2)
        RadioButtonDef3.Text = Dict(KeyArray3)

    End Sub

My randomize looks like this:

Dim Rand As New Random()
    Dim KeyIndex As Integer = Rand.Next(0, Keywords.Length - 1)
    Dim KeyArray As String = Keywords(KeyIndex)

    Dim DefIndex As Integer = Rand.Next(0, Definitions.Length - 1)
    Dim DefArray = Definitions(DefIndex)

    Dim KeyIndex2 As Integer = Rand.Next(0, Keywords.Length - 1)
    Dim KeyArray2 As String = Keywords(KeyIndex2)

    Dim DefIndex2 As Integer = Rand.Next(0, Definitions.Length - 1)
    Dim DefArray2 As String = Definitions(DefIndex2)

    Dim KeyIndex3 As Integer = Rand.Next(0, Keywords.Length - 1)
    Dim KeyArray3 As String = Keywords(KeyIndex3)

    Dim DefIndex3 As Integer = Rand.Next(0, Definitions.Length - 1)
    Dim DefArray3 = Definitions(DefIndex3)
    Dim rounds As Integer = 0

The issue I am facing is the next requirement which is:

  1. Once the user has successfully matched the keywords to the correct definition twice the option should not appear again and when all are complete twice the quiz ends and displays time taken.

I can't seem to figure out how to tell the program how to check the correct keyword to the correct definition when it is randomized.

Any help will be greatly appreciated.

Have you considered a loop? That will make the code independent of the number of words and definitions.

'using MIN ensures you don't get an error if one array is longer than the other.
'checking TRIMmed values eliminates blank entries

For i As Integer = 0 To Math.Min(UBound(Keywords), UBound(Definitions))

    Dim wrd As String = Trim(Keywords(i))
    Dim def As String = Trim(Definitions(i))

    If wrd <> "" And def <> "" Then
        Dict.Add(wrd, def)
    End If

Next

For reasons unknown to me and possibly unexplainable by Microsoft

rnd.Next(min, max)

returns a random number which is >= min and < max. So in order to generate (for example) a random number from 1 to 1-0 you must code

rnd.Next(1, 101)

I don't know if it is a requirement that you have the definitions and the words in separate files but if not then I suggest you store them in one file as in

plutocracy = govermnent by the wealthy

That way the words and definitions do not get out of sync and reading them in becomes a lot easier. Just Split the line on "=" and Trim both parts.

Now to the original question - that will depend on how you are presenting the words and definitions to the user. If, for example, a word is presented and the user selects a definition from a drop down list then all you have to do to compare them is compare Dict(displayed word) to the selected text from the drop down list. If you can be more specific as to how the quiz is presented I can be of more help.

The quiz form at the moment is a label named LabelKeyword and that displays the random keywords and the three definitions that are displayed are in radiobuttons. One of them has to match the keyword and when the user checks one and clicks next it needs to check whether the match was successful or not.

So you display a word, the correct definition, and two other unique definitions from the list. The user selects a radiobutton and the code checks to see if the selected answer is correct. What you could do is use the same handler for all three radiobuttons. See the following

Private Sub radDef_CheckedChanged(sender As System.Object, e As System.EventArgs) Handles radDef1.CheckedChanged, radDef2.CheckedChanged, radDef3.CheckedChanged

    Dim rad As RadioButton = sender

    If rad.Checked Then
        If rad.Text = Dict("plutocracy") Then
            MsgBox("correct")
        Else
            MsgBox("incorrect")
        End If
    End If

End Sub

If you notice, I created a handler for the first radiobutton then renamed it from

rad1Def_CheckedChanged

to

radDef_CheckedChanged

I then changed the Handles clause to

Handles radDef1.CheckedChanged, radDef2.CheckedChanged, radDef3.CheckedChanged

Now when the user selects any radio button the same code will execute. That's OK because you want to do the same thing no matter which button gets selected. The line

Dim rad As RadioButton = sender

gets a reference to the button that changed. One potential problem is that the event fires on a change, not just a select so if a button is already selected and the user selects a different one, the even fires for the unselect, then again for the select. We can process only the select event by

If rad.Checked Then

and you can get the text associated with the selected button by

rad.Text

now just compare that to Dict(currentWord) to see if the user chose the correct definition.

Edited 2 Years Ago by Reverend Jim

Ah I see, that's a great way of doing it, however the only thing I can't seem to figure out is how to split and then trim the keywords and definitions when they are on one line like:

Keyword1 = Definition1
Keyword2 = Definition2
Keyword3 = Definition3

and still use that same above method with a random? Do I still use:

Dict.add(Keywords(0), Definitions(0))

or do I change that as I now have them in one file?

Dictionaries are key-value pairs which are not indexed numerically (unless the key is also a number). What you can do is create a list of definitions at the same time you build the dictionary, then select two random list items (to go with the actual definition). To read the definitions you can do

For Each line As String In System.IO.File.ReadAllLines(defFile)

Next

You can split the word=definition lines by

Dim pair() As String = line.Split("=")

This will give you a two element array with pair(0) being the word and pair(1) the definition. However, you may want to do Trim(pair(0)) and Trim(pair(1)) to remove extra blanks (for example, if your file has "word = def" inistead of "word=def").

You should also check to see if pair actually has exactly two elements at each line.

By the way, you can declare the list (for randomizing) as

Private defsOnly As List(Of String)

Edited 2 Years Ago by Reverend Jim

You might consider using a class with Property values.

Quiz.vb

Public Class Quiz

    Private _question As String
    Private _answer As String
    Private _randomAnswer1 As String
    Private _randomAnswer2 As String
    Private _randomAnswer3 As String
    Private _numberOfTimesCompleted As Integer

    Public Sub New()

    End Sub

    Public Sub New(ByVal Question As String, _
                    ByVal Answer As String, _
                    ByVal RandomAnswer1 As String, _
                    ByVal RandomAnswer2 As String, _
                    ByVal RandomAnswer3 As String, _
                    ByVal NumberOfTimesCompleted As Integer)

        _question = Question
        _answer = Answer
        _randomAnswer1 = RandomAnswer1
        _randomAnswer2 = RandomAnswer2
        _randomAnswer3 = RandomAnswer3
        _numberOfTimesCompleted = NumberOfTimesCompleted

    End Sub

    Public Property Question As String
        Get
            Return _question
        End Get

        Set(value As String)
            _question = value
        End Set
    End Property 'Question

    Public Property Answer As String
        Get
            Return _answer
        End Get

        Set(value As String)
            _answer = value
        End Set
    End Property 'Answer

    Public Property RandomAnswer1 As String
        Get
            Return _randomAnswer1
        End Get

        Set(value As String)
            _randomAnswer1 = value
        End Set
    End Property 'RandomAnswer1

    Public Property RandomAnswer2 As String
        Get
            Return _randomAnswer2
        End Get

        Set(value As String)
            _randomAnswer2 = value
        End Set
    End Property 'RandomAnswer2

    Public Property RandomAnswer3 As String
        Get
            Return _randomAnswer3
        End Get

        Set(value As String)
            _randomAnswer3 = value
        End Set
    End Property 'RandomAnswer3

    Public Property NumberOfTimesCompleted As Integer
        Get
            Return _numberOfTimesCompleted
        End Get

        Set(value As Integer)
            _numberOfTimesCompleted = value
        End Set
    End Property 'NumberOfTimesCompleted

End Class

Usage:

Dim myQuiz As Quiz
Dim myQuizList As New List(Of Quiz)

Dim question As String = String.Empty
Dim answer As String = String.Empty
Dim randomAnswer1 As String = String.Empty
Dim randomAnswer2 As String = String.Empty
Dim randomAnswer3 As String = String.Empty
Dim numberOfTimesCompleted As Integer = 0

myQuiz = New Quiz(question, answer, randomAnswer1, randomAnswer2, randomAnswer3, numberOfTimesCompleted)

myQuizList.Add(New Quiz(question, answer, randomAnswer1, randomAnswer2, randomAnswer3, numberOfTimesCompleted))

You load the questions into Question and the correct answers into Answer. Randomly select three more incorrect answers to place into "RandomAnswer1", "RandomAnswer2", and "RandomAnswer3".

You could also add 3 more "RandomAnswer" properties to quiz (RandomAnswer4, RandomAnswer5, RandomAnswer6). Then populate all of the random answers at once. The first time, you could use "RandomAnswer1", "RandomAnswer2", and "RandomAnswer3" (plus Answer). The second time use "RandomAnswer4", "RandomAnswer5", and "RandomAnswer6" (plus Answer).

Then you randomly select an index in list (from 0 to myQuizList.Count - 1). When the question has been correctly answered, you update "NumberOfTimesCompleted". When "NumberOfTimesCompleted = 2", you could remove the question from the list or just skip over it.

"Quiz.vb" is attached below.

Edited 2 Years Ago by cgeier

Attachments

I have several problems with that.

  1. The idea here is not to provide a complete solution because doing so does not help the OP learn the concepts.
  2. By providing undocumented code you have probably raised more questions than you answered.
  3. You are providing an overly complex solution to a simple question.

The code I provided is basic, mostly repetative. Using dictionary is far more complex than the solution I provided. My code really only introduces 3 questions.

  1. What is a list and how do I use it?
  2. What is a property and how do I use it?
  3. What is a class and how do I use it?

I have used this code like so:

For Each line as String In System.IO.File.ReadAllLines("my-path-here")
Dim Pair() As String = line.split("=")
LabelKeyword.text = Trim(Pair(0))
RadioButtonDef1.text = Trim(Pair(1))
Next

However I don't know how to randomize this and it only picks up the very last line of the file...????

Let's say you have some globally defined objects as follows:

Private myDict As New Dictionary(Of String, String)
Private myDefs As New List(Of String)
Private myWrds As New List(Of String)

myDict will contain the word=def pairs. myDefs will be a list of only the definitions (for random access) and myWrds will be a list of only the words (again, for ranadom access). You already know how to read in the lines and populate the dictionary. You can populate myWrds and myDefs in the same loop. Now you can create a Sub to display the next step of the quiz. In this Sub you want to

  1. pick a new word at random
  2. create a list of 3 definitions
  3. display the 3 definitions in random order

To pick a random word you can generate a random number to use as an index into myWrds. Using that word you can get its corresponding definition from myDict and copy it to a label. Then copy the definition to a list. Then you can start a loop that runs until the new list has three items in it. In the loop you can pick a random definition and add it to the list (as long as it isn't already in the list - you want unique definiitions).

After that you'll have a list with three definitions, the first one being the correct one. You don't want to always have option 1 as the correct one so you'll have to populate the radio buttons randomly. Here's a hint. In my code I named the radiobuttons radDef1, radDef2 and radDef3. You should already know how to generate a random number from 1 to 3. You can access the radiobuttons dynamically by

Dim rad As RadioButton = Me.Controls("radDef" & i)

where "i" can be 1, 2 or 3. See if you can figure it out from there.

This question has already been answered. Start a new discussion instead.