Duda con juego que genera numeros aleatorios

Iniciado por Caster, 30 Septiembre 2012, 11:36 AM

0 Miembros y 1 Visitante están viendo este tema.

Caster

En el libro que estoy leyendo sobre C, venia un ejemplo de un programa de como utilizar funciones, aqui el programa:

la funcion main:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define SEMILLA 12345

void juego(void);
int tirada(void);

int main() {

char respuesta = 'S';

printf("Bienvenido al juego CRAPS\n\n");
printf("Para lanzar los dados, pulsa Intro\n\n");

srand(SEMILLA);

while (toupper(respuesta) != 'N') {
juego();
printf("\nDeseas jugar de nuevo? (S/N) ");
scanf(" %c", &respuesta);
printf("\n");

}
printf("Adios, que lo pases bien");
}


la funcion juego:

void juego(void) {

int puntos1;
int puntos2;
char nada;

printf("\nPor favor lanza los dados...");
scanf("%c", &nada);
printf("\n");
puntos1 = tirada();
printf("\n%2d", puntos1);

switch(puntos1) {

case 7:
case 11:

printf(" - Felicidades! Ganaste a la primera tirada\n");
break;

case 2:
case 3:
case 12:

printf(" - Lo siento! Perdiste en la primera tirada\n");
break;

case 4:
case 5:
case 6:
case 8:
case 9:
case 10:

do {

printf(" - Lanza los dados de nuevo...");
scanf("%c", &nada);
puntos2 = tirada();
printf("\n%2d", puntos2);
} while (puntos2 != puntos1 && puntos2 != 7);

if (puntos2 == puntos1)
printf(" - Ganas por igualar tu primera tirada\n");
else
printf(" - Pierdes por no igualar tu primera tirada");
break;
}
return;
}


la funcion tirada:

int tirada(void)  {

float x1;
float x2;
int n1;
int n2;

x1 = rand() / 32768.0;
x2 = rand() / 32768.0;

n1 = 1 + (int) (6 * x1);
n2 = 1 + (int) (6 * x2);

return(n1 + n2);
}


Entiendo todo perfectamente, pero donde me pierdo es en las funciones rand() y srand(), en la funcion tirada entiendo todas las operaciones que se hacen en ella para obtener los numeros, lo que no entiendo es para que se utiliza la funcion srand() y la constante SEMILLA, en el libro viene explicado pero no logro entenderlo, si alguien me lo puede explicar de alguna forma mas facil, gracias,


Saludos

do-while

#1
¡Buenas!

rand() te genera una sucesion de numeros pseudoaleatorios. Es decir, si la llamas sin haber llamado a srand() siempre te generara la misma secuencia de numeros.

srand() hace que esa secuencia empiece por otro numero de la sucesion. Por lo tanto, si a srand le pasas una constante, la secuencia de numeros que genera rand() sera distina (en principio) de la que genera sin haber llamado a srand, pero al haber inicializado srand la secuencia que generara rand a un valor constante (fijo), seguiran repitiendose los mismos valores en las mismas posiciones.

Para evitar que la sucesion de numeros aleatorios sea siempre la misma, puedes utilizar como semilla un valor mas o menos aleatorio, como por ejemplo el valor devuelto pot la funcion time (que se encuentra en time.h o ctime), con parametro NULL, que devuelve el numero de segundos que han pasado desde 1900 (o algun otro año, no lo se) hasta el momento en el que se ejecuta el programa. Asi, cada vez que ejecutes el programa este valor sera diferente, y por lo tanto la sucesion que generara rand() tambien sera distinta.

¡Saludos!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

leosansan

#2
Para que "veas" lo que dice do-while corre el siguiente código varias veces. Observa que la primera lista es siempre la misma -fíjate en srand en el código- mientras que las otras dos varían -fijate otra vez en el segundo srand- .
:
/*Numero aleatorios entre 0 y 50:
num=rand()%51;

Numero aleatorios entre 11 y 100:
num=11+rand()%(101);

Numero aleatorios entre 250 y 420:
num=250+rand()%(421-250);

De forma general es:
variable = limite_inferior + rand() % (limite_superior +1 - limite_inferior) ;*/

#include <stdio.h>
#include <time.h>
main()
{
   int i,x,n;
   srand();
   printf("15  numeros entre 1 y 10: \n\n");
   for (i = 0; i < 15; i++)
       {
           n = rand() % 10 ;
           printf("%d, ", n);

       } printf("\b\b \n\n");
   srand(time(0));
   printf("15  numeros entre 1 y 10: \n\n");
   for (i = 0; i < 15; i++)
       {
           n = rand() % 10 ;
           printf("%d, ", n);

       } printf("\b\b \n\n");
   printf("15  numeros entre 25 y 100: \n\n");
   for (i = 0; i < 15; i++)
       {
           n = 25+rand() % (101-25) ;
           printf("%d, ", n);

       } printf("\b\b \n");
}

Espero que te sea útil.
Saludos!.

Caster

#3
A ver, rand() genera una lista de numeros aleatorios, pero siempre son los mismos, hasta ahi creo que es asi, y entonces se llama a srand() para que empiece por otro numero y cambie la secuencia, pero si esto se repite volveriamos al problema del principio, a generar siempre la misma sucesion aun utilizando srand(), entonces para que esto no pase se le pasa una semilla que cambie cada cierto tiempo.

¿Lo he entendido bien?

Si estoy en lo cierto entonces, en mi programa como la semilla siempre es la misma, al final tambien terminarian repitiendose las suceciones, ¿es cierto?

Gracias por el codigo leosansan, me ha ayudado bastante

Saludos y muchas gracias.

EDITO: A la pregunta que hago sobre mi programa, estoy en lo cierto, en cada ejecucion se repiten las misma sucesiones. Creo que ya lo entiendo todo perfectamente.

EDITO 2: Me surge otra pregunta, utilizar srand() sin semilla y srand() pero con una semilla que no cambie, es realmente lo mismo no?

Muchas gracais

leosansan


rir3760

Cita de: Caster en 30 Septiembre 2012, 14:28 PMMe surge otra pregunta, utilizar srand() sin semilla y srand() pero con una semilla que no cambie, es realmente lo mismo no?
No.

La función "srand" requiere de un argumento, llamarla como indica leosansan (sin argumento) es un error.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

leosansan

Cita de: rir3760 en 30 Septiembre 2012, 16:07 PMLa función "srand" requiere de un argumento, llamarla como indica leosansan (sin argumento) es un error.
¿¿¿....???      cPor qué no pruebas a correr el código que expuse?.¿No será que "quieres decir otra cosa?, porque decir que no "funciona" cuando sí funciona es erróneo. Otra cosa es que quieras decir que no sirve para generar números aleatorios diferentes cada vez que le llames. Pero te recuerdo que la duda era otra, ésta en concreto:
Respuesta a:
CitarEDITO 2: Me surge otra pregunta, utilizar srand() sin semilla y srand() pero con una semilla que no cambie, es realmente lo mismo no?

SI, puedes ponerla sin semilla así "srand()" o con semilla, así  "srand(15)" y en ambos casos se genera el mismo juego de números aleatorios.
Un saludo

rir3760

Cita de: leosansan en 30 Septiembre 2012, 16:32 PMcPor qué no pruebas a correr el código que expuse?.
Porque eso es lo peor que se puede hacer en este escenario. C no es un lenguaje con "rueditas" y debido a sus reglas "tasajear" código para en base al resultado sacar conclusiones no es una buena idea. Lo explico mas adelante.


Cita de: leosansan en 30 Septiembre 2012, 16:32 PM¿No será que "quieres decir otra cosa?
No, estas leyendo de mas en mis mensajes.


Cita de: leosansan en 30 Septiembre 2012, 16:32 PMporque decir que no "funciona" cuando sí funciona es erróneo.
Cuando se trata del lenguaje C y sus estándares hay que ser muy cuidadoso con el lenguaje (con el otro, me refiero al español).

Yo no dije que en tu caso el programa no funcione correctamente, eso lo podemos dar por un hecho. Yo indique que es un error. Voy a explicar con mas detalle.


El estándar de C define el lenguaje y el comportamiento que tendrán los programas desarrollados con el pero, si se viola una de sus reglas, se genera "comportamiento no definido". Si revisamos uno de los últimos borradores (N1124) del estándar C99 tenemos:
Citar6.5.2.2  Function calls

[...]

2 If the expression that denotes the called function has a type that includes a prototype, the number of arguments shall agree with the number of parameters.

[...]

6  If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined.
En base a esa parte podemos concluir que, si se llama a la función "srand" sin argumentos cuando su prototipo (cortesía de <stdlib.h>) indica que se debe pasar uno, se genera comportamiento no definido.

¿Porque es un error? Porque, como su nombre sugiere, una vez se genere el comportamiento no definido (en nuestro caso con la llamada a "srand") ya no hay garantías sobre el comportamiento del programa.

Cualquier cosa puede pasar, por ejemplo el programa:
* Funciona correctamente.
* Genera resultados inesperados.
* Simplemente revienta.
* etc.

Y ese es el problema: el compilador se "lava las manos" y lo que sea que resulte del programa es responsabilidad de programador (por violar las reglas del lenguaje).


Otro ejemplo, por desgracia común, es el uso de "fflush(stdin)". El estándar define el comportamiento de la función pero solo para streams de salida. Si se trata de un stream de entrada (como es el caso de "stdin") y como el estándar no define el comportamiento en ese caso se genera ...


Cita de: leosansan en 30 Septiembre 2012, 16:32 PM
Pero te recuerdo que la duda era otra, ésta en concreto:
Respuesta a:
CitarEDITO 2: Me surge otra pregunta, utilizar srand() sin semilla y srand() pero con una semilla que no cambie, es realmente lo mismo no?
SI, puedes ponerla sin semilla así "srand()" o con semilla, así  "srand(15)" y en ambos casos se genera el mismo juego de números aleatorios.
Espero ahora se entienda mejor: utilizar "srand()" es un error ya que no se puede garantizar el comportamiento del programa a partir de ese punto.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

Caster

Ya esta, ya me quedo claro como se usa correctamente, muchas gracias a todos por responder. Haya paz.

Saludos.