Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Итак, вы действительно хотите 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)];

Ответ 3

Да, вы просто используете where statment в 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;
                }
            }
        }

EDIT: теперь я вижу, что это не строгий вопрос С#. Это влияет на Unity и Random. Но для полного ответа я sugest. Вы используете код выше с Enumerable.Range, а затем используйте его для генерации числа:

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

Ответ 4

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

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(" ");
    }
}

EDIT: Ой! Просто заметил, что это было для Unity3D, поэтому этот пример может оказаться неприемлемым. Он работает, используя стандартный класс Random.

Ответ 5

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

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

Ответ 6

Я собираюсь бросить свои 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);
    }
}

Ответ 7

Я создал ресурс, предназначенный именно для этого случая (он оплачен).

Он просто содержит несколько полезных функций, которые генерируют случайное число из заданных интервалов (например, между 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

Не стесняйтесь попробовать!