Estás en una mazmorra. Antes que tú, hay un grupo de Nerds de nivel 5. Quieren que ejecutes una campaña de Dungeons and Dragons para ellos.Mejorar la calidad de aleatoriedad en Objective-C
Ejecutas algunas sesiones, tus jugadores están subiendo de nivel, y las cosas son generalmente increíbles. El combate es un poco lento, sin embargo. Decides sacar tu Halberd +4 de Objective-C y escribir una aplicación para iPad para automatizar el rodaje de los dados de NPC en combate. Los nerds se mueven hacia ti amenazadoramente. "Los números generados algorítmicamente", gruñe, "son una imitación hueca de la verdadera aleatoriedad. ¡No mancharás nuestra santa campaña con tu inmundicia pseudoaleatoria!"
Ruedas para convencerlo de que arc4random_uniform()
es más que suficiente ... y falla. Los nerds se conformarán con nada menos que la verdadera aleatoriedad. Te mantienen prisionero mientras te aferras desesperadamente a tu MacBook y escribes una clase que recupera datos de random.org.
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"YYYY/YYYY-MM-dd"];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@%@",
@"http://www.random.org/files/",
[formatter stringFromDate:[NSDate date]],
@".bin"]];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:url] delegate:self];
Una vez que los datos se han guardado, permiten la generación de números aleatorios, 0-255, a partir de los bytes descargados.
-(int) nextInt:(int)start end:(int)end
{
int upperBound = end - start + 1;
unsigned char result;
int maxModulo = 255 - (255 % upperBound);
do {
NSRange range = {index, sizeof(char)};
[randos getBytes:&result range:range];
index += sizeof(char);
} while (result > maxModulo); //avoid modulo bias
result = result % upperBound;
result += start;
return result;
}
Los nerds parecen satisfechos, pero aparece un nuevo enemigo: ¡otro Dungeon Master! Él exige que le des una copia del software para sus propios fines. El problema es evidente: si ambos usan datos de random.org del mismo día, obtendrán el mismo conjunto de dados.
Así que mi pregunta es la siguiente: ¿cómo puedo modificar los datos de random.org de modo que conserven algo así como "verdadera aleatoriedad" pero sean diferentes en cada instancia del programa? Puedo imaginar una solución que implicaría obtener algunos movimientos del touchpad (supuestamente aleatorios) por parte del usuario, like TrueCrypt does, pero una vez que tengo esa constante, no estoy seguro de a dónde ir desde allí. De alguna manera hash todos los números usando mi constante? Eso producirá un número mucho mayor; ¿Estoy estadísticamente bien si trunco o modulo eso hasta la tirada de dados? No sé qué pasos algorítmicos tomar.
¡Hah! Eso servirá. Obtenemos criptografía y tenemos la sensación de tener el control de la salida. Las otras respuestas hacen evidente que mis jugadores realmente no entienden cómo se generan números aleatorios, pero ¿por qué enseñarlos cuando puedo simplemente hacerlos felices? – iameli
Mejor aún, haga que los usuarios hagan todo eso y utilicen un generador de números "aleatorio" mejor, como arc4random o SecRandomCopyBytes. El sistema tiene mejores y más fuentes de entropía. Por lo tanto, pensar que una solución "de cosecha propia" puede ser mejor que un sistema bien diseñado y diseñado profesionalmente, es una locura. – zaph
@CocoaFu: No creo que comprenda el propósito de esta aplicación. Tiene dos propósitos: 1) tener un mecanismo comprensible y tangible que se pueda explicar fácilmente, 2) producir números que sean lo suficientemente buenos para un juego de rol. Pensar que necesitas un PRNG aprobado y diseñado profesionalmente para jugar un juego de rol con algunos amigos en casa es una locura. (Como nota al margen, la mayoría de los jugadores de rol tienen dados con sesgos bastante impactantes.) Además, SHA-2 hace un excelente PRNG. –