C# 如何从随机池中选择一个数字,然后使该数字不能重新选择
我基本上是想写一个测验作为我的计算机编程课程的一部分,但我遇到了一些麻烦 我想从一个随机的池中选择问题来阻止作弊,我可以让它在1,8的数字之间随机选择,但这会导致问题重复,这是我不想要的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>()
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-没问题,很乐意帮忙。您可能想查看我在您发表评论时正在编写的更新