Unity3D 学习日记(四)生成不重复的随机数

2015年做项目的需要用到这样的功能,不过当时太忙了没时间写博客,这个刚好这几天都有时间补回这个日记吧!

在这里要感谢lynnlin1122写的博客文章,《用C#生成不重复的随机数》大家有空去看看这篇文章,原文地址:点击打开链接


如果学过计算机理论就会知道在计算机里面是没有真正的随机数,我们使用到的System.Random是一个伪随机数,我还记以前大学里面有一本书后面几页附着计算机的随机表,也就是可以理解成。那么计算机怎样生成随机数呢?这个就要我们程序员去利用计算机的伪随机数通过算法尽可能达到真正的随机数的效果,理论上来说只要知道别人随机算法就可以准确预测随机数的出现,这些预测到底用来做啥不用我说你们都知道的啦~

那么使用Random如果在有范围的随机上就会出现,重复出现的数字特别多,但是我们只希望这些随机数只在范围上随机而且不出现重复的问题,这里我们就要对其进行随机算法的限定,lynnlin1122博客上写很完整大体上有3中算法可以使用,一个是下标索引随机,一个哈希随机,以及递归随机的方法。

下表索引我就直接截lynnlin1122说明吧!如图所示:


可能说的比较抽象,其实就是申请两个数组,然后一个为空数组A1,另一个就设定好你需要的随机数范围A2,然后通过随机下标进行随机,然后把A2下标里面的数字放到空数组A1里面,然后让该位置的数用A2的最后的一个数来代替,然后减小索引范围。接下来我们用代码实现这个效果,代码如下:

/// <summary>
    /// 索引法随机
    /// </summary>
    /// <param name="minValue"></param>
    /// <param name="maxValue"></param>
    /// <returns></returns>
    public static int[] GetIndexRandomNum(int minValue, int maxValue)
    {
        System.Random random = new System.Random();
        int sum = Mathf.Abs(maxValue - minValue);//计算数组范围
        int site = sum;//设置索引范围
        int[] index = new int[sum];
        int[] result = new int[sum];
        int temp = 0;
        for (int i = minValue; i < maxValue; i++)
        {
            index[temp] = i;
            temp++;
        }
        for (int i = 0; i < sum; i++)
        {
            int id = random.Next(0, site - 1);
            result[i] = index[id];
            index[id] = index[site - 1];//因id随机到的数已经获取到了,用最后的一个数来替换它
            site --;//缩小索引范围
        }
        return result;
    }
其实方法并不难,只要理清楚其实就是一个很简单的随机方法。

那么我们继续将下一个方法,哈希表随机通过哈希表的查找,如果随机的数字重复了就不加入哈希表里面,当哈希表的长度达到需要要的长度后,这表示随机完成了。这里Dictionary方法和哈希表的都一样所以这里就放出哈希表随机,代码如下:

 /// <summary>
    /// 
    /// </summary>
    /// <param name="num"></param>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static Hashtable GetHashtableRandomNum(int num, int min, int max)
    {
        System.Random random = new System.Random();
        Hashtable hashtable = new Hashtable();
        for (int i = 0; hashtable.Count < num; i++)
        {
            int nValue = random.Next(min, max);

            if (!hashtable.ContainsValue(nValue) && nValue != min)
            {
                hashtable.Add(i, nValue);
            }
        }

        return hashtable;
    }
那么最后的算法是效率较低的,递归方法来实现随机,这个算法如果随机范围速度还是挺快的,不过越到后面速度就会呈指数倍下降,所以范围大的时候建议别用递归随机。递归用在查找是否有重复随机数,这个我就不详细讲了,代码如下:

  /// <summary>
    /// 获取随机且不重复数组
    /// </summary>
    /// <param name="arrNum"></param>
    /// <param name="minValue"></param>
    /// <param name="maxValue"></param>
    /// <returns></returns>
    public static int[] GetRecursiveRandomNum(int[] arrnum, int min, int max)
    {
        System.Random random = new System.Random(unchecked((int)System.DateTime.Now.Ticks));

        for (int i = 0; i < arrnum.Length; i++)
        {
            int tmp = random.Next(min, max);
            arrnum[i] = GetDetermine(arrnum, tmp, min, max, random);
        }
        return arrnum;
    }

    /// <summary>
    /// 递归查找
    /// </summary>
    /// <param name="arrnum"></param>
    /// <param name="tmp"></param>
    /// <param name="minValue"></param>
    /// <param name="maxValue"></param>
    /// <param name="ra"></param>
    /// <returns></returns>
    private static int GetDetermine(int[] arrnum, int tmp, int minValue, int maxValue, System.Random ra)
    {
        int i = 0;
        while (i <= arrnum.Length - 1)
        {
            if (arrnum[i] == tmp) //利用循环判断是否有重复
            {
                tmp = ra.Next(minValue, maxValue); //重新随机获取。
                GetDetermine(arrnum, tmp, minValue, maxValue, ra);//递归:如果取出来的数字和已取得的数字有重复就重新随机获取。
            }
            i++;
        }
        return tmp;
    }

我把代码都改成了静态函数,方便调用~

unity3D学习之路任重道远啊,记录点滴记录成长~

                                                                                                                                                                                                                                             ---Begonia

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值