0

Looking to show a random word from an array after each action, but not have it repeat itself. So if "blue" was chosen, it will not reappear.

@IBAction func ShowWord(_ sender: Any) 
{
    let array = ["blue","red","purple", "gold", "yellow", "orange","light blue", "green", "pink", "white", "black"]


    let RandomWordGen = Int(arc4random_uniform(UInt32(array.count)))
    randomWord?.text = array[RandomWordGen]
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
Victor
  • 11
  • 2

1 Answers1

0

you can add an array of seen index like below and get the random values each time until all array items are fetched randomly. You will get the Idea from this and implement your own way to do it properly as you desire

 //The lists of items
let items = ["blue","red","purple", "gold", "yellow", "orange","light blue", "green", "pink", "white", "black"]

//array to hold the index we have already traversed
var seenIndex = [Int]()


func chooseRandom() -> String {

    if seenIndex.count == items.count { return "" } //we don't want to process if we have all items accounted for (Can handle this somewhere else)

    let index = Int(arc4random_uniform(UInt32(items.count))) //get the random index

    //check if this index is already seen by us
    if seenIndex.contains(index) {
        return chooseRandom() //repeat
    }

    //if not we get the element out and add that index to seen
    let requiredItem = items[index]
    seenIndex.append(index)
    return requiredItem
}

Another approach is listed below. This will also give you random/unique values but without using recursion

var items = ["blue","red","purple", "gold", "yellow", "orange","light blue", "green", "pink", "white", "black"]

//This will hold the count of items we have already displayed
var counter = 0

func ShowWord() {

    //we need to end if all the values have been selected
    guard counter != items.count else {
        print("All items have been selected randomly")
        return
    }

    //if some items are remaining
    let index = Int(arc4random_uniform(UInt32(items.count) - UInt32(counter)) + UInt32(counter))

    //set the value
    randomWord?.text = items[index]

    //printing for test
    debugPrint(items[index])

    //swap at the place, so that the array is changed and we can do next index from that index
    items.swapAt(index, counter)

    //increase the counter
    counter += 1

}

Yet another way would be to take advantage of swap function. The following things are happening here

1. We create a variable to know how many items we have selected/displayed from the list i.e var counter = 0

2. If we have selected all the elements then we simply return from the method

3. When you click the button to select a random value, we first get the random index in the range from 0 to array count

4. Set the random item to randomWord i.e display or do what is intended

5. now we swap the element e.g if your array was ["red", "green", "blue"] and the index was 2 we swap "red" and "blue"

6. Increase the counter

7. when we repeat the process the new array will be ["blue", "green", "red"]

8. The index will be selected between _counter_ to _Array Count_

kathayatnk
  • 975
  • 1
  • 7
  • 9
  • There's little reason to make this recursive. Use a loop. Better yet, simply randomize the array once at the start and just iterate the randomized array. – rmaddy Aug 21 '18 at 03:01
  • @rmaddy: you are absolutely correct. This is just and example on how one would approach the case – kathayatnk Aug 21 '18 at 03:07
  • @rmaddy what would be the best way to do that in this case? Thanks :) – Victor Aug 21 '18 at 04:14
  • @Victor: I've also added another solution to this problem and described what is going in there – kathayatnk Aug 21 '18 at 05:01
  • @kathayatnk thanks so much! For some reason it's not printing properly, not sure if we're missing to it. Is there another simpler way to go about without recursives? Thanks again :) – Victor Aug 22 '18 at 03:21
  • @Victor : Which one are you using? – kathayatnk Aug 22 '18 at 03:23
  • @kathayatnk I'm trying out the recursive function, and at the end adding randomWord?.text = items[index] and get an error: "Cannot convert value of type '(Any) -> Int' to expected argument type '(UnboundedRange_)->() – Victor Aug 22 '18 at 03:45
  • don't set you label inside the recursive function. Rather call the function in your button click method, like `let randomString = chooseRandom ()` and then set the value to `randomWord?.text = randomString` – kathayatnk Aug 22 '18 at 03:52
  • @kathayatnk Thanks so much for your help. It's great to have strangers help out as I'm still new to this. The recursive function runs fine, it just doesn't randomize it that much. – Victor Aug 23 '18 at 04:37