Piensa en la diferencia entre 1 dado y 3 dados . 1 dado le da una probabilidad uniforme para todos los valores, mientras que 3 dados tenderán a tener una probabilidad más alta para los valores hacia el medio.
Cuantos más "dados" haya en su ecuación, más posibilidades tendrá de obtener algo hacia el centro. Así que definamos una función que pueda manejar cualquier número de manera uniforme :
// Takes a random number between floor and ceil
// pow defines how strongly these results should gravitate towards the middle
// We also define a function TrueRand(floor, ceil) elsewhere where you should substitute your own random function
int CenterRandom(int floor, int ceil, int pow = 3)
{
if(ceil == floor)
return ceil; // don't care to compare
int total = 0;
for(int x = 0; x < pow; x++)
{
total += TrueRand(floor, ceil);
}
return total / pow;
}
Ahora podemos definir una función de ejemplo para usar esto:
// Distribues a number of points between floor and ceil
// We assume a function PlotPoint(int) exists to aid in creating the planet, etc...
void DistributePoints(int floor, int ceil, int numPoints)
{
// Could easily output this in the function parameters, but language wasn't specified
int[numPoints] breaks;
int numBreaks = 0;
// Special case for first pair
breaks[0] = CenterRandom(floor, ceil);
numBreaks++;
for(int x = 0; x < numPoints - 1; x++)
{
// Generate a random number linearly, this will be used for picking
// This way we have a greater chance of choosing a random value between larger pairs
int picker = TrueRandom(floor, ceil);
// Now we first find the pair of points that our picker exists on
// For simplicity, we handle the first and last pair separately
if(picker >= floor && picker < breaks[0])
{
breaks[x] = CenterRandom(floor, breaks[0] - 1);
}
for(int i = 0; i < numBreaks; i++)
{
if(picker > breaks[i] && picker < breaks[i+1])
{
breaks[x] = CenterRandom(breaks[i] + 1, breaks[i+1] - 1);
}
}
if(picker > breaks[numBreaks] && picker <= ceil)
{
breaks[x] = CenterRandom(breaks[numBreaks] + 1, ceil);
}
PlotPoint(breaks[x]); // Plot the point
}
}
Ahora, lo primero en notar es que este código realmente no verifica si el selector ya coincide con uno de los puntos. Si lo hace, simplemente no va a generar un punto, posiblemente algo que le gustaría.
Para explicar lo que está sucediendo aquí, CenterRandom genera una especie de curva de campana. Esta función divide el plano en múltiples curvas de campana, una por par de puntos existentes. El selector nos dice desde qué curva de campana generar. Dado que elegimos linealmente, podemos asegurarnos de que los pares con espacios más grandes entre ellos se elijan con mayor frecuencia, pero aún lo dejamos completamente al azar.
Espero que esto te señale en la dirección correcta.