Pense na diferença entre 1 dado e 3 dados . 1 dado fornece uma probabilidade uniforme para todos os valores, enquanto 3 dados tendem a ter uma probabilidade maior para os valores no meio.
Quanto mais "dados" na sua equação, maior a sua chance de conseguir algo em direção ao centro. Então, vamos definir uma função que possa lidar com qualquer número uniformemente :
// 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;
}
Agora podemos definir um exemplo de função para usar isso:
// 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
}
}
Agora, o primeiro a observar é que esse código realmente não verifica se o selecionador já corresponde a um dos pontos. Se isso acontecer, simplesmente não irá gerar um ponto, possivelmente algo que você possa gostar.
Para explicar o que está acontecendo aqui, o CenterRandom gera uma espécie de curva de sino. Essa função divide o plano em várias curvas de sino, uma por par de pontos existentes. O selecionador nos diz de qual curva de sino gerar. Como escolhemos linearmente, podemos garantir que os pares com intervalos maiores sejam escolhidos com mais frequência, mas ainda o deixamos completamente aleatório.
Espero que isso aponte a direção certa.