2012-12-23 32 views
4

可以說我有5個結果隨機做動作與加權值

Console.WriteLine("1"); 
Console.WriteLine("2"); 
Console.WriteLine("3"); 
Console.WriteLine("4"); 
Console.WriteLine("5"); 

我想要做的隨機使用權重因此,可以說它們的權重爲100

它隨機打印啓動上述行動之一1並將其權重降低5,使其權重爲95.

因此,在完成權重升序後(95,100,100,100,100),所有100個權重都有5%的機會隨機選擇95以上,但95仍有機會被隨機挑選但不是和其他人一樣。

輸出樣本:(控制檯輸出)

1 (weight = 95) 
3 (weight = 95) 
1 (weight = 90) 
5 (weight = 95) 
1 (weight = 85) 
2 (weight = 95) 
+3

所以[你有什麼嘗試?](http://whathaveyoutried.com) –

+2

你能顯示你想要的輸出嗎?我不明白 –

+1

我只是寫了一些代碼來實現你的隨機稱量算法,也得到了1-5,所以你的代碼必須確定。 – PeterJ

回答

1

減輕體重下面是一個簡單的代碼,如果我深知,你需要什麼,你可以利用這一點,作爲一個起點:

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<ActionWithChance> list = new List<ActionWithChance>() 
              { 
               new ActionWithChance("1", 100), 
               new ActionWithChance("2", 100), 
               new ActionWithChance("3", 100), 
               new ActionWithChance("4", 100), 
               new ActionWithChance("5", 100) 
              }; 

     for (int i = 0; i < 10; i++) 
     { 
      RandomHandler.CreateIntervals(list); 
      RandomHandler.GetRandom(list); 
     } 


    } 
} 

static class RandomHandler 
{ 
    public static void CreateIntervals(List<ActionWithChance> list) 
    { 
     int currentBorderMin = 1; 
     int currentBorderMax = 0; 
     foreach (var actionWithChance in list) 
     { 
      actionWithChance.TempMin = currentBorderMin; 
      actionWithChance.TempMax = currentBorderMax 
           + actionWithChance.Chance; 

      currentBorderMax = actionWithChance.TempMax; 
      currentBorderMin = currentBorderMax; 
     } 
    } 

    public static void GetRandom(List<ActionWithChance> list) 
    { 
     Thread.Sleep(20); 
     int allChance = list.Sum(i => i.Chance); 
     Random rand = new Random(); 
     int nextValue = rand.Next(1, allChance + 1); 
     ActionWithChance selectedAction = 
list.FirstOrDefault(i => i.TempMin <= nextValue && i.TempMax >= nextValue); 

     selectedAction.Chance = selectedAction.Chance > 5 
      ? selectedAction.Chance - 5 : 100; 

     selectedAction.DoSomething(); 
    } 
} 

class ActionWithChance 
{ 
    public string Name { get; set; } 
    public int Chance { get; set; } 
    public int TempMin { get; set; } 
    public int TempMax { get; set; } 

    public void DoSomething() 
    { 
     Console.WriteLine(Name); 
    } 


    public ActionWithChance(string name, int chance) 
    { 
     Name = name; 
     Chance = chance; 
    } 
} 
+1

最好不要在每次迭代中創建一個新的「隨機」。但除此之外,你已經編碼了我懶得去做的事情。 :-) – Carson63000

+0

是的,我很無聊:)但隨時提高它! –

+0

list.FirstOrDefault和list.sum不在System.Collections.Generic中有什麼想法? –

2

不知道爲什麼你會使用嵌套case語句亂搞。

每次你需要產生一個新的隨機數,加起來你的權重。

然後使用Random.Next(sumOfWeights)

然後比較您返回的隨機數與第一個權重,前兩個權重的總和,前三個權重的總和等,直到它小於。

這是您的選擇。然後通過5

+0

每次生成新的隨機數時,您不必重新總計權重。只需使用與更新個人體重相同的值更新以前的總和即可。 – Trisped

0

另一種方法:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Collections.Generic; 

namespace RandomWeights 
{ 
    public class WeightedItem 
    { 
     public string Text { get; set; } 
     public int Weight { get; set; } 

     public WeightedItem(string text, int weight) 
     { 
      Text = text; 
      Weight = weight; 
     } 
    } 
    public class WeightedOutput 
    { 
     public static readonly int _decreaseIncrement = 5; 
     List<WeightedItem> items = new System.Collections.Generic.List<WeightedItem>(); 

     public WeightedOutput() 
     { 
      //initialize the five items with weight = 100 
      for (int i = 1; i <= 5; i++) 
       items.Add(new WeightedItem(i.ToString(), 100)); 

      for (int x = 0; x < 50; x++) 
       WriteSelected(); 

      Console.ReadLine(); 
     } 

     public void WriteSelected() 
     { 
      WeightedItem selectedItem = GetItem(); 
      if (selectedItem != null) 
       Console.WriteLine(selectedItem.Text + ": " + selectedItem.Weight); 
      else 
       Console.WriteLine("All items have 0 probability of getting selected"); 
     } 

     public WeightedItem GetItem() 
     { 
      int totalWeight = items.Sum(x=>x.Weight); 
      Random rnd = new Random((int)DateTime.Now.Ticks); 
      int random = rnd.Next(0, totalWeight); 

      WeightedItem selected = null; 
      foreach (var item in items) 
      { 
       if (random < item.Weight && item.Weight > 0) 
       { 
        //need a new item and not a reference to get the right weights 
        selected = new WeightedItem(item.Text, item.Weight); 
        //decrease item's weight 
        item.Weight -= _decreaseIncrement; 
        break; 
       } 

       random -= item.Weight; 
      } 
      return selected; 
     } 
    } 
}