Estoy trabajando en un videojuego en el que las unidades enemigas deben ser enviadas a la pantalla en un intervalo regular, pero deben permanecer algo aleatorias. Así que digamos que tengo que ponerlos en la pantalla a un ritmo de 30 por minuto.
Actualmente elijo al azar un número entero entre [1 - 100] cada 600 ms. Si el número es 30 o menos, se envía una unidad. Si el número es mayor que 30, no se envía la unidad. Como hay 100 intervalos de 600 ms en 60 segundos, llego al objetivo de 30 unidades por minuto.
El problema es que la distribución no es tan uniforme. A veces hay periodos en los que no se envían muchas unidades, y otras veces en los que hay demasiadas.
¿Hay alguna forma de suavizar la distribución para que siga siendo aleatoria pero permita un flujo de unidades más consistente?
EDIT: He seguido los consejos de @Ross Millikan y a continuación están los resultados. Definitivamente mucho más suave usando su algoritmo.
3 unidades distribuidas aleatoriamente cada 10 ranuras ___X___X_X___XXX_____X_____X_X______XX_X_X_____XX_X_X______X__X__XX____X____X__X_____XX_X____X_XX___X___X___X___X___X__X___X_X___X_____XX_X_X__XX______XXX_________X__X__X_____XX_X______X_XX___X_X___X_X___X_X____X_____XX__X_X_X________XXX_____X____X_X_X_X___X___X_X___X__X_X____X____XX_X_____XX_____X____X___XX______XX_X_X____X___X____X_X_X____X__X__X__X____XX__XX___X_______X__X_XX______X_X____X__X_X_X_X_X_____X___X__X____X___XX___X____X_XX_X___X___X_X______XX__X_X_____X______XX_X__X_X_________XX_X____X_X_X_XX___X_____X_X__X___X_____X__X_X_____XX_X_X_X_____X____X___XX__X_X_____X___X_X__X_X_X________XX___X_____X__XX__X__X__X____X__X___XX_______XXX_______XXX_X__X________X___XXX____XX_______X_X__X__XX____X__X__X____X_____XX_X_____X_XX___X__X___X___X_X_X____X__X____X__X__X__X_X___XX______X___XX______X_XX____XX_____X_X____XX__X_X____X__XX___X_____X___X__X___X__X_X__X___XX____X___X_X_____X____XX_X______X_XX__X_____X_X______XX___X_X___XX_____XX__X__X_____X___X_X__X___X_XX____X_____XX__XXX_______
30 de 100 posibilidades de una unidad en cada ranura X__XX___X__XXX___XX_XX__X_______X_XX_____X_XX_X_______X__X_XX_____________X___X___X______X_X__XX____X____X___XX_X_XX___XX______X________X__X______X_________________X___X____X__________XX__X________XX__X_______X_XX_X__XX_X_X_XXX__________X____X____________X__X______XX__XXXXXX_X_____X______X___XXX__X_XX__XX_X__X____X___XXX__X_X__XX____XX____X___XX_______X______X__X_XX_____XX_X__XX_XXX__XXX_____XX___XXXXX___X_XXX_____X_X_____X__X__XX_________XXX_______X___XX___XX_X____XX__XX___X___XX_____X_______X__________X_________X_____________XX___XX__X_X_X___X_XXX_______XXXX_X_XX__X_X___X______XX_______XXX______X_X_X____X____X_X___X_XXX_XXX_X__X___XX___X____X_____X_X_X__X_____________X_X______X_XX_____XXX_____XXX___X________X____X_X___X_____X_X_X___XXXX________X____X__X__X__X___________X______XXX____X__X______X___XX_XX__________XXX_____X__X______XX_XX___X____XXXX______X___X______X____X__X___X__X______X_XX__X____X__XX_XX_____X____XX______X___X_X___X_X_____X__X__XX__XX_XX_X__XXX_X_X___X___X___X___X_X__
A continuación se muestra el código java. Como tengo que calcular estas cosas entre fotogramas en un videojuego, me alejo de las matemáticas decimales. Así que toda la implementación se hace usando int's.
public static void main(String[] args) throws InterruptedException {
nonUniformDispatch();
uniformDispatch();
}
static void nonUniformDispatch() throws InterruptedException {
Random rand = new Random();
double it = 1_000;
int goal = 30;
int dispatches = 0;
for (int i = 0; i < it; i++) {
if (goal > rand.nextInt(100)) {
dispatches++;
System.out.print("X");
} else {
System.out.print("_");
}
}
System.out.println("\n\ndispatches = " + dispatches);
}
static void uniformDispatch() throws InterruptedException {
int totalUnits = 3;
Random rand = new Random();
double it = 1_000;
int dispatches = 0;
int totalSlots = 10;
int unitsRemaining = totalUnits;
int slotsRemaining = totalSlots;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < it; i++) {
// System.out.println("slotsRemaining = " + slotsRemaining + ", unitsRemaining = " + unitsRemaining);
if (slotsRemaining <= unitsRemaining) {
dispatches++;
unitsRemaining--;
sb.append("X");
} else if (unitsRemaining > 0) {
int x = (unitsRemaining * 100) / slotsRemaining;
if (x > rand.nextInt(100)) {
dispatches++;
unitsRemaining--;
sb.append("X");
// System.out.println("x = " + x + ", hit");
} else {
sb.append("_");
// System.out.println("x = " + x + ", miss");
}
} else {
sb.append("_");
// System.out.println("miss");
}
slotsRemaining--;
if (slotsRemaining == 0) {
slotsRemaining = totalSlots;
unitsRemaining = totalUnits;
}
}
System.out.println(sb.toString());
System.out.println("\n\ndispatches = " + dispatches);
TimeUnit.SECONDS.sleep(10);
}