从Random.Range()中排除值?

时间:2016-06-17 10:10:40

标签: c# random unity3d

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

7 个答案:

答案 0 :(得分:12)

执行此操作的最佳方法是使用您喜欢的生成器生成1到17之间的整数n,然后使用

进行转换
if (n > 5){
    n += 3;
}

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

答案 1 :(得分:10)

所以你实际上想要17(20 - 3)个不同的值

  [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)];

答案 2 :(得分:5)

是的,您可以在LINQ中简单地使用where语句

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

其他方式没有LINQ

        public IEnumerable RangeBetween()
        {
            foreach (var i in Enumerable.Range(1, 20))
            {
                if (i < 6 || i > 8)
                {
                    yield return i;
                }
            }
        }
编辑:现在我看到的不是一个严格的C#问题。它会影响UnityRandom。但是对于完整的答案我觉得你使用Enumerable.Range上面的代码然后使用它来生成数字:

list[Random.Next(list.Length)];

答案 3 :(得分:1)

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

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(" ");
    }
}
编辑:哎呀!刚刚注意到这是针对Unity3D的,所以这个例子可能不合适。但它可以使用标准Random类。

答案 4 :(得分:0)

如果r在6-8的范围内,则会选择不同的随机数。

int r = 0;
do
{
    r = Random.Next(20);
} while (r >= 6 && r <= 8)

答案 5 :(得分:-1)

我将在这个问题上投入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);
    }
}

答案 6 :(得分:-2)

我已经创建了专门针对该案例设计的资产(已付款)。

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

您的示例(介于1到20之间,但不包括6到8)将由第三个函数RandomExclude.RandomInt(int,int,Vector2)覆盖。第一个int是可能的最低值,第二个int是最高的值,Vector2是我们排除的间隔。在您的情况下,看起来像这样:

int ourOutcome = RandomExclude.RandomInt(1,20,新的Vector2(6,8));

资产包含更多类似的功能,它们使您可以生成一个排除一个数字,一个排除几个数字或排除几个间隔的整数。

所有详细的实施说明已包含在资产本身中,所以请不要担心。

https://assetstore.unity.com/packages/tools/input-management/random-exclude-133786

随时尝试!