我试着写一个简单的程序,模拟抽奖,我得到了一些我无法理解的行为,也没有解决:
为了简单起见,我排除了与问题无关的代码
程序:点击它应该获得用户输入的六个不同的数字(1到49之间),得到六个不同的随机数(1到49之间)比较它们并重复获取随机数并与输入进行比较直到有三个匹配
什么是相关的,我在按钮点击时调用函数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();
}
方法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();
}
}
这是获取随机数的函数:
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;
}
如果循环运行一次,或者每次循环后有延迟,或者我在循环中放置断点,那么程序按预期工作。
另外,有一个意外的行为,对同一个数据循环运行不止一次(对于相同的列表),我不明白为什么。
看图片:
(btw =Sprawdź= Check,raz = once,dopierwszejtrójki= 3场比赛)
非常感谢您的帮助,我正在学习,我知道代码的许多部分都可以改进,很多部分仅用于临时调试目的。但是这种行为,我根本就没有得到它。
答案 0 :(得分: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年。
随机数生成从种子值开始。如果相同 种子被重复使用,生成相同的数字序列。一 产生不同序列的方法是制作种子价值 与时间有关,从而与每个新系列产生不同的系列 随机的实例。默认情况下,无参数构造函数 随机类使用系统时钟生成其种子值,而 它的参数化构造函数可以取基于的Int32值 当前时间的刻度数。但是,因为时钟已经 有限分辨率,使用无参数构造函数创建 紧密连续的不同随机对象创建随机数 产生相同随机数序列的生成器。该 下面的例子说明了两个Random对象 紧密连续实例化生成一系列相同的 随机数。
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
通过创建单个Random对象可以避免此问题 而不是多个。要提高性能,请创建一个Random对象 随着时间的推移生成许多随机数,而不是重复 创建一个新的Random对象以生成一个随机数。至 生成适合的加密安全随机数 例如,创建随机密码,使用派生自的类 System.Security.Cryptography.RandomNumberGenerator等 System.Security.Cryptography.RNGCryptoServiceProvider。