Если вы используете Random.Range()
для генерации значений, есть ли способ исключить некоторые значения в пределах диапазона (например: выбрать число от 1 до 20, но не с 6 по 8)?
Исключить значения из Random.Range()?
Ответ 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
Не стесняйтесь попробовать!