2009-06-18 20 views
6

Para generar números aleatorios del 1 al 20, necesito seleccionar selectivamente y no debe ser repetitivo.Número aleatorio no repetitivo

Cómo hacer esto en C#

Nota tengo que recorrer como como esto

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

} 

Para todos el número de bucles debe ser de 1 a 20

+0

¿podría por favor seleccione la respuesta correcta para esta pregunta? –

Respuesta

21

¿Qué es exactamente lo que quiere decir con "no debería ser repetitivo"? Si quiere decir que no desea obtener ninguno de los duplicados, entonces básicamente debe tomar una lista de los números 1-20, mezclarlos y luego agarrar uno a la vez del encabezado de la lista. Para una manera eficiente de mezclar una lista, vea this Stack Overflow answer.

Si solo quiere decir que su intento actual da 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2 etc., entonces es probable que esté creando una nueva instancia de Random cada vez que elija un número: no lo haga. 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 sin embargo, que es un dolor.) Por ejemplo:

private static readonly Random Rng = new Random(); 

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

que no va a ser flujos seguros, pero háganos saber si eso es un problema. Una alternativa es a veces para pasar el 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 la persona que llama puede reutilizar la instancia apropiada.

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

(Tenga en cuenta que el uso de rng.Next(1, 21) también funcionaría bien - Sucede que prefieren la versión anterior ya que creo que reduce las conjeturas acerca de los límites inclusivas/exclusivas, pero es una cuestión de gusto personal.)

+0

Esto se debe a que el RNG se siembra en función del tiempo de forma predeterminada, y los bucles son demasiado rápidos para el nivel de precisión que utiliza. –

+0

Sí. He editado la respuesta para dar más detalles. –

+0

¿Qué significa "no seguro para subprocesos"? ¿Obtendré el mismo valor aleatorio en diferentes hilos? – Nick

0

De MSDN

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

Otro hecho

debe "crear uno aleatorio para generar tantos números aleatorios en el tiempo." Esto aumentará la generación aleatoria

17

Este método va a generar todos los números, y ningún número se repite:

/// <summary> 
/// Returns all numbers, between min and max inclusive, once in a random sequence. 
/// </summary> 
IEnumerable<int> UniqueRandom(int minInclusive, int maxInclusive) 
{ 
    List<int> candidates = new List<int>(); 
    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); 
    } 
} 

Usted puede utilizar de esta manera:

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

Implementa exactamente lo que pensé cuando leí el título. – VVS

1

hice una de esta manera un tiempo atrás. No sé cómo se compara con los otros métodos presentados en cuanto a eficiencia, aleatoriedad, etc.Pero parece que funciona:

List<int> integers = new List<int>() { 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; 
+0

Este método es mucho mejor que el resto. Gracias – Bijan

2

Un IEnumerable aplicación, basado en Hallgrim's respuesta:

public class UniqueRandoms : IEnumerable<int> 
{ 
    Random _rand = new Random(); 
    List<int> _candidates; 

    public UniqueRandoms(int maxInclusive) 
     : this(1, maxInclusive) 
    { } 

    public UniqueRandoms(int minInclusive, int maxInclusive) 
    { 
     _candidates = 
      Enumerable.Range(minInclusive, maxInclusive - minInclusive + 1).ToList(); 
    } 

    public IEnumerator<int> 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(); 
    } 
} 
0
class Program 
{ 
    static void Main(string[] args) 
    {   
     List<int> list = new List<int>(); 
     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++; 
      } 

     } 
    } 
} 
0

la siguiente manera está muy buena manera, yo uso una cadena aquí, se puede cambiar el tipo de la lista a lo que desee ..., pruébelo:

  List<string> NamesList = new List<string>() { "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]); 
      } 
-1

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) 
     } 
-1
static void Main(string[] args) 
{ 
    //Randomize 15 numbers out of 25 - from 1 to 25 - in ascending order 
    var randomNumbers = new List<int>(); 
    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)); 
}