5

I'm able to pick a random number for my items in my game but is it possible to pick a random number between 2 numbers?

so instead of

let number = (arc4random_uniform(100))

I would like something like this:

let number = (arc4random_uniform(10...20))

or something like that? Now if I get a weapon drop it can be everything in my list. This way I could make it so that only the first few would have a drop for a specific monster or at higher level they would drop better weapons and not the low levels anymore.

Marcy
  • 4,611
  • 2
  • 34
  • 52
Kristof.V
  • 143
  • 1
  • 7

1 Answers1

10

Xcode 11 • Swift 5.1 or later

extension Range where Bound: FixedWidthInteger {
    var random: Bound { .random(in: self) }
    func random(_ n: Int) -> [Bound] { (0..<n).map { _ in random } }
}

extension ClosedRange where Bound: FixedWidthInteger  {
    var random: Bound { .random(in: self) }
    func random(_ n: Int) -> [Bound] { (0..<n).map { _ in random } }
}

Note: For older Swift versions check the edit history

Usage:

(10...20).random    // 16
(0...1).random(10)  // [0, 1, 0, 0, 1, 1, 1, 1, 1, 0]
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Do not use `hashValue` here – the value that it returns is an implementation detail and therefore subject to change (it just *happens* to return an `Int` of the same value in this case). Always returning 0 would be a valid (albeit ineffective) `hashValue` implementation, but would completely break your random logic. A more reliable way would be to go via `IntMax` instead – for example `Int(lowerBound.toIntMax()) + Int(arc4random_uniform(UInt32((upperBound - lowerBound + 1).toIntMax())))`. – Hamish Dec 29 '16 at 11:40
  • Also IMO, a method would be more appropriate than a computed property here, as invoking it repeatedly can yield different results (not something I would expect a computed property to do). – Hamish Dec 29 '16 at 11:41
  • @Hamish Thanks for the input. I agree that toIntMax() is the appropriate approach but I prefer it as a computed property. I use computed properties for everything and I never expect it to be static. – Leo Dabus Dec 31 '16 at 04:45
  • This code gives the illusion that it works with arbitrary integers. But it crashes if `upperBound - lowerBound + 1` exceeds the UInt32 range. Compare http://stackoverflow.com/questions/31391577/how-can-i-generate-large-ranged-random-numbers-in-swift for some code which works with "large" integers. – Martin R Feb 28 '17 at 20:15
  • Btw, using `reduce` as a `map` replacement is highly ineffective. – Martin R Feb 28 '17 at 20:21