2014-06-18 61 views
0

我正在輪盤類,它應有的功能更多或更少的像一個普通的輪盤遊戲輪盤,其中某些號碼可能需要長達輪盤遊戲輪盤的較大部分,因此具有更高的概率被選中。輪盤賭弱點在隨機數選擇

到目前爲止,它已經通過了更基本的單元測試,也就是編程它的作品,我可以創造一個輪盤,並與一羣普通的值填充它,它會做到這一點。但是當涉及到我的概率測試時,我決定試試它作爲一個6面模具,經過10,000,000次試驗後,它應該產生大約3.5的平均模具卷,不幸的是它甚至不會接近在10,000,000次試驗後的平均值大約爲2,9,所以我猜測我的號碼選擇有一個弱點。我已經發布了單元測試和下面的實際代碼:

public class RouletteNumber<T> 
    { 
     public readonly T Number; 
     public readonly int Size; 

     public RouletteNumber(T number, int size) 
     { 
      this.Number = number; 
      this.Size = size; 
     } 

     public static RouletteNumber<T>[] CreateRange(Tuple<T, int>[] entries) 
     { 
      var rouletteNumbers = new RouletteNumber<T>[entries.Length]; 

      for (int i = 0; i < entries.Length; i++) 
      { 
       rouletteNumbers[i] = new RouletteNumber<T>(entries[i].Item1, entries[i].Item2); 
      } 

      return rouletteNumbers; 
     } 
    } 

public class RouletteWheel<T> 
    { 
     private int size; 
     private RouletteNumber<T>[] numbers; 
     private Random rng; 

     public RouletteWheel(params RouletteNumber<T>[] rouletteNumbers) 
     { 
      size = rouletteNumbers.Length; 
      numbers = rouletteNumbers; 
      rng = new Random(); 

      //Check if the roulette number sizes match the size of the wheel 
      if (numbers.Sum(n => n.Size) != size) 
      { 
       throw new Exception("The roulette number sections are larger or smaller than the size of the wheel!"); 
      } 
     } 

     public T Spin() 
     { 
      // Keep spinning until we've returned a number 
      while (true) 
      { 
       foreach (var entry in numbers) 
       { 
        if (entry.Size > rng.Next(size)) 
        { 
         return entry.Number; 
        } 
       } 
      } 
     } 
    } 

[TestMethod] 
     public void DiceRouletteWheelTest() 
     { 
      double expected = 3.50; 
      var entries = new Tuple<int, int>[] 
      { 
       Tuple.Create(1, 1), 
       Tuple.Create(2, 1), 
       Tuple.Create(3, 1), 
       Tuple.Create(4, 1), 
       Tuple.Create(5, 1), 
       Tuple.Create(6, 1) 
      }; 
      var rouletteWheel = new RouletteWheel<int>(RouletteNumber<int>.CreateRange(entries)); 
      var results = new List<int>(); 

      for (int i = 0; i < 10000000; i++) 
      { 
       results.Add(rouletteWheel.Spin()); 
      } 

      double actual = results.Average(); 

      Assert.AreEqual(expected, actual); 
     } 
    } 
+0

*「應該發揮作用或多或少像一個普通的輪盤賭,其中某些號碼可能需要長達輪盤賭的較大部分,因此有更高的被選中的可能性。「* - 這聽起來不像我見過的任何輪盤賭輪...所有的數字都有相同的發生機會。 –

回答

1

也許我沒有正確理解它,但我猜問題就在這裏:

while (true) 
{ 
    foreach (var entry in numbers) 
    { 
    if (entry.Size > rng.Next(size)) 
    { 
     return entry.Number; 
    } 
    } 
} 

你」每次你做if檢查時重新計算rng.Next。 所以第一個號碼有1 6機會正在採取的。號2(在數量上的下一條目),那麼具有2 6機會正在採取的(一個新的號碼爲1和6之間呈現)。但是因爲你總是從第一個開始,你最終會有更多的更低的數字。
我還沒有看到在一個正常的隨機生成的,而(真)的需要。 我猜這可能會工作,看起來像當前的代碼:

var rndValue = rng.Next(size); 
foreach (var entry in numbers) 
    { 
    if (entry.Size > rndValue) 
    { 
     return entry.Number; 
    } 
} 
+0

是的,這看起來好像他的基本計算是關閉的。 –

3

當你調用Random.Next(n)它生成介於0和N-1,而不是0到n之間的隨機數。

你有沒有考慮是什麼?

事實上,對於一個6面的骰子,你會想打電話Random.Next(1, 7)

+0

如果所有數字均爲1,他的平均數將爲2.5。 – Kristof