使用GameplayKit生成随机数

时间:2016-03-20 14:31:41

标签: swift gameplay-kit

我正在使用swift和Gameplaykit学习随机数生成。在下面的代码中,是我初始化randomDist时生成的数字,它只是在我调用nextInt时从已生成的数字中提供样本,或者是当我调用nextInt()时生成的随机生成器lazy生成的?

onSuccess

1 个答案:

答案 0 :(得分:2)

请记住,GKRandomDistribution可以使用任何基础随机函数 - 也就是说,不仅仅是任何GameplayKit GKRandomSource类,而是任何实现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 - {{1范围。

  • highestValue对其中一个方法的每次调用都会对基础GKGaussianDistribution进行两次调用。这是因为有很多方法可以在给定两个均匀随机值的情况下生成高斯(又称正常)随机值 - 请参阅Box-Muller transform

  • nextUniform在你第一次向它求一个数字时会对底层的GKShuffledDistribution进行一堆调用,但如果没有它再次调用底层源,你可以再问它一次。这符合该分布的记录行为:它确保在再次重复相同的值之前耗尽其范围内的所有可能值。一种简单的方法是获取所有这些值,对其顺序进行洗牌,然后在每次调用时从洗牌池中提取一个值,直到它清空为止。