Problema con código generador de números aleatorios diferentes

Probablemente el error sea una tontería, pero no lo encuentro :confused:
Quiero generar 8 números aleatorios diferentes entre 0 y 7, pero por alguna razón el último número siempre es igual al penúltimo y queda faltando un número.
El código usa un valor del Timer1 como semilla de una rutina generadora de números pseudo-aleatorios. La secuencia depende del timer1 en el momento en que se suelta el pulsador.

Anotación: La función RAND()%n; genera números entre 0 y (n-1)
La función SRAND(n); usa n como semilla generadora de la secuencia, si n se repite, la secuencia se repite.

Agradezco su colaboración. Espero que sirva el código si alguien lo necesita.
Código:
//----------------------------------------------------------------------------------------

#INCLUDE "16F877A.H"
#USE DELAY(CLOCK=4M)
#INCLUDE "LCD.C"
#INCLUDE "STDLIB.H"

UNSIGNED INT16 I=100;
INT X,Y;
INT DATOS[8];
VOID MAIN()
{
SETUP_TIMER_1(RTCC_INTERNAL|RTCC_DIV_64);
LCD_INIT();

WHILE(TRUE)
{
IF(INPUT(PIN_A0)==0)
{WHILE(INPUT(PIN_A0)==0){} // antirebote
SRAND(GET_TIMER1());  // Se toma el valor del Timer1 como semilla de la función RAND

FOR(X=0;X<=8;++X)
{DATOS[X]=20;} //Se ponen valores diferentes a los buscados en el Vector datos

FOR(X=1;X<=8;++X)
{OTRO_NUM:
DATOS[X]=RAND()%8; //Datos[x]= numero entre 0 y 7

FOR(Y=1;Y<=X-1;++Y)
{IF(DATOS[X]==DATOS[Y])  // Si Datos[x] es igual a algún valor anterior, 
GOTO OTRO_NUM; //cambia su valor por otro número aleatorio
}}

LCD_PUTC("\f"); // Se borra la LCD
FOR(X=1;X<=8;++X)
{PRINTF(LCD_PUTC,"%U ",DATOS[X]);} // Se imprimen los valores del vector Datos
}}}
 
Última edición por un moderador:
Sin haberlo comprobado, puede ser que el problema es que tenes que escribir X++, Y++, etc., en vez de ++X??
 
Es imposible generar números realmente aleatorios en un ordenador, las funciones random solo generan cadenas mas o menos complejas pero son predecibles y siempre las mismas en igualdad de condiciones iniciales. Todos los MP3 que he tenido reproducen siempre los discos en la misma secuencia si están en random.
 
Chclau, probé el programa como me dijiste y funciona igual.

Scooter, la función random depende de la semilla, si la semilla es la misma, la secuencia siempre será la misma, tienes razón, pero en el caso de mi código la semilla depende de una variable aleatoria, el tiempo que demora el usuario en presionar el botón. Como semilla se usa el timer1, es un registro de 16 bits, eso significa que se tienen 65536 posibles semillas. He probado el código, y aunque teóricamente no sea aleatorio, te aseguro que para todo sentido práctico sirve bastante.



Haa! otra cosa, opté por la solución poco elegante. Genero un número de más y no uso el último, el problema de hacer eso es que aumenta el rango de aleatoriedad; para el ejemplo que puse, se elegirían 8 números entre 0 y 8. Afortunadamente eso no me afecta para la aplicación que haré, pero si alguien encuentra una solución su opinión sigue siendo bien recibida =)
 
Última edición:
Te propongo una alternativa mas sencilla.
Por lo que veo quieres cargar un vector de 8 elementos con numeros del 0 al siete sin que se repita ningun elemento. Por tanto en el vector, aunque desordenados vas a tener todos los numeros de 0 a 7.
Por tanto podes hacer esto
Código:
for(i=0;i<8;i++){
    DATOS[i]=i;
}

luego desordenas el vector.

Código:
for (i=0;i<8;i++){
   int posicionAleatoria1 = RAND()%8;
   int posicionAleatoria2 = RAND()%8;
   int aux = DATOS[posicionAleatoria1];
   //intercambio valores
   DATOS[posicionAleatoria1] = DATOS[posicionAleatoria2];
   DATOS[posicionAleatoria2] = aux;
}

-----------------------------------------------------------------------------------------------------------------------------

Ahora si todavia quieres utilizar tu codigo el problema es que estas poniendo mal las condiciones de los for
Aca por ejemplo, estas poniendo desde x=0 a x=8 por lo que tu arreglo contendria 9 valores (deDATOS[0] a DATOS[8])
Código:
FOR(X=0;X<=8;++X)
{DATOS[X]=20;} //Se ponen valores diferentes a los buscados en el Vector datos
Lo correcto seria lo siguiente.
Código:
FOR(X=0;X<8;X++){
DATOS[X]=20;
}
De todas maneras este bloque es innecesario ya que cada valor se va a setear en el for siguiente.

Luego aca pusiste que inicie de x=1 y tu arreglo comienza en 0.
A la variable y tambien tendrias que ponerla en 0.
Código:
FOR(X=1;X<=8;++X)
{OTRO_NUM:
DATOS[X]=RAND()%8; //Datos[x]= numero entre 0 y 7

FOR(Y=1;Y<=X-1;++Y)
{IF(DATOS[X]==DATOS[Y])  // Si Datos[x] es igual a algún valor anterior, 
GOTO OTRO_NUM; //cambia su valor por otro número aleatorio
}
}

Lo correcto seria
Código:
FOR(X=0;X<8;X++){
OTRO_NUM:
DATOS[X]=RAND()%8; 

FOR(Y=0;Y<X;Y++){
IF(DATOS[X]==DATOS[Y])
GOTO OTRO_NUM; 
}
}
De todas maneras te recomiendo mi metodo ya que no anidas dos for y los pasos esta definida su cantidad.
Saludos.
 
Última edición:
Hola loco91

Muchas gracias por tu respuesta, pero fíjate que en los ciclos for no voy de 0 a 8 sino de 1 a 8. Tu método, aunque útil y sencillo creo que no podré usarlo. La aplicación que haré es un buscaminas, los números aleatorios son para las posiciones de las minas, es decir que necesito números aleatorios en un rango mayor al número de números, creo que con tu método no puedo hacerlo.
 
Atrás
Arriba