【问题标题】:Fisher–Yates shuffle in C#C# 中的 Fisher-Yates 洗牌
【发布时间】:2019-05-30 12:49:03
【问题描述】:

我有这个方法Shuffle,它假设返回一组随机数,这些随机数在上述方法中显示,但数字需要以混合格式显示。 第一种方法效果很好,因为数字在范围集中正确显示,但是这种方法 Shuffle 没有以混合格式返回它们。

例子:

第一个方法返回:1, 2, 3, 4, 5

这个方法需要返回2, 1, 4, 5, 3

    public int[] Shuffle(int[] Sequence)
    {
        int[] Array = new int[Sequence.Length];

        for(int s=0; s < Array.Length-1; s++){
           int GenObj = GenerateAnotherNum (0, Array.Length + 1);

            Array[s] = Sequence[GenObj];
            Sequence[GenObj] = Array[s];
        }
        return Sequence;
    }

【问题讨论】:

  • 不清楚你在问什么。这段代码是什么?这是第一种还是第二种方法?那么另一种方法是什么?如果应该随机打乱,为什么你希望你的方法返回一个特定的序列?
  • 你应该小心命名你的变量。标准方法是使用初始小写(camelCase)命名局部变量和参数。这将有助于避免与关键字发生冲突,例如 Array...
  • 这段代码是Fisher-Yates shuffle方法。我只是举了一个序列应该返回什么的例子。 @ArthurAttout
  • 交换程序不正确,应该是int h = Array[s]; Array[s] = Sequence[GenObj]; Sequence[GenObj] = h;
  • Array[s] = Sequence[GenObj]; Sequence[GenObj] = Array[s]; 没有做任何事情。您需要交换值。

标签: c#


【解决方案1】:

这里有几个问题:全零数组、范围和交换过程

算法:

https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

代码:

// probably "static" should be added (depends on GenerateAnotherNum routine)
public int[] Shuffle(int[] Sequence)
{
    // public method's arguments validation
    if (null == Sequence)
        throw new ArgumentNullException(nameof(Sequence));

    // No need in Array if you want to modify Sequence

    for(int s = 0; s < Sequence.Length - 1; s++)
    {
        int GenObj = GenerateAnotherNum(s, Sequence.Length); // pleace, note the range

        // swap procedure: note, var h to store initial Sequence[s] value
        var h = Sequence[s];          
        Sequence[s] = Sequence[GenObj];
        Sequence[GenObj] = h;
    }

    return Sequence;
}

演示:

// Random(0) - we want to reproduce the results in the demo
private static Random random = new Random(0); 

// Let unknown GenerateAnotherNum be a random
private static int GenerateAnotherNum(int from, int to) => random.Next(from, to);

...

int[] array = new int[] { 1, 2, 3, 4, 5 };

string result = string.Join(", ", Shuffle(array));

Console.Write(result);

结果:

4, 5, 2, 3, 1

【讨论】:

  • 获取随机数的参数也可以在0-s的范围内
  • 很好的答案,虽然我已经用另一个给定的答案解决了这个问题,但这是一个很好的例子!
【解决方案2】:
public static class Shuffler<T>
{
    private static Random r = new Random();
   
    public static T[] Shuffle(T[] items)
    {      
        for(int i = 0; i < items.Length - 1; i++)
        {
            int pos = r.Next(i, items.Length); 
            T temp = items[i];          
            items[i] = items[pos];
            items[pos] = temp;
        }
        return items;
    }

    public static IList<T> Shuffle(IList<T> items)
    {      
        for(int i = 0; i < items.Count - 1; i++)
        {
            int pos = r.Next(i, items.Count); 
            T temp = items[i];          
            items[i] = items[pos];
            items[pos] = temp;
        }
        return items;
    }
}

【讨论】:

  • 我知道这是旧的,但我希望它作为另一个答案的参考。
猜你喜欢
  • 2017-07-08
  • 2013-10-26
  • 2023-03-27
  • 1970-01-01
  • 2021-09-04
  • 2011-01-28
  • 1970-01-01
  • 2019-03-06
  • 1970-01-01
相关资源
最近更新 更多