Número aleatorio no repetitivo

Para generar números aleatorios del 1 al 20, necesito seleccionar selectivo y no debe ser repetitivo.

Cómo hacer esto en C #

Tenga en cuenta que necesito hacer un bucle como este

Random rnd = new Random() rnd.Next(1,20) for(int i =0; i<=20;i++) { } 

Para todos los números de bucles debe ser 1 a 20

¿A qué te refieres exactamente por “no debería ser repetitivo”? Si te refieres a que no quieres obtener ningún duplicado, básicamente debes tomar una lista de los números del 1 al 20, mezclarlos y luego agarrar uno a la vez del encabezado de la lista. Para una forma eficiente de mezclar una lista, consulte esta respuesta de desbordamiento de stack .

Si solo quiere decir que su bash actual da 5, 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 etc., entonces es probable estás creando una nueva instancia de Random cada vez que seleccionas un número: no hagas eso. Cada vez que creas una instancia, usará la hora actual como la “semilla” para el generador de números aleatorios (a menos que especifiques uno explícitamente). Eso significa que si crea varias instancias en sucesión rápida, cada una obtendrá la misma semilla y, por lo tanto, dará la misma secuencia de números.

En su lugar, use una sola instancia de Random y vuelva a utilizarla. (Tenga en cuenta que no es seguro para subprocesos, lo cual es un problema.) Por ejemplo:

 private static readonly Random Rng = new Random(); public int NextNumber() { return Rng.Next(20) + 1; } 

Eso no será seguro para subprocesos, pero háganos saber si eso es un problema. Una alternativa es a veces pasar al Random en el método (que normalmente sería más complicado, por supuesto):

 public int NextNumber(Random rng) { return rng.Next(20) + 1; } 

entonces el que llama puede reutilizar la instancia de manera apropiada.

Si desea una forma de generación de números aleatorios segura para subprocesos, es posible que desee ver mi clase StaticRandom en MiscUtil .

(Tenga en cuenta que el uso de rng.Next(1, 21) también funcionaría bien: prefiero la versión anterior, ya que creo que reduce las conjeturas sobre los límites inclusivos / exclusivos, pero es una cuestión de gusto personal).

Este método generará todos los números y no se repetirán los números:

 ///  /// Returns all numbers, between min and max inclusive, once in a random sequence. ///  IEnumerable UniqueRandom(int minInclusive, int maxInclusive) { List candidates = new List(); for (int i = minInclusive; i <= maxInclusive; i++) { candidates.Add(i); } Random rnd = new Random(); while (candidates.Count > 0) { int index = rnd.Next(candidates.Count); yield return candidates[index]; candidates.RemoveAt(index); } } 

Puedes usarlo así:

 Console.WriteLine("All numbers between 0 and 20 in random order:"); foreach (int i in UniqueRandom(0, 20)) { Console.WriteLine(i); } 

Una implementación de IEnumerable , basada en la respuesta de Hallgrim :

 public class UniqueRandoms : IEnumerable { Random _rand = new Random(); List _candidates; public UniqueRandoms(int maxInclusive) : this(1, maxInclusive) { } public UniqueRandoms(int minInclusive, int maxInclusive) { _candidates = Enumerable.Range(minInclusive, maxInclusive - minInclusive + 1).ToList(); } public IEnumerator GetEnumerator() { while (_candidates.Count > 0) { int index = _rand.Next(_candidates.Count); yield return _candidates[index]; _candidates.RemoveAt(index); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

Hice uno así por un tiempo. No sé cómo se compara con los otros métodos presentados en cuanto a eficiencia, aleatoriedad, etc. Pero parece funcionar:

 List integers = new List() { 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12 }; Random rnd = new Random(); var ints = from i in integers orderby rnd.Next(integers.Count) select i; 

Desde MSDN

“Una forma de mejorar la aleatoriedad es hacer que el valor de la semilla dependa del tiempo”.

Otro hecho

deberías “crear un Aleatorio para generar muchos números aleatorios a lo largo del tiempo”. Esto mejorará la generación aleatoria

 class Program { static void Main(string[] args) { List list = new List(); int val; Random r; int IntialCount = 1; int count = 7 ; int maxRandomValue = 8; while (IntialCount <= count) { r = new Random(); val = r.Next(maxRandomValue); if (!list.Contains(val)) { list.Add(val); IntialCount++; } } } } 

La siguiente manera es muy buena, uso una cadena aquí, puedes cambiar el tipo de la lista a lo que quieras … pruébalo:

  List NamesList = new List() { "Name1", "Name2", "Name3", "Name4", "Name5" }; Random rnd = new Random(); //Now to get random of the above "Without Repeating.." for (int i = 0; i <= NamesList.Count - 1; i++) { int TheSelectedRand = rnd.Next(NamesList.Count); string MyRandNumber = NamesList[TheSelectedRand]; //Print or use your item here NamesList.Remove(NamesList[TheSelectedRand]); } 

el código de golpe genera 65 números aleatorios únicos entre 0 – 92 y devuelve esos números aleatorios únicos en una matriz.

 public static int[] RandomNumbers_Supplier() { Random R = new Random(); int[] RandomNumbers = new int[65]; int k = 0, Temp; bool IsRepetitive = false; while (k < 65) { Temp = R.Next(0, 92); for (int i = 0; i < 65; i++) { IsRepetitive = false; if (RandomNumbers[i] == Temp) { IsRepetitive = true; break; } } if (!IsRepetitive) { RandomNumbers[k] = Temp; k++; } } return(RandomNumbers) } 
 static void Main(string[] args) { //Randomize 15 numbers out of 25 - from 1 to 25 - in ascending order var randomNumbers = new List(); var randomGenerator = new Random(); int initialCount = 1; for (int i = 1; i <= 15; i++) { while (initialCount <= 15) { int num = randomGenerator.Next(1, 26); if (!randomNumbers.Contains(num)) { randomNumbers.Add(num); initialCount++; } } } randomNumbers.Sort(); randomNumbers.ForEach(x => Console.WriteLine(x)); }