为我的测验问题创建一个随机顺序
本文关键字:一个 随机 顺序 我的 问题 创建 | 更新日期: 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();
}
}
}
为了确保每个问题只被问一次,我会使用两个列表:AnsweredQuestions
和UnansweredQuestions
。
开始时,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);
}