Rappelez-vous qu'un GKRandomDistribution
peut utiliser toute sous-jacente randomizer - qui est, non seulement l'une des classes de GameplayKit GKRandomSource
, mais toute classe qui implémente le protocole GKRandom
. Vous pouvez donc répondre à cette question en implémentant votre propre source aléatoire et en voyant comment/quand ses méthodes sont appelées.
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()
continuer à explorer avec cette astuce, vous remarquerez quelques petites choses sur les classes de distribution au hasard:
GKRandomDistribution
appels nextIntWithUpperBound
la source aléatoire sous-jacente une fois pour chaque appel à l'une de ses méthodes. Cela est logique, car la source sous-jacente nextIntWithUpperBound
est supposée être uniforme, donc tout ce que GKRandomDistribution
doit faire est de mapper cet entier uniforme à sa plage lowestValue
- highestValue
.
GKGaussianDistribution
effectue deux appels au sous-jacente nextUniform
pour chaque appel à l'une de ses méthodes. C'est parce qu'il y a beaucoup de façons de générer une valeur aléatoire gaussienne (alias normal) donnée par deux valeurs aléatoires uniformes - voir le Box-Muller transform.
GKShuffledDistribution
nextIntWithUpperBound
la première fois que vous lui demandez un numéro, mais vous pouvez le demander pour beaucoup plus sans qu'il appelle à nouveau la source sous-jacente. Cela correspond au comportement documenté de cette distribution: elle veille à épuiser toutes les valeurs possibles dans sa plage avant de répéter la même chose. Un moyen facile de le faire est de prendre toutes ces valeurs, de mélanger leur ordre, puis d'extraire une valeur du pool mélangé à chaque appel jusqu'à ce qu'il se vide.