为我的测验问题创建一个随机顺序

本文关键字:一个 随机 顺序 我的 问题 创建 | 更新日期: 2023-09-27 18:24:23

我创建了一个测试应用程序,并使用switch语句来解决问题。即从1到2到3到4,依此类推。然而,一旦用户完成了一次测试并想重新开始,他们就必须重新完成所有相同的问题。(设计是,如果他们弄错了,应用程序就会退出)。因此,我想看看是否有一种方法可以随机化QuestionCount的数字(但只生成一次这个数字),或者我可以用其他方法来做。我可以看到使用列表有一些建议,但这些建议似乎集中在列表中包含的大量问题上,而我的问题目前只有20个问题。

我已经复制了当前正在使用的代码。

private void Verify(int Question)
{
    switch (Question)
    {
        case 1:
            if (checkBox1.Checked && !checkBox2.Checked && !checkBox3.Checked && !checkBox4.Checked)
            {
                MessageBox.Show("Correct - Well Done");
                //This was a test to see if I could assign a random number which works but the number could then appear again meaning the user gets the same question
                Random random = new Random();
                QuestionCount = random.Next(0, 21);
                QuestionSelection(QuestionCount);
                //SelectLabel(QuestionCount);
                ClearcheckBox();
            }
            else
            {
                MessageBox.Show("No - It was Sunguard");
                Application.Exit();
            }
            break;
        case 2:
            if (checkBox3.Checked && !checkBox2.Checked && !checkBox1.Checked && !checkBox4.Checked)
            {
                //this method was the original where it just adds 1 to QuestionCount and works it way through the switch statement for the questions.
                MessageBox.Show("Correct - Well Done");
                QuestionCount++;
                QuestionSelection(QuestionCount);
                //SelectLabel(QuestionCount);
                ClearcheckBox();
            }
            else
            {
                MessageBox.Show("No - It's to look at a students details");
                Application.Exit();
            }
    }
}

为我的测验问题创建一个随机顺序

为了确保每个问题只被问一次,我会使用两个列表:AnsweredQuestionsUnansweredQuestions

开始时,AnsweredQuestions为空,UnansweredQuestions包含所有要问的问题。现在你可以像上面的代码中已经有的那样使用随机发生器了。作为random.Next()的最大值,您采用UnansweredQuestions列表的当前项Count

问题回答正确后,您可以将其从UnansweredQuestions列表中删除,并将其放入AnsweredQuestions列表中。

这样,你的随机化器只使用那些真正没有答案的问题。

为什么不把所有的问题都放在一个列表中,然后打乱它:

public List<T> RandomPermutation<T>(List<T> array)
{
    Random random = new Random();
    List<T> retArray = new List<T>(array);
    int maxIndex = array.Count - 1;
    for (int i = 0; i <= maxIndex; i++)
    {
        int swapIndex = random.Next(i, maxIndex);
        if (swapIndex != i)
        {
            T temp = retArray[i];
            retArray[i] = retArray[swapIndex];
            retArray[swapIndex] = temp;
        }
    }
    return retArray;
}

如果只有少量可能的值,则可以将选择编码为Uint64中的位标志。我在下面添加了一个这样做的例子。

为了方便起见,我使用了BitArray。最好使用bit wise&和|运算符。结果被打包到一个UInt64中,但对于标志和值,它可以很容易地是两个单独的Uint32。

private static UInt64 Next(UInt64 current, int questions)
{
    // Convert the current value to an array of bytes.
    // Remove the least significant 4 bytes.
    // and then create a flag array.
    var bytes = BitConverter.GetBytes(current);
    bytes[0] = bytes[1] = bytes[2] = bytes[3] = 0;
    var flags = new BitArray(bytes);
    // If all questions has been answered then exit with 0.
    var all = Enumerable.Range(32, questions).All(flags.Get);
    if (all)
        return 0UL;
    // Make a random next value, if the value has been used then repeat.
    var random = new Random(DateTime.Now.Millisecond);
    var next = random.Next(questions);
    while (flags.Get(next + 32))
        next = random.Next(questions);
    // set the flag value for the guess.
    flags.Set(next + 32, true);
    // convert the flags back to Uint64 and add the next value.
    flags.CopyTo(bytes, 0);
    return BitConverter.ToUInt64(bytes, 0) + Convert.ToUInt64(next);
}

测试使用:

var first = Next(0UL, 20);
while (first != 0UL)
{
    var v = first & 0xFFFFFFFF;
    Console.Out.WriteLine(v);
    first = Next(first, 20);
}