C# 是否从Random.Range()中排除值?

C# 是否从Random.Range()中排除值?,c#,random,unity3d,C#,Random,Unity3d,如果使用Random.Range()生成值,是否有任何方法排除该范围内的某些值(例如:选择1到20之间的数字,而不是6到8之间的数字)?最好的方法是使用您最喜欢的生成器生成1到17之间的整数n,然后使用 if (n > 5){ n += 3; } 如果采样值介于1和20之间,则丢弃值可能会引入统计异常。(例如,如果您的随机数生成器是线性同余生成器,则您的方差将太大:请尝试并查看。)是的,您只需在LINQ中使用的where语句 var list = Enumerable.Ra

如果使用
Random.Range()
生成值,是否有任何方法排除该范围内的某些值(例如:选择1到20之间的数字,而不是6到8之间的数字)?

最好的方法是使用您最喜欢的生成器生成1到17之间的整数
n
,然后使用

if (n > 5){
    n += 3;
}

如果采样值介于1和20之间,则丢弃值可能会引入统计异常。(例如,如果您的随机数生成器是线性同余生成器,则您的方差将太大:请尝试并查看。)

是的,您只需在LINQ中使用
的where
语句

   var list = Enumerable.Range(1, 20).Where(a => a < 6 || a > 8).ToArray();

所以你实际上想要17个不同的值

  [1..5] U [9..20]
您可以实现如下内容:

  // Simplest, not thread-safe
  private static Random random = new Random();

  ...  

  int r = (r = random.Next(1, 17)) > 5
    ? r + 3
    : r;
在一般(复杂)的情况下,我建议生成一个包含所有可能值的数组,然后 其中的项目:

  int[] values = Enumerable
    .Range(1, 100) // [1..100], but
    .Where(item => item % 2 == 1) // Odd values only
    .Where(item => !(item >= 5 && item <= 15)) // with [5..15] range excluded
    //TODO: Add as many conditions via .Where(item => ...) as you want
    .ToArray();

  ...

  int r = values[random.Next(values.Length)];
int[]值=可枚举
.范围(1100)/[1..100],但是
。其中(项=>项%2==1)//仅限奇数值
。其中(项目=>!(项目>=5和项目…)如您所需
.ToArray();
...
int r=值[random.Next(values.Length)];

如果r在6-8(含6-8)范围内,这将选择一个不同的随机数

int r = 0;
do
{
    r = Random.Next(20);
} while (r >= 6 && r <= 8)
intr=0;
做
{
r=随机。下一个(20);

}虽然(r>=6&&r我将在这个问题上投入我的2美分。这里是一个完整的类,展示了一个生成随机数的方法,不包括您选择的数字以及如何使用它

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

public class test2 : MonoBehaviour {

    System.Random rand;
    int[] excludelist;
    void Start()
    {
         rand = new System.Random();
        excludelist = new int[] { 5,9,3};
        for(int i = 0; i<20;i++)
        {
            Debug.Log(MakeMeNumber(excludelist));
        }

    }
    private int MakeMeNumber(params int[] excludeList)
    {
        var excluding = new HashSet<int>(excludeList);
        var range = Enumerable.Range(1, 20).Where(i => !excluding.Contains(i));


        int index = rand.Next(0, 20 - excluding.Count);
        return range.ElementAt(index);
    }
}
使用UnityEngine;
使用System.Collections.Generic;
使用System.Linq;
公共类测试2:单一行为{
随机随机随机数;
int[]排除列表;
void Start()
{
rand=新系统。随机();
excludelist=newint[]{5,9,3};
对于(int i=0;i!排除.Contains(i));
int index=rand.Next(0,20-不包括.Count);
返回范围.ElementAt(索引);
}
}

另一种方法是创建一个有效返回值数组,然后随机选择一个:

void Main()
{
    var rng = new Random();
    var validValues = Enumerable.Range(1, 20).Except(new int[] {6, 7, 8}).ToArray();

    for (int i = 0; i < 25; i++)
    {
        Console.Write(validValues[rng.Next(0, validValues.Length)]);
        Console.Write(" ");
    }
}
void Main()
{
var rng=新随机数();
var validValues=Enumerable.Range(1,20).Exception(新的int[]{6,7,8}).ToArray();
对于(int i=0;i<25;i++)
{
Console.Write(validValues[rng.Next(0,validValues.Length)];
控制台。写(“”);
}
}

编辑:哎呀!刚刚注意到这是针对Unity3D的,所以这个例子可能不合适。不过,它使用标准的
Random
类工作。

我创建了一个专门为这种情况设计的资产(它是付费的)

它只包含一些有用的函数,这些函数根据给定的间隔(例如,X和Y之间不包括Z)生成一个随机数

第三个函数RandomExclude.RandomInt(int,int,Vector2)将涵盖您的示例(介于1到20之间,但不包括6到8)。第一个int是可能的最低值,第二个int是最高值,Vector2是我们排除的间隔。在您的示例中,它如下所示:

intouroutcome=RandomExclude.RandomInt(1,20,新向量2(6,8))

该资源包含几个类似的函数,它们允许您生成一个不包括一个数字、不包括几个数字或不包括几个间隔的整数

资产本身已经包含了所有详细的实现说明,所以不用担心


请随意尝试!

您可以编写自己的方法来检查生成的数字是否属于排除范围,并在本例中重新生成它。我添加了随机标签,以向该网站上的许多随机数字专家介绍这个问题,并为我的答案提供一些可信度。这是为游戏引擎设计的。如果您可以避免linq,请避免它。这是很重要的查找内存,有些函数在iOS中不起作用。@程序员也避免使用lambda表达式?我不会这么说。我的意思是,如果他大部分时间都调用该代码,他应该避免使用它。@Programmer LINQ在iOS上工作得很好,如果你使用列表而不是数组。它是抽象循环和列表的复杂性的一个很好的资产。我想原因是什么它只适用于iOS上的列表,因为LINQ不使用
IEnumerable
(这在iOS上有问题)在列表上,而在数组上,它可以。很有趣。@MyIsaak是的,它与列表一起工作。它不工作是因为iOS上没有AOT功能。虽然我只在必要时使用它的几个linq函数。但是,他的答案中的第一个代码仍然会分配内存,只是为了生成随机数……不值得牺牲。加上一个,这是st统计上是正确的;我相信在条件测试中对赋值左边定义的变量的赋值在C#中定义得很好!Unity3D提供了一个随机类,大多数用户都依赖该类。此外,出于内部原因,Unity不推荐使用Linq(iOS上的FullAOT)这使得它的一些功能并不总是起作用。我认为使用这种方法是有机会的(虽然可能性很小,但仍然存在)程序进入无限循环…如果你总是得到一个介于6和8之间的数字。我想对这一个进行评论。这是一个冻结游戏的好方法。@Ignacio你是对的。这以前在我身上发生过。在Unity中生成随机数时没有while循环。@Programmer,不仅仅在Unity中,它可以冻结任何数据program@Ignacio好要知道这一点。呃,它真的不能冻结一个程序。计算机依赖于能够生成随机数并在任何地方使用随机过程——互联网及其协议依赖于这一点——数据包有可能会丢失并永远不会到达,但从统计上看,这永远不会发生。如果你在计算机上运行这个程序,因为到现在为止,宇宙的开始不会被卡住——很容易证明,在一个统一的概率(或任何概率,如果一个数字不在6到8之间出现的概率为非零)下,它可能不会被卡住超过一秒钟。你能解释一下(或链接到解释)如果你取样并丢弃,为什么差异会太大?(贝卡)
using UnityEngine;
using System.Collections.Generic;
using System.Linq;

public class test2 : MonoBehaviour {

    System.Random rand;
    int[] excludelist;
    void Start()
    {
         rand = new System.Random();
        excludelist = new int[] { 5,9,3};
        for(int i = 0; i<20;i++)
        {
            Debug.Log(MakeMeNumber(excludelist));
        }

    }
    private int MakeMeNumber(params int[] excludeList)
    {
        var excluding = new HashSet<int>(excludeList);
        var range = Enumerable.Range(1, 20).Where(i => !excluding.Contains(i));


        int index = rand.Next(0, 20 - excluding.Count);
        return range.ElementAt(index);
    }
}
void Main()
{
    var rng = new Random();
    var validValues = Enumerable.Range(1, 20).Except(new int[] {6, 7, 8}).ToArray();

    for (int i = 0; i < 25; i++)
    {
        Console.Write(validValues[rng.Next(0, validValues.Length)]);
        Console.Write(" ");
    }
}