张银的博客


Eat to live, but do not live to eat.

导航

随机数 生成时间要平均

Posted on 2010-11-04 01:28  张银  阅读(727)  评论(0编辑  收藏  举报

  生成随机数组,在很多领域的开发中都会用到,例如游戏开发。随即数组生成的时间如果是固定的,那么执行效率就会比较高;如果不固定,就可能会影响程序的运行速度。

  题:生成20个随机数字,该组数字包含2组1~10之间的整数,即包含2个1、2个2,依此类推,但是每个数字的位置是随机的。

 

  答案A:

int num[] = new int[20];
int index = 0; //数组下标
int ranNum; //随机数字
int time = 0; //数字已出现次数
Random r = new Random();

while(true){
ranNum
= r.nextInt(9)+1; //随机1~10之间的数字

//统计数字ranNum已出现次数
time=0
for(int i = 0;i < index; i ++){
if(num[i] == ranNum){
time
++;
}
}

//如果未出现2次
if (time !=2) {
num[index]
= ranNum;
index
++; //继续赋值下一个
}
if(index == num.length) { //全部赋值
break;
}

}

 

  答案B:

//生成2组1~10之间的规则数字
int num[] = new int[20];
for(int i = 0; i < num.length; i++){
num[i]
= i/2 + 1;
}

//随机打乱数字顺序
Random r = new Random();
int times = 30; //两两交换次数
int ranIndex; //随机下标
int temp; //交换变量
int cIndex; //当前下标

for (int i = 0; i < times; i++){
ranIndex
= r.nextInt(20); //[0~20]之间的随机数,作为下标

//和下标i % 20 交换
cIndex = i % 20 ;
if(cIndex != ranIndex ){
temp
= num[cIndex];
num[cIndex]
= num[ranIndex];
num[ranIndex]
= temp;
}
}

正确答案:B

答案分析

  答案A使用的是自然思维,即随机生成一个1~10之间的数字,然后判断该数字是否在数组中出现2次,如果未出现2次,则将该数字赋值到数组中,接着随机出现下一个数字。使用这种方式,虽然可以满足要求的功能,但是在程序的执行效率上很不稳定,每次随机过程所需的时间差异很大,甚至有可能卡死。如果程序中生成较多的随机数字,那么就不能用这种方法。

  答案B采用的是一种变通的方法,先生成一组规则的数字,然后随机打乱该组数字的顺序。使用这种思路,程序的执行效率很稳定,而且实现起来比较简单。具体步骤如如下:生成两组1~10之间的整数,按照1,1,2,2,……的顺序依次赋值到数组中,这样就得到一个规则的数组num。

  接着使用两两交换的方式随机交换数组中数字的位置,生成一个随机数字,作为一个数组交换时的下标,然后和数组当前的下标进行交换,这样经过一定次数的交换以后,数组中的数字位置就变得随机了。每次交换消耗的时间基本固定,代码的执行效率很稳定,生成的速度也很高效。

 

 

扑克洗牌中的随机数组

  高效生成随即数组,这种算法在实际的程序开发中大量被使用,特别是在游戏中被广泛使用,例如扑克牌游戏中的洗牌,网游中的随机掉装备等。下面,外面来看实际程序卡发中是如何高效生成随机数组的。

  代码的目的是要实现扑克游戏洗牌的功能,根据扑克牌的特点(每副牌包含54张不同的牌),将扑克牌中的每张牌依次对应编号成0~53之间的所有整数的数组,而洗牌就是将这样一个规则的数组变成一个随机数组。代码如下:

//生成一副牌,编号为0~53
int poker[] = new int[54];
for (int i = 0; i < poker.length; i++) {
poker[i]
= i;
}

//洗牌
Random r = new Random();
int times = 54; //两两交换次数
int ranIndex; //随机下标
int temp; //交换数字
int cIndex; //当前下标

for (int i = 0; i < times; i++) {
ranIndex
= r.nextInt(54) ; //[0~53]之间的随机数
}

//和下标i%54交换
cIndex = i % 54;
if (cIndex != ranIndex) {
temp
= poker[cIndex];
poker[cIndex]
= poker[ranIndex];
poker[ranIndex]
= temp;
}

点评:在该代码中,先生成一个包含[0~53]之间所有整数的规则数组poker,然后再使用两两交换的方式对该数组中的元素交换54次。