Search code examples
swift2arc4randomios8.4xcode6.4

Random Number Generator - arc4Random - Numbers can not be same


I have a random number generator using arc4Random and integers with three numbers, number1, number2, number3, in the range 1 - 3. A zero is not permitted. That part I have sorted due to a previous request on here, however, when the test button is pressed, I want to ensure the random numbers are not the same, i.e. if number1 displays 2, then number2 and number3 can not display 2 etc. I tried to do this longhand below, but there must be a simpler way of doing it. How would this be written in code as I have only been learning Xcode for about 6 weeks? Regards. Del Hinds

@IBAction func testButtonPressed(sender: UIButton) {

var str = "Hello, playground"

var number1 = Int(arc4random() % UInt32(4))

if number1 == 0 {
number1 = 1
}

var number2 = Int(arc4random() % UInt32(4))

if number2 == 0 {
if number1 == 1 {
    number2 = 2
}
else if number1 == 2 {
    number2 = 3
}
else if number1 == 3 {
    number2 = 1
}
number2 = 1
}

label2TextLabel.text = "\(number2)"

var number3 = Int(arc4random() % UInt32(4))

if number3 == 0 {
if number2 == 1 {
    number3 = 2
}
else if number2 == 2 {
    number3 = 3
}
else if number2 == 3 {
    number3 = 1
}
number3 = 1
}

label3TextLabel.text = "\(number3)"

Solution

  • If you are using ios9's GameplayKit, consider GKShuffledDistribution.
    Playground example:

      import GameplayKit
      let distribution = GKShuffledDistribution(lowestValue: 1, highestValue: 3)
      for i in 1...36 {  // Do 12 groups of 3
          print(distribution.nextInt(), appendnewline: false)
          if i % 3 == 0 { print(" ", appendnewline: false ) }
       }
    

    Sample result: 213 132 321 312 213 132 132 123 132 231 132 123


    Or consider GKRandomSource:

      import GameplayKit
      blocks : [AnyObject] = ["A","B","C"]
      for  _ in  1...5 {  // do 5 shuffles
         blocks = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(blocks)
         print(blocks)
       }
    

    Sample result: [A, C, B] [B, C, A] [B, A, C] [C, A, B] [B, A, C]

    Swift 3:

    GKShuffledDistribution - No real change, modified print usage.

      import GameplayKit
      let distribution = GKShuffledDistribution(lowestValue: 1, highestValue: 3)
      for i in 1...36 {
          print(distribution.nextInt(), terminator: "")
          if i % 3 == 0 { print(" ", terminator: "" ) }
      }
    

    GKRandomSource usage revision

    • Replaced AnyObject with Any
    • Now use arrayByShufflingObjects(in: blocks)

    gives

      import GameplayKit
      blocks : [Any] = ["A","B","C"]
      for  _ in  1...5 {  // do 5 shuffles
         blocks = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: blocks)
         print(blocks)
       }