Random:随机值的处理:发牌游戏

伪随机数是以相同的概率从一组有限的数字中选取的。所选数字并不具有完全的随机性,因为它们是用一种确定的数学算法选择的,但是从实用的角度而言,其随机程度已足够了。Random 类的当前实现是基于 Donald E. Knuth 的减随机数生成器算法的,它提供我们产生随机的整数、双精度随机数和字节随机数。

以下是模拟投掷硬币两面的代码,需注意的是:Next产生的是从第一个参数开始,无限的趋向第二个参数,但不会产生第二个参数的值。

System.Random r = new Random();

for (int i = 0; i <= 10 - 1; i++)

{

System.Console.WriteLine(r.Next(1, 3));

}

运行的效果如图3.1.18:

clip_image002

图3.1.18

如果写成以下代码,

System.Console.WriteLine(r.Next(1, 2));

则产生出来的都是1了。

产生双精度的随机值其实是产生0到1之间的浮点数,以下代码给出了样例:

System.Random r = new Random();

for (int i = 0; i <= 10 - 1; i++)

{

System.Console.WriteLine(r.NextDouble());

}

运行的结果如图3.1.19:

clip_image004

图3.1.19

产生随机字节的方式有所不同。我们需要先定义一个字节数组,然后填充这个数组,代码演示如下:

System.Random r = new Random();

byte[] bytes = new Byte[10];

r.NextBytes(bytes);

for (int i = 0; i <= bytes.Length - 1; i++)

{

System.Console.WriteLine(bytes[i]);

}

运行效果如下图3.1.20:

clip_image006

图3.1.20

在实例化Random对象时,需要注意一个很重要的概念。在一般情况不要在循环中生成随机对象实例,以下代码会产生令你惊讶的效果。

for (int i = 0; i <= 10 - 1; i++)

{

System.Random r = new Random();

System.Console.WriteLine(r.Next(1, 10));

}

也许你认为是产生1-9之间的随机分部值,但事实是往往出现的是一连串相同的值,偶然会出现些不同的值列。如图3.1.21所示,所有数字均为6。

clip_image008

图3.1.21

这是为什么呢?随机数的生成是从种子值开始。如果反复使用同一个种子,就会生成相同的数字系列。产生不同序列的一种方法是使种子值与时间相关,从而对于 Random 的每个新实例,都会产生不同的系列。默认情况下,Random 类的无参数构造函数使用系统时钟生成其种子值。

因为处理器的速度很快,在一个循环中每次实例的时候系统时钟的值都一样,因此得到的数字系列也就一样。如果你一定要在循环中实例化随机对象,可用使用以下方式:

for (int i = 0; i <= 10 - 1; i++)

{

System.Random r = new Random(unchecked((int)(DateTime.Now.Ticks >> i)));

System.Console.WriteLine(r.Next(1, 10));

}

以下我们模拟一个随机发票的案例,首先我们定义一个存放54个string元素的数组,为该数组创建一副新的牌。

string[] pokers = new string[54];

for (int i = 0; i <= 13 - 1; i++)

{

string title = "";

switch (i + 1)

{

case 1:

title = "A";

break;

case 11:

title = "J";

break;

case 12:

title = "Q";

break;

case 13:

title = "K";

break;

default:

title = (i + 1).ToString();

break;

}

pokers[i] = string.Format("{0}{1}", (char)3, title);//红桃花色

pokers[i + 13] = string.Format("{0}{1}", (char)4, title);//方块花色

pokers[i + 26] = string.Format("{0}{1}", (char)5, title);//草花花色

pokers[i + 39] = string.Format("{0}{1}", (char)6, title);//黑桃花色

}

pokers[52] = string.Format("{0}", (char)1);//小鬼

pokers[53] = string.Format("{0}", (char)2);//大鬼

我们使用for循环排列输出数组中的元素。

for (int i = 0; i <= pokers.Length - 1; i++)

{

System.Console.Write("{0,-4}", pokers[i]);

//每13张牌输出一行

System.Console.Write("{0}", (i + 1) % 13 == 0 ? "\n" : "");

}

结果如图3.1.22:

clip_image010

图3.1.22

现在我们再定义三个string数组,分部标示玩家一、玩家二和玩家三。

string[] player1 = new string[18];

string[] player2 = new string[18];

string[] player3 = new string[18];

然后我们要把pokers数组中的值,随机的赋值到这三个数组中。我们的思路是,随机的定一个pokers中的位置,如果该位置中元素的值非空,则将元素中的值赋值给一个玩家,然后将这个位置上的元素赋值为null。

System.Random r = new Random();

for (int i = 0; i <= player1.Length - 1; i++)

{

int index = r.Next(0, pokers.Length);

while (pokers[index] == null)

{

index = r.Next(0, pokers.Length);

}

player1[i] = pokers[index];

pokers[index] = null;

index = r.Next(0, pokers.Length);

while (pokers[index] == null)

{

index = r.Next(0, pokers.Length);

}

player2[i] = pokers[index];

pokers[index] = null;

index = r.Next(0, pokers.Length);

while (pokers[index] == null)

{

index = r.Next(0, pokers.Length);

}

player3[i] = pokers[index];

pokers[index] = null;

}

以上代码根据我们的思路进行处理的结果,将牌随机的发给三个玩家了。然后我们输出看下,是否真的随机将牌发出了。

string[][] players = new string[][] { player1, player2, player3 };

for (int i = 0; i <= players.Length - 1;i++ )

{

for (int j = 0; j < +players[i].Length - 1;j++ )

{

System.Console.Write("{0,-4}", players[i][j]);

}

System.Console.WriteLine();

}

我们得到的结果如图3.1.23:

clip_image012

图3.1.23

原文地址:https://www.cnblogs.com/shyleoking/p/1535472.html