Подумайте о разнице между 1 кубиком и 3 кубиками . 1 кубик дает вам равную вероятность для всех значений, в то время как 3 кубика будут иметь более высокую вероятность для значений ближе к середине.
Чем больше «кубиков» в вашем уравнении, тем больше у вас шансов получить что-то к центру. Итак, давайте определим функцию, которая может обрабатывать любое число равномерно :
// 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;
}
Теперь мы можем определить пример функции, чтобы использовать это:
// 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
}
}
Теперь первое, что следует отметить, - этот код действительно не проверяет, соответствует ли сборщик одному из пунктов. Если это произойдет, то просто не будет генерировать точку, возможно, то, что вам может понравиться.
Чтобы объяснить, что здесь происходит, это то, что CenterRandom создает своего рода кривую колокола. Эта функция разбивает плоскость на несколько кривых колокольчиков, по одной на пару существующих точек. Сборщик говорит нам, из какой кривой колокола генерировать. Поскольку мы выбираем линейно, мы можем гарантировать, что пары с большими промежутками между ними будут выбираться чаще, но мы все равно оставляем их совершенно случайными.
Надеюсь, что это указывает вам в правильном направлении.