產生亂數的 GKRandomDistribution & GKShuffledDistribution

亂數(random number)是我們在開發 iOS App 時常用到的功能。尤其在製作遊戲或測驗 App 時,利用亂數才能讓電腦隨機做決定,比方以下人類的偉大發明,剪刀石頭布,利用亂數,電腦才能隨機出拳,不會傻傻地每次都出布。

從前我們習慣利用 function arc4random_uniform 生成亂數,例如以下例子:

let rps = ["rock", "paper", "scissors"]let index = Int(arc4random_uniform(UInt32(rps.count)))rps[index]

麻煩的地方在於我們要做很多轉換才能變成我們習慣使用的 Int,因為 arc4random_uniform 只愛 UInt32。

func arc4random_uniform(_ __upper_bound: UInt32) -> UInt32

幸運的,iOS 9 為了幫助我們製作遊戲推出的 GameplayKit framework,裡頭就有一個方便產生 Int 亂數的 function,讓我們看看以下例子:

import GameplayKitlet randomDistribution = GKRandomDistribution(lowestValue: 0, highestValue: 2)let number = randomDistribution.nextInt()
  1. 產生 GKRandomDistribution 物件, lowestValue 設定數字的最小值,highestValue 設定最大值。在此我們設定 0 & 2,因此 randomDistribution 之後將可產生 0 ~ 2 之間的亂數。
  2. 呼叫 GKRandomDistribution 物件的 function nextInt, 產生一個 Int 型別的亂數。在剛剛的例子裡,我們產生的數字將有三種可能,0,1,2。

開發 iOS App 時,我們也時常遇到這樣的情況,我們希望隨機決定 array 裡東西的順序,比方我們有三個女朋友,必須妥善地分配時間,每天跟不同人約會,不讓任何一個被冷落。或是像考題 App,題庫有一百題,隨機出十題測驗,這時候必須確保不會出到重覆的題目。

如果利用剛剛的 GKRandomDistribution,我們也是可以做到,只是可能會產生一樣的數字,造成悲劇,例如以下例子:

var girlFriends = ["小龍女", "黃蓉", "任盈盈"]let randomDistribution = GKRandomDistribution(lowestValue: 0, highestValue: girlFriends.count-1)for i in 0..<girlFriends.count {   let index  = randomDistribution.nextInt()   let name = girlFriends[index]   print("跟" + name + "一起吃法國菜")}

亂數的結果,黃蓉比較幸運,吃到兩次法國菜,但小龍女就慘了,只能在家吃泡麵。

為了解決這個問題,我們必須額外寫程式處理。不過如果透過 GKShuffledDistribution,我們即可輕鬆實現每天跟不同女朋友約會的心願,因為它十分公平,它將確保每一個數字出現的機率一樣。

如以下例子,我們的 for 迴圈跑三次,產生的隨機數字將平均分布,0, 1, 2 各一次,每個女朋友都可以幸福地吃到法國菜。

var girlFriends = ["小龍女", "黃蓉", "任盈盈"]let shuffledDistribution = GKShuffledDistribution(lowestValue: 0, highestValue: girlFriends.count - 1)for i in 0..<girlFriends.count {   let index  = shuffledDistribution.nextInt()   let name = girlFriends[index]   print("跟" + name + "一起吃法國菜")}

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com