【问题标题】:Create number for random and non repeat为随机和不重复创建数字
【发布时间】:2023-03-06 23:41:01
【问题描述】:

我是代码:

       Random rand = new Random();
       int[] arr = new int[4];
       for (int i = 0; i < 4; i++)
       {
           for (int k = 0; k < 4; k++)
           {
               int rad = rand.Next(1, 5);
               if (arr[k] != rad)
                   arr[i] = rad;
           }
       }
       for (int i = 0; i < 4; i++)
           MessageBox.Show(arr[i].ToString());

我想要从凌晨 1 点到 4 点的生产编号,并且彼此不相等。 tnx。

【问题讨论】:

标签: c# random numbers


【解决方案1】:

反过来想:

代替:

生成一个数字然后检查它是否不重复

你做到了:

你已经有一组不重复的数字,然后你拿走 一对一 - 消除重复的可能性。

这样就可以了:

List<int> list = Enumerable.Range(1, 4).ToList();
List<int> rndList = new List<int>();
Random rnd = new Random();
int no = 0;
for (int i = 0; i < 4; ++i) {
    no = rnd.Next(0, list.Count);
    rndList.Add(list[no]);
    list.Remove(list[no]);
}

结果在您的rndList 中。

这样就不会出现重复了。

【讨论】:

  • 运行代码后,rndList 包含 0, 0, 3, 0,这不是 OP 所要求的唯一,而且生成一个数字然后检查重复项的效率低于简单的 Fisher-Yates。
  • @IvanLeonenko 已更正。它应该是 list[no] 而不是 no。感谢您的通知。关于效率,我真的没有他们之间的简介。但正如你所说,Fisher Yates 算法可能比我的简单算法更快。我的看法只是我提供的算法非常简单明了。
【解决方案2】:

创建一个具有唯一元素的数组,然后对其进行洗牌,如下面的代码所示,它将以使用Fisher-Yates shuffle algorithm 的统一随机顺序洗牌:

int N = 20;
var theArray = new int[N];
for (int i = 0; i < N; i++)
    theArray[i] = i;

Shuffle(theArray);

public static void Shuffle(int[] a) {
    if (a == null) throw new ArgumentNullException("Array is null");
    int n = a.Length;
    var theRandom = new Random();
    for (int i = 0; i < n; i++) {
        int r = i + theRandom.Next(n-i);     // between i and n-1
        int temp = a[i];
        a[i] = a[r];
        a[r] = temp;
    }
}

可以在 in this post 找到算法的解释和模板版本,Jon Skeet 给出了很好的回答。

public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> source, Random rng)
{
    T[] elements = source.ToArray();
    // Note i > 0 to avoid final pointless iteration
    for (int i = elements.Length-1; i > 0; i--)
    {
        // Swap element "i" with a random earlier element it (or itself)
        int swapIndex = rng.Next(i + 1);
        T tmp = elements[i];
        elements[i] = elements[swapIndex];
        elements[swapIndex] = tmp;
    }
    // Lazily yield (avoiding aliasing issues etc)
    foreach (T element in elements)
    {
        yield return element;
    }
}

【讨论】:

    【解决方案3】:

    创建一个包含您想要的数字的列表,然后将它们随机排列:

    var rnd = new Random();
    List<int> rndList = Enumerable.Range(1, 4).OrderBy(r => rnd.Next()).ToList();
    

    如果你想要一个数组而不是一个列表:

    var rnd = new Random();
    int[] rndArray = Enumerable.Range(1, 4).OrderBy(r => rnd.Next()).ToArray();
    

    【讨论】:

    • 谢谢。我不想从列表中使用。我想做正确的数组。因为我有游戏权利
    • @user5566530 也更新了数组
    • 我知道这种方法可行,但我总是讨厌看到当存在 O(N) 算法时提出 O(N Log(N)) 算法。
    • 这个实现是 O(n log n),我给的一个是 O(n)。此外,此实现不会为您提供统一的随机顺序。请参阅此帖子中的说明stackoverflow.com/questions/1287567/…
    【解决方案4】:
    int[] arr = new int[5];
    int i = 0;
    while (i < 5)
    {
        Random rand = new Random();
        int a = rand.Next(1,6);
    
        bool alreadyexist = false;
        for (int j = 0; j < 5; j++)
        {
    
            if (a == arr[j])
            {
                alreadyexist = true;
            }
    
        }
        if (alreadyexist == false)
        {
            arr[i] = a;
            i++;
        }
    
    }
    for (int k = 0; k < 5; k++)
    {
    
        MessageBox.Show(arr[k].ToString());
    }
    

    【讨论】:

    • 您不应该在每次迭代中创建 Random,如果它发生得太频繁,它可能会给出相同的顺序和值。复杂性高于线性,尤其是当您过于频繁地创建 Random 对象时。此外,这个实现并没有给你统一的随机顺序,至少使用 Fisher-Yates。这个答案不应该被接受。
    • 谢谢。但是这个答案和我在项目中得到帮助的答案
    • 你为什么在@user5566530之后将此问题从已回答改为未回答
    猜你喜欢
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2014-05-09
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    相关资源
    最近更新 更多