如何在 vb 中显示文本文件中的随机问题?

How to display random ques from text file in vb?

我在 Visual 中创建了一个测验应用程序 Basic.I 将问题存储在一个文本文件中,我正在使用 streamreader 阅读 lines.The 文本文件,如下所示

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

第一行是问题,第二到第五行是选项,第六行是答案,有100多个问题,每次打开都要打印随机问题和对应的选项应用程序,它不应该重复相同的 question.Can 谁能给我一个代码片段?

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
  • 首先,我建议使用 File.ReadAllLines() 函数来获取文本文件中包含问题的行数组。然后你就可以轻松访问它们了。

  • 如果您观察,问题行的索引将是 (n - 1) * 6,其中 n 是问题编号。一旦你得到它,选项的索引由以下给出:

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

    其中 i = (n - 1) * 6。答案由:

    i + 5
    

这应该让你开始了。如果您遇到困难,请发表评论:)

  • 所以你可以通过以下方式完成第一部分:

    Dim lines() As String = File.ReadAllLines("<yourQuestions.txt")
    
  • 然后,您可以使用以下方法生成所需范围内的随机数:

    Dim questionNumber As Integer = Random.Next(1, (lines.Length / 6) + 1)
    
  • 之后,您可以通过以下方式检索问题、选项和答案键:

    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)))
    

你也可以考虑创建一个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

然后你可以分配属性。

另一种选择(性能上可能更好,事实上,我认为应该如此)是使用 File.ReadLines() 函数并使用 Take()Skip() 扩展方法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)))

我会做一个 class "question" 这样的:

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

现在像这样在程序中加载所有问题:

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

希望能帮到你。为了防止程序再次显示相同的问题,这是你的工作:)

首先,以这种方式加载您的问题:

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()

这将为您的问题提供一个数组:

接下来,您需要创建一个 "queue.txt" 文件,其中包含您希望以随机顺序显示的问题的索引。创建队列的方法如下:

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)

然后当你加载你的程序时,你可以读取这个文件并选择下一个要问的问题,然后保存文件,下次跳过第一个问题,就像这样:

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

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

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

您需要确保在文件不存在时创建该文件,并编写代码来检查您是否已提出所有问题并需要重新创建队列。

这是使用 XML 的 class 的基础知识。

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

带有富文本框和按钮的表单

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