I tried to write simple program, that simulates lottery and I got some behavior I cannot understand, nor fix:
To keep it simple I excluded code that is irrelevant to the problem
PROGRAM: On click it should Get six different numbers (between 1 and 49) entered by user, get six different random numbers (between 1 and 49) compare them and repeat getting random numbers and comparing with entered until there are three matches.
What is relevant, I am calling function GetResults() on button click and passing to it two parameters (method definition below). I simplified it to button click to show you. There are some conditions and function calls there, but they are working and problem exists even without them so that's why image example on the bottom may be a little different.
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(); }
The method GetResults() takes 3 as number of desired matches and List of Labels which is updated at the end
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(); } }
And this is the function which gets random numbers:
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; }
So program works as expected if loop run once, or if there is delay after each loop, or if I put breakpoint in the loop.
OTHERWISE there is an unexpected behavior, loop run more than once for the same data (for the same lists), I don't understand why.
look at the images:
- Program run once, I clicked button five times, to show you that results are fine:
(btw = Sprawdź = Check, raz = once, do pierwszej trójki = until 3 matches)
- And when I select until 3 matches (or click button from the code example above) I am receiving wrong result, loop runs multiple times for the same values.
Would be really grateful for help, I am learning, I know that many parts of code could be improved, many parts are for temp debugging purposes only. But this behavior, I simply don't get it.