当今社会“客”字横飞,什么“博客”、“播客”、“优客”、“威客”。。。,作为一个程序工作者决定在本人的第一个带“客”字类型的文章中迎来2007年。
今天写了一个扑克牌类库(C#),想写一个客户端程序实现随机抓取5张扑克牌,判断是否是同花。
具体思路是这样的:
1、用类库生产一副52张不同花色和点数的牌(没有2王),并将其打乱。
2、进入一个5次的循环体来随机抽取5张不同的牌,并将其存入一个数组中。
3、判断数组中的牌是否同花,如是则打印,否则继续尝试;
程序中用到了Random类来生成随机数进行取牌,虽然每次的随机数都不相同(通过断点调试来观测变量的值),但是取到的牌总是一样。但是奇怪的是,如果当我在进入第一个for循环之前设置断点调试程序,则程序正常运行。反复检查程序还是不知所云。
下面是不正常的部分客户端程序:
static void Main(string[] args)
{
Deck playDeck = new Deck();
playDeck.Shuffle();
bool isFlush = true;
bool[] handCard = new bool[52]; // 用来标志52张牌中哪张已经被取过
Card[] myCard = new Card[5];
Random rdFive = new Random();
// 随机从52张牌中抽取5张牌
for (int i = 0; i < 5; i++)
{
bool foundCard = false; // foudCard变量用来表明是否找到了有效的牌
int destCardID = 0;
while (foundCard == false)
{
destCardID = rdFive.Next(52); // 随机产生一个目标牌的数字
if (handCard[destCardID] == false)
foundCard = true;
}
handCard[destCardID] = true;
myCard[i] = playDeck.GetCard(destCardID);
}
for (int m = 0; m < 5; m++)
{
Console.WriteLine("The card {0} is :" + myCard[m].rank + " of " + myCard[m].suit, m);
}
Console.ReadKey();
}
最后,真是山穷水尽疑无路,柳暗花明又一春。无意中查看MSDN中关于Random类的介绍,找到了解决方案。问题就是Random类引起的,修改Random rdFive = new Random();这句为: Random rdFive = new Random(DateTime.Now.Millisecond + 2);即可。
MSDN中这样解释Random的非默认Constructor:
如果应用程序需要不同的随机数序列,则使用不同的种子值重复调用此构造函数。一种产生唯一种子值的方法是使它与时间相关。例如,从系统时钟派生出种子值。
但是,如果应用程序在一个较快的计算机上运行,则该计算机的系统时钟可能没有时间在此构造函数的调用之间进行更改,Random 的不同实例的种子值可能相同。这种情况下,请应用一个算法来区分每个调用的种子值。
例如,以下的 C# 表达式使用按位求补运算来生成两个不同的种子值,即使系统时间值相同也可以。
Random rdm1 = new Random(unchecked((int)DateTime.Now.Ticks));
Random rdm2 = new Random(~unchecked((int)DateTime.Now.Ticks));
分析一下:由于我类库中打乱牌的函数也用到了Random类的默认构造器,而在测试程序中同样用Random类的默认构造器来产生的随机数,所以两次产生的随机数一样,造成了最后程序的bug。
平淡中结束我的第一个blog,准备倒纤割接~~~