1

I am working on my first project where I am trying to create a random color to a UILabel (when a button is pressed) that does not repeat itself twice in a row. I have read many questions and found codes that generates random numbers that does not appear twice in a row, however, when I "link" that random number to a UIColor and "link" that UIColor to a label the code no longer works. This code has no errors but it allows the same color to appear twice;

@IBOutlet var HelloWorld: UILabel!
@IBOutlet var MyButton: UIButton!

@IBAction func MyButton(sender: AnyObject) {
let randomNumber2 = Int(arc4random_uniform(5))

    if randomNumber2 == 0 {
        HelloWorld.textColor = UIColor.redColor()
    }
    else if randomNumber2 == 1 {
        HelloWorld.textColor = UIColor.blueColor()
    }
    else if randomNumber2 == 2 {
        HelloWorld.textColor = UIColor.yellowColor()
    }
    else if randomNumber2 == 3 {
        HelloWorld.textColor = UIColor.orangeColor()
    }
    else if randomNumber2 == 4 {
        HelloWorld.textColor = UIColor.blueColor()
    }

Does anyone know how to generate a random color to a label that does not appear twice in a row?

R.S
  • 253
  • 2
  • 7
  • 1
    Take a look [here](http://stackoverflow.com/a/34466012/2442804). It is quite similar, create an array of colors and select from that array without duplicates – luk2302 Jan 02 '16 at 16:52
  • 1
    You should use a switch case instead of all those if conditions – Leo Dabus Jan 02 '16 at 16:53
  • var randomNumber = Int(arc4random_uniform(5)) – Leo Dabus Jan 02 '16 at 16:55
  • You will need to do the same inside the while loop. Btw chose a different name for your var other than the same method name – Leo Dabus Jan 02 '16 at 17:00
  • change your method return type to `UIColor`: `func getRandomColor() -> UIColor {...` – luk2302 Jan 02 '16 at 17:13
  • @luk2302 I changed the method return type to UIColor:... But now I am receiving an error saying: "Labels are only valid on loops, if, and switch statements" There is a lot of new stuff in my code so I am a bit confused, sorry.. – R.S Jan 02 '16 at 17:29
  • @R.S add that code to your question, as an update. Have you seen my answer? – R Menke Jan 02 '16 at 17:44
  • remove `UIColor :` Your version of the function is completely scrambled. It will not work – R Menke Jan 02 '16 at 17:56

2 Answers2

0

If you can't limit the outcome from the random function, store the result, and check that the random is unique by checking that the array of generated randoms doesn't contain the new random.

struct UniqueRandomGenerator<T:Equatable> {

    var usedRandoms : [T] = []

    mutating func newRandom(randomGenerator:() -> T) -> T {

        var random = randomGenerator()
        while usedRandoms.contains(random) {
            random = randomGenerator()
        }
        usedRandoms.append(random)
        return random
    }
}

func randomGenerator() -> Float {
    return Float(arc4random())
}

var uniqueRandomGen = UniqueRandomGenerator<Float>() // not so elegant
uniqueRandomGen.newRandom(randomGenerator)

If you can limit the outcome (known possible values) you can use the function below.

struct RandomSet<T:Equatable> {

    var set : [T] = []
    var unusedSet : [T] = []

    init(set:[T]) {
        self.set = set
        self.unusedSet = set
    }

    mutating func uniqueRandom() -> T {
        if (unusedSet.count == 0) {
            unusedSet = set
        }
        let randomNumber = Int(arc4random_uniform(UInt32(unusedSet.count)))
        return unusedSet.removeAtIndex(randomNumber)
    }
}

var randomColors = RandomSet(set: [UIColor.redColor(),UIColor.blueColor(),UIColor.yellowColor(),UIColor.orangeColor(),UIColor.greenColor()])
randomColors.uniqueRandom() // a random color
R Menke
  • 8,183
  • 4
  • 35
  • 63
  • How can I use this? the "struct UniqueRandomSet" is not possible to use in the ViewController, any button action or timer. – R.S Jan 02 '16 at 20:15
  • @R.S just put the `struct` definition in a separate file. Use an instance of the struct in your view. – R Menke Jan 02 '16 at 20:20
  • @R.S try it in a playground first too see what it does. – R Menke Jan 02 '16 at 20:21
0

You can use this Singleton class

class ColorGenerator {
    static let sharedInstance = ColorGenerator()
    private var last: UIColor
    private var colors: [UIColor] = [.redColor(), .blueColor(), .yellowColor(), .orangeColor(), .greenColor()]

    private init() {
        let random = Int(arc4random_uniform(UInt32(colors.count)))
        self.last = colors[random]
        colors.removeAtIndex(random)
    }

    func next() -> UIColor {
        let random = Int(arc4random_uniform(UInt32(colors.count)))
        swap(&colors[random], &last)
        return last
    }
}

The usage is pretty straightforward

Step 1

Create a new file in your project ColorGenerator.swift and paste the code above into it.

Step 2

Anywhere in your code just write

ColorGenerator.sharedInstance.next()

to get a new random UIColor.

enter image description here

That's it.

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • Wonderful, it works perfectly! - You forgot however to write that you need to "import UIKit" for the code to work. Else, great job. – R.S Jan 05 '16 at 14:49