如何从随机池中 select 一个数字,然后使数字无法重新 select

How to select a number from random pool, then make so number can't be reselected

我基本上是想写一个测验作为我的计算机编程课堂作业的一部分,但我 运行 遇到了麻烦。

我希望从 运行dom 池中选择问题以防止作弊,我可以做到 运行domly 在 1,8 之间选择,但这可能会导致提问中重复,这是我不想要的。

Random random = new Random(); // We use this random object to choose random icons for the squares.

    List<int> Assignments = new List<int>()
    {

        1,2,3,4,5,6,7,8

    };

    Random RandomlyChooseNumbers = new Random();

    int AssignmentForQ1;
    int AssignmentForQ2;
    int AssignmentForQ3;
    int AssignmentForQ4;
    string CorrectAnswerA1;
    string CorrectAnswerA2;
    string CorrectAnswerA3;
    string CorrectAnswerA4;
    public double timePassed;
    public int calculatedScore;
    public int timeLeft;

    public frmQuizOneHardMode()
    {
        InitializeComponent();

        AssignQuestionToTextQ1();

    }

    private void AssignQuestionToTextQ1()
    {
        int randomNumber = RandomlyChooseNumbers.Next(Assignments.Count);

        AssignmentForQ1 = Assignments[randomNumber];

        Assignments.RemoveAt(randomNumber);

        AssignmentForQ2 = Assignments[randomNumber];

        Assignments.RemoveAt(randomNumber);

        AssignmentForQ3 = Assignments[randomNumber];

        Assignments.RemoveAt(randomNumber);

        AssignmentForQ4 = Assignments[randomNumber];

        Assignments.RemoveAt(randomNumber);
    }

但由于某种原因,数字总是相同的,这意味着 AssignmentForQ1、Q2、Q3 和 Q4 都显示完全相同的问题,我完全不知道这里出了什么问题,有人可以帮忙吗?

编辑:我个人要感谢 Jamiec,伙计,你真是个救星,没有你我做不到,谢谢!

您已经完成了一半。一般的想法是选择一个随机数,然后删除该元素,这样它就不能被重新选择。但是,为了使所有元素都是随机的,您需要在每次尝试后从缩减集中选择一个 new 随机数。

 int randomNumber1 = RandomlyChooseNumbers.Next(Assignments.Count);

 AssignmentForQ1 = Assignments[randomNumber1];

 Assignments.RemoveAt(randomNumber1);

 // set is reduced
 int randomNumber2 = RandomlyChooseNumbers.Next(Assignments.Count);

 AssignmentForQ2 = Assignments[randomNumber2];

Assignments.RemoveAt(randomNumber2);

这可以通过使用数组进行赋值和循环来简化

int[] Questions = new int[4];
for(var i=0;i<Questions.Length;i++)
{
    int randomNumber = RandomlyChooseNumbers.Next(Assignments.Count);
    Questions[i] = Assignments[randomNumber];
    Assignments.removeAt(randomNumber);
}

TL;DR

不必每次都尝试生成一个随机数,您可以随机化列表并获取第一个 n 项可以满足您的要求。

详情

如果你总共有 20 个问题,但测验只有 10 个,那么随机化 20 个列表和 select 前 10 个。我还建议你创建一个数据结构来存储这些信息,而不仅仅是 AssignmentForQ1AssignmentForQ2 等。使用如下内容:

public class Question
{
    public int Assignment { get; set; }
    public string ActualAnswer { get; set; }
    public string SelectedAnswer { get; set; }

    public bool IsCorrect
    {
        get { return String.Equals(ActualAnswer, SelectedAnswer, 
            StringComparison.InvariantCultureIgnoreCase); }
    }
}

public class Quiz
{
    public List<Question> Questions { get; set; }

    public int CalculatedScore
    {
        get { return Questions.Count(q => q.IsCorrect); }
    }

    public DateTime TimeStarted { get; set; }
    public TimeSpan TimeAllowed { get; set; }

    public TimeSpan TimeRemaining
    {
        get { return DateTime.Now - (TimeStarted + TimeAllowed); }
    }

    public TimeSpan TimeElapsed
    {
        get { return DateTime.Now - TimeStarted; }
    }
}

然后将它们存储在 List<Question> 中并像这样随机化它:

Random rand = new Random();
List<Question> questions = new List<Question>();

var myQuiz = new Quiz
{
    TimeAllowed = TimeSpan.FromMinutes(15),
    Questions = questions.OrderBy((q) => rand.Next()).Take(10).ToList()
};

这会给你 10 个随机问题,没有重复!虽然这不是最优化的洗牌,但它只是完成了工作。查看 this answer 以获取有关如何安全有效地随机排列列表的更详细说明。

最后,尝试使用类封装你的数据,它会让事情变得更容易理解和扩展。