web-dev-qa-db-fra.com

Exclure les valeurs de Random.Range ()?

Si vous utilisez Random.Range() pour générer des valeurs, existe-t-il un moyen d'exclure certaines valeurs de la plage (par exemple: choisissez un nombre compris entre 1 et 20, mais pas entre 6 et 8)?

17
Dinovr

La meilleure façon de faire est d’utiliser votre générateur préféré pour générer un entier n compris entre 1 et 17 puis le transformer en utilisant

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

Si vous échantillonnez entre 1 et 20, puis éliminez les valeurs, vous pouvez introduire des anomalies statistiques. (Par exemple, votre variance sera trop élevée si votre générateur de nombres aléatoires est un congruentiel linéaire: essayez-le et voyez.)

12
Bathsheba

Donc, vous voulez réellement 17 (20 - 3) valeurs différentes 

  [1..5] U [9..20]

et vous pouvez implémenter quelque chose comme ceci:

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

  ...  

  int r = (r = random.Next(1, 17)) > 5
    ? r + 3
    : r;

En général (et compliqué) cas, je suggère de générer un tableau de toutes les valeurs possibles et ensuite prendre L'élément de celui-ci:

  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

Oui, vous utilisez simplement where déclaration dans LINQ

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

Autre moyen sans LINQ

        public IEnumerable RangeBetween()
        {
            foreach (var i in Enumerable.Range(1, 20))
            {
                if (i < 6 || i > 8)
                {
                    yield return i;
                }
            }
        }

EDIT: Maintenant, je vois n’est pas une question C # stricte. Cela affecte Unity et Random. Mais pour une réponse complète, je vous propose que vous utilisez le code ci-dessus avec Enumerable.Range et que vous l'utiliserez ensuite pour générer le numéro:

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

Une autre méthode consiste à créer un tableau des valeurs de retour valides, puis à en sélectionner une au hasard:

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: Oups! Je viens de remarquer que c'était pour Unity3D, donc cet exemple pourrait ne pas être approprié. Cela fonctionne cependant avec la classe Random standard.

1
Chris Dunaway

Cela choisira un nombre aléatoire différent si r est compris entre 6 et 8 inclus.

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