2014-06-27 22 views
2

我試着寫簡單的程序,模擬開獎,我得到了一些行爲,我無法理解,也不能修復:列表更新 - 意外行爲

爲了簡單起見我排除的代碼是無關的問題

程序:點擊它應該得到用戶輸入的六個不同的數字(1和49之間),獲得六個不同的隨機數字(1和49之間)比較它們,並重復獲得隨機數字,並與輸入比較,直到有三場比賽。

  1. 什麼是相關的,我調用函數GetResults()上的按鈕單擊並傳遞給它兩個參數(下面的方法定義)。我將其簡化爲按鈕單擊以顯示您。這裏有一些條件和函數調用,但它們正在工作,即使沒有它們也存在問題,所以這就是爲什麼底部圖像示例可能有點不同。

    private void btnCheck_Click(object sender, EventArgs e) 
    { 
        lotto.GetResults(3, ref listRndNumLabels); 
    
        lblMatches.Text = lotto.CurrentMatches.ToString(); 
        lblTryCounter.Text = lotto.NumberOfTries.ToString(); 
        lblBalance.Text = lotto.Balance.ToString() + " zł"; 
        lblThreesAmmount.Text = lotto.ThreesAmmount.ToString(); 
        lblFoursAmmount.Text = lotto.FoursAmmount.ToString(); 
        lblFivesAmmount.Text = lotto.FivesAmmount.ToString(); 
        lblSixesAmmount.Text = lotto.SixesAmmount.ToString(); 
    } 
    
  2. 方法GetResults()需要3作爲在端

    public void GetResults(int Choice, ref List<Label> listLblRndNum) 
    { 
        _currentMatches = 0; 
        int desiredNumberOfMatches = Choice; 
    
        // while we got other ammount of matches than three, go again 
        while (_currentMatches != desiredNumberOfMatches) 
        { 
         _numberOfTries++; 
    
         // get list of mutually exclusive 6 numbers betweeen 1 and 49 
         var tempList = GetRndNums(); 
    
         // insert random numbers to list 
         _listLotteryNumbers.Clear(); 
         for (int i = 0; i < 6; i++) 
         { 
          _listLotteryNumbers.Insert(i, tempList[i]); 
         } 
    
         _balance -= _ticketCost; 
         _currentMatches = 0; 
    
         // get number of matches 
         for (int i = 0; i < 6; i++) 
         { 
          foreach (int num in _listLotteryNumbers) 
          { 
           if (_listSelectedNumbers[i] == num) 
           { 
            _currentMatches++; 
           } 
          } 
         } 
    
         //FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _currentMatches: " + _currentMatches.ToString()); 
    
         //FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - tempList { " + tempList[0] + " " + tempList[1] + " " + tempList[2] + " " + tempList[3] + " " + tempList[4] + " " + tempList[5] + " }"); 
         //FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _listLotteryNumbers { " + _listLotteryNumbers[0] + " " + _listLotteryNumbers[1] + " " + _listLotteryNumbers[2] + " " + _listLotteryNumbers[3] + " " + _listLotteryNumbers[4] + " " + _listLotteryNumbers[5] + " }"); 
         //FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _listSelectedNumbers { " + _listSelectedNumbers[0] + " " + _listSelectedNumbers[1] + " " + _listSelectedNumbers[2] + " " + _listSelectedNumbers[3] + " " + _listSelectedNumbers[4] + " " + _listSelectedNumbers[5] + " }"); 
    
         // update stats 
         if (_currentMatches == 3) 
         { 
          _threesAmmount++; 
          _balance += 10; 
         } 
         else if (_currentMatches == 4) 
         { 
          _foursAmmount++; 
          _balance += 100; 
         } 
         else if (_currentMatches == 5) 
         { 
          _fivesAmmount++; 
          _balance += 3500; 
         } 
         else if (_currentMatches == 6) 
         { 
          _sixesAmmount++; 
          _balance += 1000000; 
         } 
    
         //FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - Threes Ammount right after updating: " + _threesAmmount); 
         //FrmLotto.lbResults.Items.Add(""); 
    
         // this gets out of the loop if user has chosen from ddl to run once, it is irrelevant here 
         if (desiredNumberOfMatches == -1) 
          break; 
        } 
    
        // finally update Labels with the desired result 
        for (int i = 0; i < 6; i++) 
        { 
         listLblRndNum[i].Text = _listLotteryNumbers[i].ToString(); 
        } 
    } 
    
  3. 更新所需的比賽和標籤的列表的數目這是它獲取的隨機數的函數:

    public List<int> GetRndNums() 
    { 
        List<int> listRndNums = new List<int>(); 
        Random rndNum = new Random(); 
    
        for (int i = 0; i < 6; i++) 
        { 
         int myNum = 0; 
         do 
          myNum = rndNum.Next(1, 49); 
         while (listRndNums.Contains(myNum)); 
    
         listRndNums.Add(myNum); 
        } 
        listRndNums.Sort(); 
    
        return listRndNums; 
    } 
    

所以程序按預期工作,如果循環運行一次,或者如果有德拉每個循環之後,或者如果我在循環中放置斷點。

否則會出現意外的行爲,對同一個數據循環運行不止一次(對於相同的列表),我不明白爲什麼。

看看圖片:

  1. 程序運行一次,我點擊按鈕五次,向您展示的結果是罰款:

(順便說一句=Sprawdź=檢查,拉茲=一次, DO pierwszejtrójki=直到3個匹配)

http://ultraimg.com/jHQY

  1. 而當我選擇3個匹配項時(或者從上面的代碼示例中單擊按鈕),我收到錯誤的結果,循環將多次運行相同的值。

http://ultraimg.com/jHQn

將是幫助非常感激,我學習,我知道的代碼,很多地方還有待改進,許多地方只用於臨時調試的目的。但是,這種行爲,我根本不明白。

+2

http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number?lq=1 – Steve

+0

只是一個供參考 - 通過你的列表作爲ref參數是多餘的,列表是默認通過引用傳遞的實例 – James

回答

0

爲了解決這個問題,你應該嘗試使

Random rndNum = new Random(); 

一個靜態變量。

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

僞隨機數被從有限組數字的選擇概率相同。所選擇的數字不是完全隨機的,因爲使用確定的數學算法來選擇它們,但它們對於實際目的而言是足夠隨機的。 Random類的當前實現基於Donald E. Knuth的減法隨機數生成器算法。欲瞭解更多信息,請參閱D. E. Knuth。 「計算機編程的藝術,第2卷:研究數學算法」。 Addison-Wesley,Reading,MA,第二版,1981年。

隨機數的產生從種子值開始。如果重複使用相同的 種子,則會生成相同的一系列數字。一種產生不同序列的方法是使種子值 具有時間依賴性,由此產生與每個新的Random實例不同的系列。默認情況下,Random類的無參數構造函數使用系統時鐘生成其種子值,而其參數化構造函數的 可以基於當前時間內的 數量的滴答取Int32值。但是,由於時鐘具有有限分辨率,因此使用無參數構造函數創建 不同的隨機對象會緊密連續生成隨機數 生成器,以生成相同的隨機數序列。以下示例說明了兩個緊密連續實例化的 隨機對象會生成一系列相同的 隨機數。

byte[] bytes1 = new byte[100]; 
byte[] bytes2 = new byte[100]; 
Random rnd1 = new Random(); 
Random rnd2 = new Random(); 

rnd1.NextBytes(bytes1); 
rnd2.NextBytes(bytes2); 

Console.WriteLine("First Series:"); 
for (int ctr = bytes1.GetLowerBound(0); 
    ctr <= bytes1.GetUpperBound(0); 
    ctr++) { 
    Console.Write("{0, 5}", bytes1[ctr]); 
    if ((ctr + 1) % 10 == 0) Console.WriteLine(); 
} 
Console.WriteLine(); 
Console.WriteLine("Second Series:");   
for (int ctr = bytes2.GetLowerBound(0); 
    ctr <= bytes2.GetUpperBound(0); 
    ctr++) { 
    Console.Write("{0, 5}", bytes2[ctr]); 
    if ((ctr + 1) % 10 == 0) Console.WriteLine(); 
} 
// The example displays the following output to the console: 
//  First Series: 
//   97 129 149 54 22 208 120 105 68 177 
//   113 214 30 172 74 218 116 230 89 18 
//   12 112 130 105 116 180 190 200 187 120 
//   7 198 233 158 58 51 50 170 98 23 
//   21 1 113 74 146 245 34 255 96 24 
//   232 255 23 9 167 240 255 44 194 98 
//   18 175 173 204 169 171 236 127 114 23 
//   167 202 132 65 253 11 254 56 214 127 
//   145 191 104 163 143 7 174 224 247 73 
//   52 6 231 255 5 101 83 165 160 231 
//   
//  Second Series: 
//   97 129 149 54 22 208 120 105 68 177 
//   113 214 30 172 74 218 116 230 89 18 
//   12 112 130 105 116 180 190 200 187 120 
//   7 198 233 158 58 51 50 170 98 23 
//   21 1 113 74 146 245 34 255 96 24 
//   232 255 23 9 167 240 255 44 194 98 
//   18 175 173 204 169 171 236 127 114 23 
//   167 202 132 65 253 11 254 56 214 127 
//   145 191 104 163 143 7 174 224 247 73 
//   52 6 231 255 5 101 83 165 160 231 

此問題可以通過創建一個單獨的隨機對象而 不是多個被避免。爲了提高性能,創建一個隨機對象 隨着時間的推移生成許多隨機數,而不是重複創建一個新的隨機對象來生成一個隨機數 。以 生成一個密碼安全的隨機數,適合於創建一個隨機密碼 ,例如,使用從 System.Security.Cryptography.RandomNumberGenerator派生的類,例如 System.Security.Cryptography.RNGCryptoServiceProvider。

+0

非常感謝!我嘗試了數百萬件事情,並不認爲它可能如此簡單。謝謝先生,你啓蒙了我。 – rvnlord