c# - List update in every loop run - Unexpected behavior -
i tried write simple program, simulates lottery , got behavior cannot understand, nor fix:
to keep simple excluded code irrelevant problem
program: on click should 6 different numbers (between 1 , 49) entered user, 6 different random numbers (between 1 , 49) compare them , repeat getting random numbers , comparing entered until there 3 matches.
what relevant, calling function getresults() on button click , passing 2 parameters (method definition below). simplified button click show you. there conditions , function calls there, working , problem exists without them that's why image example on bottom may 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 number of desired matches , list of labels updated @ end
public void getresults(int choice, ref list<label> listlblrndnum) { _currentmatches = 0; int desirednumberofmatches = choice; // while got other ammount of matches three, go again while (_currentmatches != desirednumberofmatches) { _numberoftries++; // list of mutually exclusive 6 numbers betweeen 1 , 49 var templist = getrndnums(); // insert random numbers list _listlotterynumbers.clear(); (int = 0; < 6; i++) { _listlotterynumbers.insert(i, templist[i]); } _balance -= _ticketcost; _currentmatches = 0; // number of matches (int = 0; < 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(""); // gets out of loop if user has chosen ddl run once, irrelevant here if (desirednumberofmatches == -1) break; } // update labels desired result (int = 0; < 6; i++) { listlblrndnum[i].text = _listlotterynumbers[i].tostring(); } }
and function gets random numbers:
public list<int> getrndnums() { list<int> listrndnums = new list<int>(); random rndnum = new random(); (int = 0; < 6; i++) { int mynum = 0; mynum = rndnum.next(1, 49); while (listrndnums.contains(mynum)); listrndnums.add(mynum); } listrndnums.sort(); return listrndnums; }
so program works expected if loop run once, or if there delay after each loop, or if put breakpoint in loop.
otherwise there unexpected behavior, loop run more once same data (for same lists), don't understand why.
look @ images:
- program run once, clicked button 5 times, show results fine:
(btw = sprawdź = check, raz = once, pierwszej trójki = until 3 matches)
- and when select until 3 matches (or click button code example above) receiving wrong result, loop runs multiple times same values.
would grateful help, learning, know many parts of code improved, many parts temp debugging purposes only. behavior, don't it.
in order fix problem should try making
random rndnum = new random();
a static variable.
see : http://msdn.microsoft.com/en-us/library/system.random.aspx
pseudo-random numbers chosen equal probability finite set of numbers. chosen numbers not random because definite mathematical algorithm used select them, sufficiently random practical purposes. current implementation of random class based on donald e. knuth's subtractive random number generator algorithm. more information, see d. e. knuth. "the art of computer programming, volume 2: seminumerical algorithms". addison-wesley, reading, ma, second edition, 1981.
the random number generation starts seed value. if same seed used repeatedly, same series of numbers generated. 1 way produce different sequences make seed value time-dependent, thereby producing different series each new instance of random. default, parameterless constructor of random class uses system clock generate seed value, while parameterized constructor can take int32 value based on number of ticks in current time. however, because clock has finite resolution, using parameterless constructor create different random objects in close succession creates random number generators produce identical sequences of random numbers. following example illustrates 2 random objects instantiated in close succession generate identical series of random numbers.
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:"); (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:"); (int ctr = bytes2.getlowerbound(0); ctr <= bytes2.getupperbound(0); ctr++) { console.write("{0, 5}", bytes2[ctr]); if ((ctr + 1) % 10 == 0) console.writeline(); } // example displays following output 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
this problem can avoided creating single random object rather multiple ones. improve performance, create 1 random object generate many random numbers on time, instead of repeatedly creating new random objects generate 1 random number. generate cryptographically secure random number suitable creating random password, example, use class derived system.security.cryptography.randomnumbergenerator such system.security.cryptography.rngcryptoserviceprovider.
Comments
Post a Comment