C# 如何从随机池中选择一个数字,然后使该数字不能重新选择

C# 如何从随机池中选择一个数字,然后使该数字不能重新选择,c#,random,C#,Random,我基本上是想写一个测验作为我的计算机编程课程的一部分,但我遇到了一些麻烦 我想从一个随机的池中选择问题来阻止作弊,我可以让它在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,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);
    }
但出于某种原因,数字总是一样的,这意味着Q1、Q2、Q3和Q4的分配都显示了完全相同的问题,我真的不知道这里出了什么问题,有人能帮忙吗


编辑:我个人要感谢杰米克,伙计,你是一个十足的救生员,没有你我不可能做到这一点,谢谢

你已经走到一半了。一般的想法是选择一个随机数,然后删除该元素,使其无法重新选择。但是,为了使所有元素都是随机的,您需要在每次尝试后从减少的集合中选取一个新的随机数

 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;博士 你不必每次都尝试生成一个随机数,你只需将列表随机化,抓取满足你需求的前n项即可

细节 如果你总共有20个问题,但是测验只有10个,那么将20个问题的列表随机化并选择前10个。我还建议您创建一个数据结构来存储此信息,而不仅仅是AssignmentForQ1、AssignmentForQ2等。请使用以下内容:

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; }
    }
}
然后将其存储在列表中并按如下方式随机排列:

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个随机问题,没有重复!虽然这不是最优化的洗牌,但它只是完成了任务。查看更多关于如何安全有效地洗牌列表的详细说明


最后,尝试使用类来封装数据,这将使事情变得更容易理解,并在时机成熟时进行扩展。

您没有更改随机数,因此您选择1作为示例,所有操作都以1为准。因为您只生成一个随机数,然后使用它来访问您的分配列表。randomNumber被分配一个值,然后保留分配的值。您需要调用randomNumber=RandomlyChooseNumbers.NextAssignments.Count;每次使用后。旁注:按顺序挑选通常更容易理解…快告诉我吧。OP可能希望将其推广到一个循环中。当我发现自己一遍又一遍地写着同样的代码时,我总是开始担心…@PaulGriffin-我百分之百同意。伙计,你是个十足的救命恩人!非常感谢你帮助我@JamesHadnett-没问题,很乐意帮忙。您可能想查看我在您发表评论时正在编写的更新