请记住,aGKRandomDistribution
可以使用任何底层随机化器——也就是说,不仅仅是任何 GameplayKitGKRandomSource
类,而是任何实现该GKRandom
协议的类。因此,您可以通过实现自己的随机源并查看其方法被调用的方式/时间来自己回答这个问题。
class LoggingRandomSource: GKRandom {
let source = GKARC4RandomSource()
@objc func nextInt() -> Int {
let num = source.nextInt()
print("nextInt: \(num)")
return num
}
@objc func nextIntWithUpperBound(upperBound: Int) -> Int {
let num = source.nextIntWithUpperBound(upperBound)
print("nextIntWithUpperBound: \(num)")
return num
}
@objc func nextUniform() -> Float {
let num = source.nextUniform()
print("nextUniform: \(num)")
return num
}
@objc func nextBool() -> Bool {
let flip = source.nextBool()
print("nextBool: \(flip)")
return flip
}
}
let rand = LoggingRandomSource()
let randomDist = GKRandomDistribution(randomSource: rand, lowestValue: 50, highestValue: 100)
randomDist.nextInt()
继续探索这个技巧,你会注意到一些关于随机分布类的事情:
GKRandomDistribution
nextIntWithUpperBound
每次调用其方法之一时调用底层随机源一次。这是有道理的,因为nextIntWithUpperBound
假设底层源是统一的,所以GKRandomDistribution
需要做的就是将统一的 int 映射到它的lowestValue
-highestValue
范围。
GKGaussianDistribution
nextUniform
每次调用其方法之一时,都会对底层进行两次调用。这是因为在给定两个均匀随机值的情况下,有很多方法可以生成高斯(又名正常)随机值——请参阅Box-Muller 变换。
GKShuffledDistribution
在您第一次向底层nextIntWithUpperBound
索要一个数字时,会向底层进行大量调用,但您可以在不再次调用底层源的情况下要求它进行更多次调用。这符合该分布的记录行为:它确保在再次重复相同的值之前用尽其范围内的所有可能值。一种简单的方法是获取所有这些值,打乱它们的顺序,然后在每次调用时从打乱的池中提取一个值,直到它清空。