C# 中多维数组的随机化

发布于 2024-12-10 00:41:56 字数 755 浏览 0 评论 0原文

对于一个迷你项目,我正在制作一个测验程序 我当前的(相关)代码如下:

static Random _r = new Random();        
static int Quiz()
{
    string[,] QAndA = {
        {"What is the capital of France", "Paris"},
        {"What is the capital of Spain", "Madrid"},
                ...
        {"What is the captial of Russia", "Moscow"},
        {"What is the capital of Ukraine", "Kiev"},
    };

    for (int i = 0; i < NUM_QUESTIONS; i++)
    {
        int num = _r.Next(QAndA.GetLength(0) / 2);
        Question(QAndA[num, 0], QAndA[num, 1]);
    }
}

现在,明显的问题是随机数可以重复,这意味着问题可以重复。

现在,我的老师(是的,这是学校的事情)告诉我寻找洗牌算法,但我未能找到任何适用于我使用的多维数组的算法。

我是一个相当新的 C# 程序员,但我有 C++ 经验 并且该程序是一个命令行程序(目前:)),如果这很重要/有帮助

那么,问题是,将多维数组重新排序/洗牌为随机顺序的最佳方法是什么?

For a mini project I am making a quiz program
My current (relavant) code is as follows:

static Random _r = new Random();        
static int Quiz()
{
    string[,] QAndA = {
        {"What is the capital of France", "Paris"},
        {"What is the capital of Spain", "Madrid"},
                ...
        {"What is the captial of Russia", "Moscow"},
        {"What is the capital of Ukraine", "Kiev"},
    };

    for (int i = 0; i < NUM_QUESTIONS; i++)
    {
        int num = _r.Next(QAndA.GetLength(0) / 2);
        Question(QAndA[num, 0], QAndA[num, 1]);
    }
}

Now, the obvious problem with this is that the random numbers can be repeated, meaning that questions can be repeated.

Now, my teacher (yes, this is a school thing) told me to look for shuffling algorithms, but I have failed to find any that work for multidimensional arrays like i have used.

I am a fairly new c# programmer, but I have experience with c++
and the program is a commandline program (at the moment :) ), if that matters/helps

So, the question is, what's the best way of reordering/shuffling the multidimensional array to be in a random order?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

抱着落日 2024-12-17 00:41:56

你正在寻找错误的问题。使用锯齿状数组代替多维数组(很少使用,因为几乎不支持)。

string[][] questions = new[] { 
    new [] {"What is the capital of France", "Paris"}, 
    new [] {"What is the capital of Spain", "Madrid"},
    new [] {"What is the captial of Russia", "Moscow"},
    new [] {"What is the capital of Ukraine", "Kiev"},
};

// use: questions[0][0] (question), questions[0][1] (answer), questions[1][0] (question)...

或者(更好)创建一个包含两个成员的类:QuestionAnswer

class QuestionAndAnswer
{
    public string Question { get; protected set; }
    public string Answer { get; protected set; }

    public QuestionAndAnswer(string question, string answer)
    {
        this.Question = question;
        this.Answer = answer;
    }
}

QuestionAndAnswer[] questions = new QuestionAndAnswer[] { 
    new QuestionAndAnswer("What is the capital of France", "Paris"),
    new QuestionAndAnswer("What is the capital of Spain", "Madrid"),
    // ...
};

// use: questions[0].Question, questions[0].Answer...

然后,您可以使用 Knuth 算法:-)

引用那里

To shuffle an array a of n elements (indexes 0..n-1):
  for i from n − 1 downto 1 do
       j ← random integer with 0 ≤ j ≤ i
       exchange a[j] and a[i]

: C# 算法类似于

Random rnd = new Random();

for (int i = questions.Length - 1; i >= 1; i--)
{
    // Random.Next generates numbers between min and max - 1 value, so we have to balance this
    int j = rnd.Next(0, i + 1);

    if (i != j)
    {
        var temp = questions[i];
        questions[i] = questions[j];
        questions[j] = temp;
    }
}

You are looking at the wrong problem. Instead of a multidimensional array (something quite rarely used because scarcely supported) use a jagged array.

string[][] questions = new[] { 
    new [] {"What is the capital of France", "Paris"}, 
    new [] {"What is the capital of Spain", "Madrid"},
    new [] {"What is the captial of Russia", "Moscow"},
    new [] {"What is the capital of Ukraine", "Kiev"},
};

// use: questions[0][0] (question), questions[0][1] (answer), questions[1][0] (question)...

or (better) create a class with two members, Question and Answer.

class QuestionAndAnswer
{
    public string Question { get; protected set; }
    public string Answer { get; protected set; }

    public QuestionAndAnswer(string question, string answer)
    {
        this.Question = question;
        this.Answer = answer;
    }
}

QuestionAndAnswer[] questions = new QuestionAndAnswer[] { 
    new QuestionAndAnswer("What is the capital of France", "Paris"),
    new QuestionAndAnswer("What is the capital of Spain", "Madrid"),
    // ...
};

// use: questions[0].Question, questions[0].Answer...

You could then use the Knuth algorithm :-)

Quoting from there:

To shuffle an array a of n elements (indexes 0..n-1):
  for i from n − 1 downto 1 do
       j ← random integer with 0 ≤ j ≤ i
       exchange a[j] and a[i]

In C# the algorithm will be something like

Random rnd = new Random();

for (int i = questions.Length - 1; i >= 1; i--)
{
    // Random.Next generates numbers between min and max - 1 value, so we have to balance this
    int j = rnd.Next(0, i + 1);

    if (i != j)
    {
        var temp = questions[i];
        questions[i] = questions[j];
        questions[j] = temp;
    }
}
策马西风 2024-12-17 00:41:56

如果它不是多维数组,我建议使用“多维”数组。

我的建议:(查看现场http://ideone.com/NsjfM

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    struct QA { public string Q, A; }

    static Random _r = new Random();        
    static int Quiz()
    {
        var QAndA = new QA[] {
            new QA { Q = "What is the capital of France"  , A = "Paris"}, 
            new QA { Q = "What is the capital of Spain"   , A = "Madrid"}, 
            //  ...
            new QA { Q = "What is the captial of Russia"  , A = "Moscow"}, 
            new QA { Q = "What is the capital of Ukraine" , A = "Kiev"}, 
        };

        foreach (var qa in QAndA.OrderBy(i => _r.Next()))
        {
            Question(qa.Q, qa.A);
        }

        return 0;
    }

    public static void Main(string[] args)
    {
        int n = Quiz();
    }

    private static void Question(string q, string a)
    {
        Console.WriteLine("Q. {0}", q);
        Console.WriteLine("A. {0}", a);
    }

}

I suggest NOT using a 'multidimensional' array if it is ... not an multidemensional array.

My suggestion: (see it live here http://ideone.com/NsjfM)

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    struct QA { public string Q, A; }

    static Random _r = new Random();        
    static int Quiz()
    {
        var QAndA = new QA[] {
            new QA { Q = "What is the capital of France"  , A = "Paris"}, 
            new QA { Q = "What is the capital of Spain"   , A = "Madrid"}, 
            //  ...
            new QA { Q = "What is the captial of Russia"  , A = "Moscow"}, 
            new QA { Q = "What is the capital of Ukraine" , A = "Kiev"}, 
        };

        foreach (var qa in QAndA.OrderBy(i => _r.Next()))
        {
            Question(qa.Q, qa.A);
        }

        return 0;
    }

    public static void Main(string[] args)
    {
        int n = Quiz();
    }

    private static void Question(string q, string a)
    {
        Console.WriteLine("Q. {0}", q);
        Console.WriteLine("A. {0}", a);
    }

}
◇流星雨 2024-12-17 00:41:56
maybe better (without shouffling, without repeatable questions):       



class QuizQuestion
{
public string Question {get; set;}
public string Answer {get; set;}
}

static Random _r = new Random();        
        static int Quiz()
        {
            QuizQuestion[] QAndA = new QuizQuestion[] {
                new QuizQuestion() {Question = "What is the capital of France", Answer = "Paris"},
                new QuizQuestion() {Question = "What is the capital of Spain", Answer ="Madrid"},
                        ...
                new QuizQuestion() {Question = "What is the captial of Russia", Answer ="Moscow"},
                new QuizQuestion() {Question = "What is the capital of Ukraine", Answer ="Kiev"},
            };

            var questions = QAndQ.ToList();
            for (int i = 0; i < NUM_QUESTIONS; i++)
            {
                int num = _r.Next(questions.Length / 2);
                Question(questions[num].Question, questions[num].Answer);
                questions.Remove(questions[num]);
            }
        }
maybe better (without shouffling, without repeatable questions):       



class QuizQuestion
{
public string Question {get; set;}
public string Answer {get; set;}
}

static Random _r = new Random();        
        static int Quiz()
        {
            QuizQuestion[] QAndA = new QuizQuestion[] {
                new QuizQuestion() {Question = "What is the capital of France", Answer = "Paris"},
                new QuizQuestion() {Question = "What is the capital of Spain", Answer ="Madrid"},
                        ...
                new QuizQuestion() {Question = "What is the captial of Russia", Answer ="Moscow"},
                new QuizQuestion() {Question = "What is the capital of Ukraine", Answer ="Kiev"},
            };

            var questions = QAndQ.ToList();
            for (int i = 0; i < NUM_QUESTIONS; i++)
            {
                int num = _r.Next(questions.Length / 2);
                Question(questions[num].Question, questions[num].Answer);
                questions.Remove(questions[num]);
            }
        }
一枫情书 2024-12-17 00:41:56

实际上,您正在重新排序一个维数数组,因为您不应该打乱答案;)最简单的算法可能是:

   foreach array index
      switch with random index in array

actually you're reordeing one dimential array, because you shouldn't shufftle answers ;) simplest algorithm may be:

   foreach array index
      switch with random index in array
本王不退位尔等都是臣 2024-12-17 00:41:56

一种不需要您重新排列数组并且只需选择几个问题的方法会更快,即将您选择的问题存储在一个集合中。

继续生成随机数并将该索引处的问题添加到集合中,一旦集合的大小正确就将其返回。

您的循环将类似于:

var questions = new HashSet<Question>();
while (questions.Count < numberOfQuestionsRequired)
{
  questions.Add(questionArray[_r.Next()])
}

HashSet<>.CountHashSet<>.Add() 都是 O(1),因此限制因素将是多少随机数发生碰撞。

A method that doesn't require you to reshuffle the array and which will be quicker if you only need to pick a few questions is to store your selected questions in a set.

Keep generating random numbers and adding the question at that index to the set, once the set is of the correct size return it.

Your loop will look something like:

var questions = new HashSet<Question>();
while (questions.Count < numberOfQuestionsRequired)
{
  questions.Add(questionArray[_r.Next()])
}

HashSet<>.Count and HashSet<>.Add() are both O(1) so the limiting factor will be how many random numbers collide.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文