簡體   English   中英

如何在數組中生成比其他隨機數更多的隨機數?

[英]How to Generate one random number more than other random numbers in an array?

我有一個數字列表,例如: {1,2,3,4,5,6}

我想隨機生成這些數字,我這樣做是這樣的:

void Update(){
    float ran = Random.Range(1,6);
    print(ran);
}

如何生成或打印比其他數字多3個的數字?

例如,如果您想要偏斜的分布,則可以將生成的值映射到所需的分布

// all 1..6 are equal with exception of 3 which appears more frequently 
// 1..2, 4..6 - 10% each (1 occurence  per 10 items)
// 3          - 50%      (5 occurences per 10 items)
private static int[] map = new int[1, 2, 3, 4, 5, 6, 3, 3, 3, 3];

...

void Update{
  float ran = map[Random.Range(map.Length)];
  print(ran);
}

這是一種使用概率論的解決方案,但它是過度設計的。 它也可能有輕微的語法錯誤,因為我現在離Visual Studio太遠了(

var data = new float[] {1, 2, 3, 4, 5, 6};
var indexToWeight = (index) => {
  if (index == 3) return 2;
  return 1; 
};
var total = data.Select((value, index) => indexToWeight(index)).Sum(); 
var weightedData = data.Select((value, index) => Tuple.Create(value, indexToWeight(index)/(float)sum)).ToList();
var boundedData = new List<Tuple<float, float>>(weightedData.Count);
float bound = 0.0f;
for (int i = 0; i < weightedData.Count; i++) {
  boundedData.Add(Tuple.Create(weightedData[i].Item1, bound));
  bound += weightedData[i].Item2;
}

var weightedToValue = (List<Tuple<float, float>> wv, float p) => {
  var pair = wv.FirstOrDefault(item => item.Item2 > p);
  if (pair != null) return pair.Item1;
  return vw.Last().Item1; 
}; 
Random random;
var randomizedData = Enumerable.Range(1, data.Count).Select(index => weightedtoValue(weightedData, random.NextDouble())).ToArray();   

對於正態分布,將threeMultiplier設置為1,將2設置為3的兩倍多,將3設置為3的三倍,依此類推。

void Update() {
    int threeMultiplier = 2; // Twice as much 3's
    int maxNumber = 6;
    int num = Random.Range(1, threeMultiplier * maxNumber);
    if (num > maxNumber) num = 3;
    print(num); 
}

解決“擲骰子攻擊”的一種解決方案可能是:float ran = Random.Range(1,10);

“轉換為整數”

switch (ran) 
 case 1: 
   return 1
 case 2: 
   return 2
 case 3:
   return 3
 case 4:
   return 4
 case 5: 
   return 5
 case 6:
   return 6
 default:
   return 3

因此,您將有50%的機會獲得3的機會,而彼此有10%的機會將3秒的數量減少10,從而減小值^^

檢查我在.Net小提琴中制作的這個示例。 在此代碼中,您有2種可能性。 我非常確定這可以解決您的問題,並且它是一個非常簡單的解決方案。 當然,在Unity中,您可能想使用Random.Range ...更改某些vars yada yada的名稱。

1-您可以打印列表中元素的數量,因此具有'n'個元素的列表將始終打印'n'個數字作為輸出。

2-您可以打印所需的任何數量,只要您更改變量timesToPrint

該代碼將基於goldenNumber的機會打印chanceToPrintGoldenNumber ,否則將在列表上打印一個隨機元素(偶然地可能是黃金數字)。

示例鏈接在這里!

碼:

public static void Main()
{
    Random rnd = new Random();
    var li = new List<int> {1,2,5,3,6,8};
    var timesToPrint = 10;

    var goldenNumber = 3;

     // this is actually 55% chance, because we generate a number form 0 to 100 and if it is  > than 45 we print it... so 55% chance
    var chanceToPrintGoldenNumber = 45;


    // Print as many times as there are numbers on the list

    Console.WriteLine("Printing as many times as there are elements on the list");

    foreach(var number in li)
    {       
        var goldenNumberChance = rnd.Next(0,100);

        if (goldenNumberChance > chanceToPrintGoldenNumber) // 55% chance to print goldenNumber
        {
            Console.WriteLine(goldenNumber);            
        }
        else
        {           
            var i = rnd.Next(0,li.Count);
            Console.WriteLine(li[i]);           
        }
    }

    Console.WriteLine("****************** END ***************************");

    // Print as many times as the value of your "timesToPrint".

    Console.WriteLine("Printing as many times as the value on timesToPrint ");

    for(var i=0; i< timesToPrint; i++)
    {
        var goldenNumberChance = rnd.Next(0,100);

        if (goldenNumberChance > chanceToPrintGoldenNumber) // 55% chance to print goldenNumber
        {
            Console.WriteLine(goldenNumber);            
        }
        else
        {           
            var n = rnd.Next(0,li.Count);
            Console.WriteLine(li[n]);           
        }

    }

}

我會為加權分布執行以下操作:

public class RandomGenerator
{
    Dictionary<Tuple<double, double>, Tuple<int, int>> probability;
    Random random;

    public RandomGenerator(Dictionary<double, Tuple<int, int>> weights)
    {
        random = new Random();

        Dictionary<double, Tuple<int, int>> percent = weights.Select(x => new { Key = x.Key / weights.Keys.Sum(), Value = x.Value }).ToDictionary(t => t.Key, t => t.Value);
        probability = new Dictionary<Tuple<double, double>, Tuple<int, int>>();
        double last = 0;
        foreach (var item in percent.OrderBy(x => x.Key).Select(x => new { Key = x.Key, Value = x.Value }))
        {
            probability.Add(new Tuple<double, double>(last, last + item.Key), item.Value);
            last += item.Key;
        }
    }

    public double GetRandomNumber()
    {
        double w = random.NextDouble();

        var range = probability.Where(x => w >= x.Key.Item1 && w <= x.Key.Item2).First().Value;

        return random.Next(range.Item1, range.Item2);
    }
}

您可以這樣使用它:

Dictionary<double, Tuple<int, int>> weights = new Dictionary<double, Tuple<int, int>>();
weights.Add(80, new Tuple<int, int>(1, 100));
weights.Add(20, new Tuple<int, int>(3,3));

var randgen = new RandomGenerator(weights);
var number = randgen.GetRandomNumber();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM