zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    JAVA回调机制(转)
    单例模式之饿汉懒汉模式
    TOMCAT目录结构
    Hibernate Component的用法
    【转】单例模式完全剖析
    EhCache使用详解
    【转】jar包详解和METAINF作用
    使用 Spring 2.5 注释驱动的 IoC 功能
    vc中,制作在任务栏隐藏图标的mfc程序
    打开网页,打开外部应用程序
  • 原文地址:https://www.cnblogs.com/shyleoking/p/1535472.html
Copyright © 2011-2022 走看看