How to generate a random number in Swift without repeating the previous random number?
my solution, i think its easy to understand
var nums = [0,1,2,3,4,5,6,7,8,9]
while nums.count > 0 {
// random key from array
let arrayKey = Int(arc4random_uniform(UInt32(nums.count)))
// your random number
let randNum = nums[arrayKey]
// make sure the number isnt repeated
nums.swapAt(arrayKey, nums.count-1)
nums.removeLast()
}
Store the previous generated number in a variable and compare the generated number to the previous number. If they match generate a new random number. Repeat the generation of new numbers until they don't match.
var previousNumber: UInt32? // used in randomNumber()
func randomNumber() -> UInt32 {
var randomNumber = arc4random_uniform(10)
while previousNumber == randomNumber {
randomNumber = arc4random_uniform(10)
}
previousNumber = randomNumber
return randomNumber
}
Update for Swift 5
Here is a nice trick to choose equally from the numbers that were not just previously chosen.
You have 10 numbers, but you only want to select from 9 numbers (0 through 9, but excluding the previous number). If you reduce your range by 1, you can select from 9 random numbers and then just replace a repeated number with the previous top number of the range. In this way, you only have to generate a single random number each time and you get uniformity.
This can be implemented as Int.random(in:excluding:)
where you pass the value you want to exclude
.
extension Int {
static func random(in range: ClosedRange<Int>, excluding x: Int) -> Int {
if range.contains(x) {
let r = Int.random(in: Range(uncheckedBounds: (range.lowerBound, range.upperBound)))
return r == x ? range.upperBound : r
} else {
return Int.random(in: range)
}
}
}
Example:
// Generate 30 numbers in the range 1...3 without repeating the
// previous number
var r = Int.random(in: 1...3)
for _ in 1...30 {
r = Int.random(in: 1...3, excluding: r)
print(r, terminator: " ")
}
print()
1 3 2 1 2 1 3 2 1 3 1 3 2 3 1 2 3 2 1 3 2 1 3 1 2 3 2 1 2 1 3 2 3 2 1 3 1 2 1 2
Previous Answer:
var previousNumber = arc4random_uniform(10) // seed the previous number
func randomNumber() -> UInt32 {
var randomNumber = arc4random_uniform(9) // generate 0...8
if randomNumber == previousNumber {
randomNumber = 9
}
previousNumber = randomNumber
return randomNumber
}