在寫程式的時候常常會需要進行一些隨機的動作,來增加程式的娛樂性和複雜性。在Java程式語言中,可以使用Math類別的random方法或是Random物件來達到取得隨機數字的目的。取得隨機數字之後還需要撰寫一些程式來使用這個隨機數,這類程式常會頻繁地重複撰寫,十分麻煩。為了精簡程式,MagicRandom實作好了一些常用的隨機資料程式,只要使用一個靜態方法就可以完成大部分的事。



下載MagicRandom

https://github.com/magiclen/MagicRandom

MagicRandom的應用

以下列舉一些亂數的例子,並分別使用Math.random()、Random物件和MagicRandom來實作同樣的效果。MagicRandom相對其他兩者來說要容易使用得多。

限定範圍隨機產生一個整數(int)資料

如果要隨便在一定範圍內產生出一個整數(int)資料,程式實作方式如下。

Math.random()

Math.random()只會傳回一個0~1.0(包含0,但不包含1.0)的浮點數,所以還需要經過一些運算來使它可以產生某個範圍內的數。首先要將它乘以某個倍數來延展,擴充或縮減它可以隨機產生出來的數字區間大小,接著要加上某數讓它位移到正確的數字範圍內。

假設我們要從min~max整數範圍中隨機產生一個整數,共有「max - min + 1」個可能會出現的整數,程式可以這樣寫:

int i = (int) (Math.random() * (max - min + 1) + min);
Random物件

Random物件的init方法可以產生IntStream物件,使用IntStream物件的findFirst方法可以取得第一個隨機產生出來的整數。

Random random = new Random();
int i = random.ints(min, max + 1).findFirst().getAsInt();
MagicRandom

直接使用MagicRandom類別的randomInteger方法。

int i = MagicRandom.randomInteger(min, max);

不限範圍隨機產生一個短整數(short)資料

如果要隨便產生出一個短整數(short)資料,程式實作方式如下。

Math.random()
short s = (short) (Math.random() * (Short.MAX_VALUE - Short.MIN_VALUE + 1) + Short.MIN_VALUE);
Random物件
Random random = new Random();
short s = (short)random.ints(Short.MIN_VALUE, Short.MAX_VALUE + 1).findFirst().getAsInt();
MagicRandom

直接使用MagicRandom類別的randomShort方法。

short s = MagicRandom.randomShort();

限定範圍隨機產生一組可重複的整數(int)資料

Math.random()
int[] array = new int[length];
for (int a = 0; a < array.length; ++a) {
    array[a] = (int) (Math.random() * size + min);
}
Random物件

Random物件的init方法可以產生IntStream物件,使用IntStream物件的toArray方法可以將IntStream物件轉成int陣列物件。

int[] array = random.ints(length, min, max + 1).toArray();
MagicRandom

直接使用MagicRandom類別的randomIntegerArray方法。

int[] array = MagicRandom.randomIntegerArray(min, max, length, false);

限定範圍隨機產生一組不重複的整數(int)資料

這個例子好像有點難以理解,其實就像是樂透開獎。就以1~48號選出6個數字當作例子,程式實作方式如下。

Math.random()

由於需要抽選不重複的亂數,因此亂數在產生之後還需要判斷是否已經抽選過,若有抽選過就再重新抽選一次。

int[] array = new int[6];
for (int a = 0; a < array.length; ++a) {
    int i = 0;
    pick:
    while (i == 0) {
        i = (int) (Math.random() * 48 + 1);

        for (int b = 0; b < a; ++b) {
            if (array[b] == i) {
                i = 0;
                continue pick;
            }
        }
        array[a] = i;
    }
}
Random物件

Random物件的init方法可以產生IntStream物件,但不能直接使用IntStream物件的toArray方法來直接取得int陣列物件,因為元素可能會重複。所以也還需要判斷是否已經抽選過,若有抽選過就再重新抽選一次。

int[] array = new int[6];
for (int a = 0; a < array.length; ++a) {
    int i = 0;
    pick:
    while (i == 0) {
        i = random.ints(1, 19).findFirst().getAsInt();

        for (int b = 0; b < a; ++b) {
            if (array[b] == i) {
                i = 0;
                continue pick;
            }
        }
        array[a] = i;
    }
}
MagicRandom

直接使用MagicRandom類別的randomIntegerArray方法。

int[] array = MagicRandom.randomIntegerArray(min, max, length, true);

完全隨機抽取某陣列中的一個元素

Math.random()

先隨機選出索引值,再用索引值來取得元素。

int i = (int) (Math.random() * array.length);
int element = array[i];
Random物件

同樣也是先隨機選出索引值,再用索引值來取得元素。Random物件的nextInt(bound)方法可以隨機產生大於等於0且小於bound的整數。

int i = random.nextInt(array.length);
int element = array[i];
MagicRandom

直接使用MagicRandom類別的singlePickFromArray方法。

int element = MagicRandom.singlePickFromArray(array);

依權重隨機抽取某陣列中的一個元素

這個例子好像有點難以理解,其實就像是一般的抽獎活動,愈大獎抽到的機率愈少。假設有個抽獎活動共有5種獎項,愈前面的獎項價值愈高,所以抽到的機會也愈少。若第1種獎項抽到的機率為2%,第2種獎項抽到的機率為5%,第3種獎項抽到的機率為10%,第4種獎項抽到的機率為33%,第5種獎項抽到的機率為50%。若要從prizes這個字串陣列中抽出獎項:

String[] prizes = new String[]{"頭獎", "二獎", "三獎", "四獎", "五獎"};

程式實作方式如下。

Math.random()

從0~99抽出一個數字,判斷這個數字落在哪個範圍內來決定對應到的獎項。

String prize;
int i = (int) (Math.random() * 100);
if (i >= 0 && i <= 1) {
    prize = prizes[0];
} else if (i >= 2 && i <= 6) {
    prize = prizes[1];
} else if (i >= 7 && i <= 16) {
    prize = prizes[2];
} else if (i >= 17 && i <= 49) {
    prize = prizes[3];
} else {
    prize = prizes[4];
}
Random物件

同樣也是從0~99抽出一個數字,判斷這個數字落在哪個範圍內來決定對應到的獎項。

String prize;
int i = random.nextInt(100);
if (i >= 0 && i <= 1) {
    prize = prizes[0];
} else if (i >= 2 && i <= 6) {
    prize = prizes[1];
} else if (i >= 7 && i <= 16) {
    prize = prizes[2];
} else if (i >= 17 && i <= 49) {
    prize = prizes[3];
} else {
    prize = prizes[4];
}
MagicRandom

直接使用MagicRandom類別的singlePickFromArray方法,利用singlePickFromArray方法的參數來設定元素的權重。

String prize = MagicRandom.singlePickFromArray(prizes, 2, 5, 10, 33, 50);