Java - make a random permutation

由於要製作抽抽樂的翻牌App,因此在初始化時必須將數量內的(1 ~ N)的號碼牌亂數排列

,以便達到遊戲抽號碼的目的!在這邊將提到我自製的亂數排列方法及書本中提到的方法。

以前常用到的是取亂數值(1 ~ N),不過倒很少是將現有的數字陣列打亂掉順序。如:

num[0] = 1, num[1] = 2,....num[39] = 40.

亂數排列後為,num[0] = 10, num[1] = 12,....num[39] = 8.

作法一:

最沒有效率的做法,及最直覺的做法可能為:

假設產生第一個亂數 6 (1 ~ 40)

檢查陣列是否存在這個值,有則重新跑亂數,若無則放進第二個位置

因為陣列是空的,馬上存進陣列的第一個位置num[0] = 6

產生第二個亂數 ,此時就需要去與剛剛的位置一的數值做比較囉!!

....

以此進行下去,雖然電腦產生的速度很快,但很沒效率!

作法二:

自行想的方法,將rawNumber即1 ~ 40的數字放進ArrayList內,將產生的亂數排列放

進一個陣列內(結果),相關語法如下:

public void setRandomNumber(List<Integer> rawNumber, Integer[]rmdNumber){
    int r_num = 0;
    Random rmd = new Random();
    while(rawNumber.size() != 0){
       r_num = rmd.nextInt(rawNumber.size());
       rmdNumber[rawNumber.size()-1] = rawNumber.get(r_num);
       System.out.println(rmdNumber[rawNumber.size()-1]);
       rawNumber.remove(r_num);
    }
}

首先,若以rawNumber現有的size當作亂數的數字範圍,產生一個亂數來取List內的數值,即

將亂數當作一個index,rmd.nextInt(40) => 0 ~ 39的值

假設r_num = 10,那麼rawNumber.get(r_num) => 11,將此數值存進rmdNumber的最後一個位置。

再來就是將rawNumber index = 10 remove掉,下次就不會再取出11的數字!

以此進行下去,while只會跑40次即結束!

作法三:

此作法出自Java於演算法與資料結構之實習應用一書,作者為河西朝雄,為翻譯書

主要概念為,有一個陣列num[1] = 1,....., num[20] = 20

此時有一變數N = 20(陣列長度), 以此變數值來取亂數取(1 ~ 20)的數值

若亂數值取出為8,那麼將num[8]與num[20]的數值進行交換,即8與20交換

再來N = 19, 以此變數值來取亂數取(1 ~ 19)的數值

若亂數值取出還是為8,那麼將num[8]與num[19]的數值進行交換,即20與19交換

在以此類推進行交換

作法四:

最簡單的做法,可以利用Java Collections class內的shuffle method進行亂數排列,參數請

放置一個List。


綜合上面的四種作法,只能說作法三的演算法很高明,就現有的陣列做值的交換,而我的

方法需要一個List及一個陣列,真的還需要再加強orz...

留言