Search code examples
xcodeswiftexc-bad-instruction

Random number generate issue in swift language - EXC_BAD_INSTRUCTION


I tried to generate an array with strings in random order, but always got the error "Thread1:EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)" at the end of function randomPile. Below is my code:

import UIKit

class RandomView: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    var cardOrder = ["HeartSix","HeartNine", "ClubQueen", "SpadeKing" ]

    // cannot randomlize due to the lanuage drawbacks.
    cardOrder = randomPile(cardOrder)

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

// random the order of the original card pile
func randomPile(arrayPile: String[]) -> String[] {
    var arry = arrayPile
    for( var i = arry.count-1; i > 0; --i){
        var r = Int(arc4random())%(i+1)
        var a = arry[r]
        arry[r] = arry[i]
        arry[i] = a

    }
    return arry
}    
}

Solution

  • Also not an answer, because I can also run in playground and so I don't know where your problem is coming in. However, there's no need to create a new reference to the array and return it. I also implemented a Fisher-Yates shuffle variant which is geared towards an integer PRNG that excludes its upper bound, as arc4random_uniform does:

    func randomPile(myArray: String[]) -> Void {
        for i in 0..(myArray.count - 1) {
            let j = Int(arc4random_uniform(UInt32(myArray.count - i))) + i
            let tmp = myArray[i]
            myArray[i] = myArray[j]
            myArray[j] = tmp
        }
    }
    
    let cardOrder: String[] = ["HeartSix","HeartNine", "ClubQueen", "SpadeKing" ]
    println(cardOrder)
    randomPile(cardOrder)
    println(cardOrder)
    

    After invoking this on your array, it's shuffled, no need for reassignment to cardOrder.

    Addendum - I just checked, and since cardOrder doesn't appear again on the left of an assignment it can be declared with let.

    You can also make the shuffle capability generic, so why not?

    func shuffle<T>(myArray: T[]) -> Void {
        for i in 0..(myArray.count - 1) {
            let j = Int(arc4random_uniform(UInt32(myArray.count - i))) + i
            let tmp:T = myArray[i]
            myArray[i] = myArray[j]
            myArray[j] = tmp
        }
    }
    
    let cardOrder: String[] = ["HeartSix","HeartNine", "ClubQueen", "SpadeKing"]
    println(cardOrder)  // [HeartSix, HeartNine, ClubQueen, SpadeKing]
    shuffle(cardOrder)
    println(cardOrder)  // sample result: [SpadeKing, HeartNine, HeartSix, ClubQueen]
    let intValues = [1,2,3,4,5,6,7,8,9,10]
    println(intValues)  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    shuffle(intValues)
    println(intValues)  // sample result: [3, 10, 8, 4, 9, 7, 1, 2, 5, 6]