it-roy-ru.com

Исключить значения из Random.Range ()?

Если вы используете Random.Range() для генерации значений, есть ли способ исключить некоторые значения из диапазона (например: выбрать число от 1 до 20, но не от 6 до 8)?

17
Dinovr

Лучший способ сделать это - использовать ваш любимый генератор, чтобы сгенерировать целое число n от 1 до 17, а затем преобразовать, используя

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

Если вы выбираете от 1 до 20, а затем отбрасываете значения, вы можете ввести статистические аномалии. (Например, ваша дисперсия будет слишком высокой, если ваш генератор случайных чисел является линейным конгруэнтным: попробуйте и посмотрите.)

12
Bathsheba

Таким образом, вы на самом деле хотите 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)];
10
Dmitry Bychenko

Да, вы просто используете where оценку в LINQ

   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 #. Это влияет на Unity и Random. Но для полного ответа я рекомендую использовать код выше с Enumerable.Range, а затем использовать его для генерации числа:

list[Random.Next(list.Length)];
5
blogprogramisty.net

Другой способ - создать массив допустимых возвращаемых значений, а затем случайным образом выбрать одно:

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.

1
Chris Dunaway

Это выберет другое случайное число, если r находится в диапазоне 6-8 включительно.

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