Supongmaos que tenemos una lista de 100 canciones (la cantidad es irrelevante ahora mismo)...
Es ideal tenerlos indexados de alguna manera, supongamos que mantienes las rutas en un array...
0) ruta a la canción 0.mp3
1) ruta a la canción 1.mp3
...
99) ruta a la canción 99.mp3
Bien pués la idea es tener una función que primero recoja el número de canciones solicitadas al azar...
entero IndexOrden, IndexAzar
string [] Canciones
entero[] Barajado
funcion InicializarArrayExtra(entero cantidad)
entero k
alojar espacio para Barajado[cantidad]
bucle para k desde 0 hasta cantidad -1
barajado[k] = k
siguiente
fin funcion
entero[] = funcion GetListaReproduccion( entero cantidad, buleano alAzar, entero TotalCanciones)
entero k, j, i, n
entero[] Lista
//NOTA: No se comprueba que cantidad sea negativo, cero, o un valor mayor que 'canciones'... debería verificarse antes de llamarse aquí.
alojar espacio para lista[cantidad]
Si (alAzar == FALSE)
j = (IndexOrden + cantidad)
sino
j = (IndexAzar + cantidad)
fin si
si (j >= TotalCanciones)
n = (j modulo TotalCanciones)
j = TotalCanciones -1
sino
n = -1
fin si
si (alzar == FALSE) // se toma la lista en secuencia, siguiendo
bucle para i desde IndexOrden hasta j
lista[k] = i
k +=1
siguiente
bucle para i desde 0 hasta n // si n es negativo no entrará al bucle.
lista[k] = i
k +=1
siguiente
IndexOrden = i // se actualiza el index... para una próxima llamada.
sino // Elegidos al azar.
Si (n <=0) // barajamos...
llamada a Barajar(cantidad, TotalCanciones lista[] )
fin si
bucle para i desde IndexAzar hasta j
lista[k] = barajado[i]
k +=1
siguiente
si (k < cantidad) // no se han recogido todos los solicitados en ese tramo restante...
llamada a Barajar(cantidad, TotalCanciones lista[] )
fin si
bucle para i desde 0 hasta n // si n es negativo no entrará al bucle.
lista[k] = barajado[i]
k +=1
siguiente
IndexAzar = i // se actualiza el index... para una próxima llamada.
fin si
devolver lista[]
fin funcion
// La lista se pasa por referencia
Funcion Barajar(entero cantidad, entero TotalCanciones, entero[] Lista )
entero k, j, tmp
bucle para j desde TotalCanciones -1 hasta 1 retrocediendo
k = random(entre j y 1) // elegir un indice al azar
// intercambia el elemento en posición 'i', con el elemento en posición 'k'
tmp = barajado[j]
barajado[j] = barajado[k]
barajado[k] = barajado[tmp]
siguiente
fin funcion
...y eso es todo...
Si lo revisas bien... verás que la lista no se toca, lo que se hace es usar un array adicional del mismo tamaño que el array de canciones... que se inicializa después de tomar el array de canciones, pués el tamaño de este array es el parámetro que se precisa para inicializar dicho array temporal. Inicialmente dicho array se mantiene en orden, pero luego se barajará.... desordenando los índices.
Cuando se invoque la función 'GetListaReproduccion', se la pasan 3 parámetros...
- La cantidad de canciones que se quiere reproducir...
- Si se desea reproducir al azar, o en el orden en que aparecen.
- La cantidad total de canciones que tiene la lista de canciones (en el ejemplo sería 100).
Lo primero que hace la función es retomar un 'index' que puede tener un valor previo y que se va actualizando...
Cada 'modo de reproducción' mantiene su propio index, para no interferir... es decir es posible reproducir las canciones al azar y luego alternar a ordenado, volver a reproducir al azar y luego ordenado , etc... y siempre se estarán reproduciiendo canciones no escuchadas antes...
De hecho si revisas a fondo el pseudocódigo, verás que cualquier canción no se volverá a reproducir hasta que no se hayan escuchado las otras 99... es circular... de modo que si se han pedido 15 canciones y se empieza en la canción 92, tomará las 7 que quedna hasta el 99 y luego tomará las otroas 8 desde el índice 0.
En el caso de 'al azar', cuando se han escuchado todas, se vuelven a a barajar, para disponer de otro orden distinto... fíjate que si tras el primer bucle no se han recogido todos los índices, volvemos a barajar antes de retomar las que faltan para devolve rla lista con los índices que se han de reproducir...
La función lo que devuelve es un pequeño array de indices, son estos índices los que 'mandan' sobre la lista a reproducir....
La función de reproducción sería tal que así:
// Ambas listas se pasan por referencia
funcion Reproducir( entero Cantidad, string[] canciones, entero[] Lista)
entero k
string rutaMp3
bucle para k desde 0 hasta cantidad-1
rutaMp3 = canciones[lista[k]]
reproducir(rutamp3 .... )
siguiente
fin funcion
Si te fijas, tomamos como ruta, no el índice k en el array de canciones, si no que el índice en canciones a reproducir, es el valor que contiene el array lista en el índice k... (que se tomó de la función previa).
p.d.:Fíjate que esta función 'Reproducir', recibe como parámetro la lista, de índices que ya se ha obtenido, pero podría modificarse ligeramente la función y recibir otro parámetro, para adquirir la lista desde dentro de dicha función.... se hace el pesudcódigo para este cambio, nota ahora los parámetro de entrada...
// La listas se pasan por referencia
funcion Reproducir( entero Cantidad, string[] canciones, buleano alAzar)
entero k
string rutaMp3
lista[] = GetListaReproduccion(cantidad, canciones.Length, alAzar)
bucle para k desde 0 hasta cantidad-1
rutaMp3 = canciones[lista[k]]
reproducir(rutamp3 .... )
siguiente
fin funcion
Antes se asumía que la lista se solicitaba antes de llamar a la reproducción, ahora esta función resulta más 'funcional'...
Cuando salga d ela función 'Reproducir' es ahora cuando puedes indica ral usuario eso de:
cout << "\t>>>Siguiente bloque de canciones, pulse cualquier tecla" << endl;