Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

How Do I Prevent Same Random Color and Random Fact From Showing Consecutively in Swift?

I have completed the Build a Simple iPhone App with Swift course, and now I would like to add a feature to it. I want to have functionality that prevents the same background color and same interesting fact from showing consecutively. I have been working on this, but I just cannot seem to figure out the correct way. Any help would be much appreciated!

//
//  ColorWheel.swift
//  FunFacts
//
//  Created by Nick Kohrn on 9/18/14.
//  Copyright (c) 2014 Nick Kohrn. All rights reserved.
//

import Foundation
import UIKit

struct ColorWheel {
    let colorsArray = [
        UIColor(red: 90/255.0, green: 187/255.0, blue: 181/255.0, alpha: 1.0), //teal color
        UIColor(red: 222/255.0, green: 171/255.0, blue: 66/255.0, alpha: 1.0), //yellow color
        UIColor(red: 223/255.0, green: 86/255.0, blue: 94/255.0, alpha: 1.0), //red color
        UIColor(red: 239/255.0, green: 130/255.0, blue: 100/255.0, alpha: 1.0), //orange color
        UIColor(red: 77/255.0, green: 75/255.0, blue: 82/255.0, alpha: 1.0), //dark color
        UIColor(red: 105/255.0, green: 94/255.0, blue: 133/255.0, alpha: 1.0), //purple color
        UIColor(red: 85/255.0, green: 176/255.0, blue: 112/255.0, alpha: 1.0), //green color
    ]

    func randomColor() -> UIColor {
        var unsignedArrayCount = UInt32(colorsArray.count)
        var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)
        var randomNumber = Int(unsignedRandomNumber)
        return colorsArray[randomNumber]
    }
}
//
//  FactBook.swift
//  FunFacts
//
//  Created by Nick Kohrn on 9/18/14.
//  Copyright (c) 2014 Nick Kohrn. All rights reserved.
//

import Foundation

struct FactBook {
    let factsArray = [
        "Ants stretch when they wake up in the morning.",
        "Ostriches can run faster than horses.",
        "Olympic gold medals are actually made mostly of silver.",
        "You are born with 300 bones; by the time you are an adult you will have 206.",
        "It takes about 8 minutes for light from the Sun to reach Earth.",
        "Some bamboo plants can grow almost a meter in just one day.",
        "The state of Florida is bigger than England.",
        "Some penguins can leap 2-3 meters out of the water.",
        "On average, it takes 66 days to form a new habit.",
        "Mammoths still walked the earth when the Great Pyramid was being built." ]

    func randomFact() -> String {
        var unsignedArrayCount = UInt32(factsArray.count)
        var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)
        var randomNumber = Int(unsignedRandomNumber)

        return factsArray[randomNumber]
    }
}
//
//  ViewController.swift
//  FunFacts
//
//  Created by Nick Kohrn on 9/18/14.
//  Copyright (c) 2014 Nick Kohrn. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var funFactLabel: UILabel!
    @IBOutlet weak var funFactButton: UIButton!

    let factBook = FactBook()
    let colorWheel = ColorWheel()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        funFactLabel.text = factBook.randomFact()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func showFunFact() {
        var randomColor = colorWheel.randomColor()
        var randomFact = factBook.randomFact()
        view.backgroundColor = randomColor
        funFactButton.tintColor = randomColor
        funFactLabel.text = randomFact
    }
}

5 Answers

use a variable to store the value of the previousRandomIndex. then in your randomFact/color function use a do while loop to generate the number. in the while condition compare the randomNumber that was generated to the previous randomNumber. if you get the same twice in a row it will keep generating a number until its different.

import Foundation

struct FactBook {

    //this will hold the random index
    var previousRandomIndex = 0
    let factsArray = [
        "Ants stretch when they wake up in the morning.",
        "Ostriches can run faster than horses.",
        "Olympic gold medals are actually made mostly of silver.",
        "You are born with 300 bones; by the time you are an adult you will have 206.",
        "It takes about 8 minutes for light from the Sun to reach Earth.",
        "Some bamboo plants can grow almost a meter in just one day.",
        "The state of Florida is bigger than England.",
        "Some penguins can leap 2-3 meters out of the water.",
        "On average, it takes 66 days to form a new habit.",
        "Mammoths still walked the earth when the Great Pyramid was being built." ]

    func randomFact() -> String {
        var unsignedArrayCount = UInt32(factsArray.count)
        var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)

        //this will run at least once. it will keep generating a random number until you get one thats not the same as the previous
        do {
        var randomNumber = Int(unsignedRandomNumber)
       } while randomNumber == previousRandomIndex

        previousRandomIndex = randomNumer
        return factsArray[randomNumber]
    }
}

Stone,

Thank you so much! I was using a variable to store the index, however, I was using if-statements rather than a loop. No wonder I was generating the same colors/facts consecutively.

Thanks again, sir!

no problem

When I go to assign ``` previousRandomIndex = randomNumber

I keep getting an error that says "Cannot assign to 'previousRandomIndex' in 'self'". I am not quite sure how to fix this.

I tried implementing the above code and am also seeing that error. Stone Preston, how can this be resolved?

are you sure you declared previousRandomIndex as a variable and not a constant?

So when I set up my code similarly to your first solutions I got the three errors that I added as comments below.

import Foundation

struct FactBook {

    var previousRandomIndex = 0
    let factsArray = [
        "Ants stretch when they wake up in the morning.",
        "Ostriches can run faster than horses.",
        "Olympic gold medals are actually made mostly of silver.",
        "You are born with 300 bones; by the time you are an adult you will have 206.",
        "It takes about 8 minutes for light from the Sun to reach Earth.",
        "Some bamboo plants can grow almost a meter in just one day.",
        "The state of Florida is bigger than England.",
        "Some penguins can leap 2-3 meters out of the water.",
        "On average, it takes 66 days to form a new habit.",
        "Mammoths still walked the earth when the Great Pyramid was being built."
    ]

    func randomFact() -> String {
        var unsignedArrayCount = UInt32(factsArray.count)
        var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)

        do {
            var randomNumber = Int(unsignedRandomNumber)
        } while randomNumber == previousRandomIndex   //use of unresolved indentifier 'randomNumber' 

        previousRandomIndex = randomNumber  //use of unresolved indentifier 'randomNumber' 
        return factsArray[randomNumber]  //use of unresolved indentifier 'randomNumber' 
    }
}

Then I tried declaring random number outside of the do while loop to change the scope of the variable, and got the same error as Nick.

    func randomFact() -> String {
        var randomNumber = 0
        var unsignedArrayCount = UInt32(factsArray.count)
        var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)

        do {
            randomNumber = Int(unsignedRandomNumber)
        } while randomNumber == previousRandomIndex

        previousRandomIndex = randomNumber //Cannot assign to "previousRandomIndex' in 'self'
        return factsArray[randomNumber]
    }

Thanks for your help Stone!

To solve your error I'd try to move the

var previousRandomIndex = 0

to above your Struct declaration and I'd also put the randomNumber declaration there too

i.e.

var previousRandomIndex = 0 var randomNumber = 0

struct FactBook {

I hope this helps, I'm just learning too, but I thought I'd add this

I also think that the var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount) should be put into your array to ensure it doesn't get stuck in a never ending loop?

i.e. do { var unsignedRandomNumber = arc4random_uniform(unsignnedNumberOfJokes) randomNumber = Int(unsignedRandomNumber) } while randomNumber == previousRandomIndex

Let me know if that works for you :)

Can someone post the solution without any errors?