Случайное взвешивание в C # - PullRequest
       20

Случайное взвешивание в C #

1 голос
/ 24 сентября 2011

Я создаю игру на C #, и важной частью игры является случайность.По сути, это симулятор борьбы, где «ходы» выбираются на столе в зависимости от ряда факторов, таких как атрибуты борцов и текущий импульс.

Затем из всех ходов, соответствующих этому критерию, случайнымодин выбирается для выполнения с использованием объекта Random и Skip / Take в LINQ. Но этого действительно недостаточно.То, что я хочу сделать, это вероятность выбора веса перемещений (у меня уже есть столбец для таблицы перемещений для целого числа от 1 до 100).Как бы я применил это взвешивание в моем случайном выборе строки?

Ответы [ 4 ]

0 голосов
/ 24 сентября 2011

Я смотрел на то же самое, что и Карстен, но с Linq.

данные ходы представляют собой набор ходов, каждое из которых имеет целочисленное свойство Weight

public Move PickRandomMove()
{
    var allMovesWeight = moves.Sum(m => m.Weight);
    // pick a unit of weight at random, then shift it along by the weight of the 
    // first move so that there will always be an element in the TakeWhile results
    var randomPick = new Random().Next(0, allMovesWeight) +  moves.First().Weight;

    return moves.TakeWhile(move => (randomPick -= move.Weight) > 0).Last(); 
}

Я подозреваю, что есть более ясный способ выразить, как работает TakeWhile, но, надеюсь, вы поймете идею

0 голосов
/ 24 сентября 2011

Суммируйте общий вес каждого возможного хода.

Разделите каждый из них на общее количество, чтобы вы нормализовали диапазон до 0.этот диапазон.Выберите последовательный порядок для каждого хода и выберите тот, в котором находится случайное число.

0 голосов
/ 24 сентября 2011

это не так уж сложно.У меня нет кода для работы, поэтому я предполагаю, что у вас есть объекты Move с атрибутом Weight внутри массива, и все веса составляют до 100,0 (на самом деле не имеет значения).Теперь вы сортируете массив по убыванию весов, выбираете случайное число от 0 до 99 и повторяете все это, уменьшая ваше случайное число.Как только он перестает быть положительным, вы останавливаетесь и выбираете текущий индекс / ход

var value = rnd.NextDouble()*100.0;
foreach(var move in moves.OrderByDescending(m => m.Weight))
{
   value -= move.Weight;
   if (value <= 0) return move;
}

, конечно, вы можете кэшировать порядок или даже выборки в большой массив и использовать случайный индекс для этого (дляНадеюсь, что принцип должен быть ясен.

Как предложил Джордж - вот вариант, в котором можно опустить предположения, что весовые коэффициенты составляют до 100:

double _weightSum;
...
// initialize the Sum somewhere
_weightSum = moves.SumBy(m => m.Weight);

Move GetRandomMove()
{
    var value = rnd.NextDouble()*weightSum;
    foreach(var move in moves.OrderByDescending(m => m.Weight))
    {
       value -= move.Weight;
       if (value <= 0) return move;
    }
}
0 голосов
/ 24 сентября 2011

Некоторый код поможет мне точно понять, что вам нужно, но я предлагаю использовать библиотеку Random .NET.Некоторая документация может быть найдена здесь:

http://msdn.microsoft.com/en-us/library/system.random.aspx

В этом примере генерируется 5 случайных целых чисел

Random rand = new Random();

Console.WriteLine("Five random integer values:");
for (int ctr = 0; ctr <= 4; ctr++)
   Console.Write("{0,15:N0}", rand.Next());
Console.WriteLine();

Это приведет к тому, что текущее время станет большеслучайный».Если вам нужны воспроизводимые тесты, вы можете заполнить их постоянными во время тестирования.

...