2009-09-29 12 views
5

Ok, así que tengo una aplicación tiro de dados ...El código C# solo da los resultados esperados en el paso a paso?

Cuando me paso a través del código funciona normalmente y 'resultados' contiene el número correcto de los resultados de tiro y que parecen ser al azar, cuando deje el código de ejecuta y haz exactamente lo mismo que produce un conjunto de números idénticos.

Estoy seguro de que este es un error lógico que no puedo ver, pero tocarlo durante horas no mejoró la situación, por lo que cualquier ayuda es muy útil. :)

class Dice 
{ 

    public int[] Roll(int _throws, int _sides, int _count) 
    { 
     Random rnd = new Random(); 
     int[] results = new int[_throws]; 
     // for each set of dice to throw pass data to calculate method 
     for (int i = 0; i < _throws; i++) 
     { 
      int thisThrow = Calculate(_sides, _count); 
      //add each throw to a new index of array... repeat for every throw 
      results[i] = thisThrow; 
     } 

     return results; 
    } 


    private int Calculate(int _sides, int _count) 
    { 
     Random rnd = new Random(); 
     int[] result = new int[_count]; 
     int total = 0; 
     //for each dice to throw put data into result 
     for (int i = 0; i < _count; i++) 
     { 
      result[i] = rnd.Next(1, _sides); 
     } 
     //count the values in result 
     for (int x = 0; x < _count; x++) 
     { 
      total = total + result[x]; 
     } 
     //return total of all dice to Roll method 
     return total; 
    } 
} 

Respuesta

12

Primer error: Nunca use varias instancias de Random, utilizar un único ejemplo, y pasar que, junto con los otros parámetros.

+0

gracias modificando ahora :) – Yoda

+0

maldita extracción rápida! –

+1

@Ian: he visto esto suceder demasiadas veces para no detectarlo de inmediato :) – leppie

-1

Proporcione al constructor Random a seed. Ese es el problema.

http://msdn.microsoft.com/en-us/library/aa329890%28VS.71%29.aspx

Random r = new Random(DateTime.Now.Millisecond); 
+2

El uso de Millisecond como semilla es incluso peor que el valor predeterminado de Ticks. La semilla de tic-tac está bien en la mayoría de los casos, tal como han dicho los demás, no recree la clase Random y, por lo tanto, vuelva a sembrarla con el mismo valor. –

+0

Ah. Estoy tan acostumbrado a las funciones rand de estilo C. –

5

Cuando crea "Random rnd = new Random();" está sembrado por el tiempo actual. Cuando depure su código (lo cual toma tiempo) se sembrará de manera diferente cada vez.

Cree 1 instancia de Aleatorio, y haga referencia a eso en todas partes.

1

Está creando una clase aleatoria cada vez que necesita crear un número. Hacer esto le dará los resultados de nuez.

Ver aquí: FROM MSDN

Este problema se puede evitar mediante la creación de un único objeto aleatorio en lugar de múltiples.

Para mejorar el rendimiento, cree un objeto aleatorio para generar muchos números aleatorios a lo largo del tiempo, en lugar de crear repetidamente un nuevo objeto aleatorio para generar un número aleatorio.

E.g. crear una instancia privada de azar ...

1

Además de lo que se ha mencionado antes ...

uso aleatorio para cosas como los dados, juegos de cartas, la elección de imágenes al azar y así sucesivamente. Si alguna vez necesita crear un número aleatorio por seguridad, use System.Security.Cryptography.RandomNumberGenerator. Este sencillo ejemplo muestra la creación de un entero aleatorio.

 RandomNumberGenerator gen = RandomNumberGenerator.Create(); 
     byte[] myBytes = new byte[4]; 
     gen.GetBytes(myBytes); 
     int myValue = (BitConverter.ToInt32(myBytes, 0)); 

NO lo use a menos que tenga una necesidad de seguridad. El rendimiento es menor que el de la clase Aleatoria. Supongo que podrías usar esto para sembrar al azar, pero eso podría ser excesivo.

EDITAR: Se me ocurrió que nunca había probado esto. Una prueba de rendimiento rápido mostró lo siguiente:

1,000,000 números aleatorios: RandomNumberGenerator: 2.6 seconds Aleatorio: .015 segundos.

So Random es aproximadamente 150 veces más rápido.

+2

Dos cosas. Primero, usar un número aleatorio para sembrar un generador de números pseudoaleatorio en realidad no te da más aleatoriedad; la salida del pseudo-RNG es aún predecible. –

+1

En segundo lugar, el rendimiento del RNG de criptoresistencia está controlado no solo por las matemáticas que tiene que hacer, sino también por la capacidad de la máquina para proporcionar * entropy * para que funcione el RNG. Los RNG no inventan la entropía de la nada, ¿sabes? Esa entropía tiene que provenir de algún lugar, y la entropía es un recurso tan limitado como, por ejemplo, el ancho de banda, la memoria o el tiempo del procesador. Solo obtienes tanta entropía por segundo; un intento de usar grandes cantidades de entropía, por supuesto, se bloqueará hasta que haya más entropía disponible, al igual que un intento de usar bloques de ancho de banda de procesador o red. –

Cuestiones relacionadas