如何从枚举中选择10个随机卡(或数字)

时间:2016-02-22 13:46:29

标签: swift arc4random

我有一些关于swift 2随机的问题。我有一个枚举子类的所有卡片例子:

enum CardName : Int{

case Card2Heart = 0,
Card2Diamond,
Card2Club,
Card2Spade,
Card3Heart..... }

我想在didMoveToView上选择10张随机卡

5 个答案:

答案 0 :(得分:2)

要获得一组独特的随机数字,您可以执行以下操作...

从这里使用Fisher-Yates shuffle ...... How do I shuffle an array in Swift?

你可以......

var numbers = Array(0...51)

numbers.shuffleInPlace()

let uniqueSelection = numbers[0..<10]

...或

let uniqueSelection = Array(0...51).shuffleInPlace()[0..<10]

这将从您开始的52张卡片阵列中创建10个数字(卡片)的随机,唯一选择。

然后你可以迭代这个数组来获取枚举或者创建一个包含所有枚举的数组等等......有很多方法可以使用它。

答案 1 :(得分:2)

在Swift 4.2(随Xcode 10推出)中,任务将变得更加容易:

enum CardName: CaseIterable {
    case Card2Heart
    case Card2Diamond
    case Card2Club
    case Card2Spade
    case Card3Heart
    // ...
}

let randomCard = CardName.allCases.randomElement()
print(randomCard)

let randomCards10 = CardName.allCases.shuffled().prefix(10)
print(randomCards10)

请注意,枚举不需要从Int继承。

答案 2 :(得分:1)

根据您的上一次评论,这里有一个小巧,简化的示例,其约束条件是必须保留您制作卡片的枚举。

我们需要包含由Fogmeister链接的扩展程序:

extension MutableCollectionType where Index == Int {
    /// Shuffle the elements of `self` in-place.
    mutating func shuffleInPlace() {
        // empty and single-element collections don't shuffle
        if count < 2 { return }

        for i in 0..<count - 1 {
            let j = Int(arc4random_uniform(UInt32(count - i))) + i
            guard i != j else { continue }
            swap(&self[i], &self[j])
        }
    }
}

extension CollectionType {
    /// Return a copy of `self` with its elements shuffled
    func shuffle() -> [Generator.Element] {
        var list = Array(self)
        list.shuffleInPlace()
        return list
    }
}

这些扩展将允许我们改组一系列值。

哪个阵列?

有很多种方法,但最简单的选择可能是创建一个索引数组,它们是简单的整数(用枚举中的实际卡数替换52):

Array(1...52) // [1, 2, 3, ... , 52]

我们改变它:

Array(1...52).shuffle() // [33, 42, 7, ...]

现在我们有一系列随机指数。让我们用你的枚举来制作卡片:

Array(0...51).shuffle().flatMap({ CardName(rawValue: $0) })

就是这样,我们有一系列随机顺序的卡片:

let shuffledDeck = Array(0...51).shuffle().flatMap({ CardName(rawValue: $0) }) // [Card3Heart, Card2Diamond, ...]

我们可以从中取卡:

func takeCardsFromDeck(number: Int) -> [CardName] {
    if shuffledDeck.count > number {
        let cards = Array(shuffledDeck[0..<number])
        shuffledDeck.removeRange(0..<number)
        return cards
    }
    return []
}

let tenRandomCards = takeCards(10)

当然,我们需要从卡片中删除我们处理的卡片,这样您绘制的每张卡片都是唯一的:我们正在使用removeRange。

这个例子有目的地保持简单:你仍然需要在绘图之前验证牌组中是否有足够的牌,以及许多未经考虑的其他复杂性。但它很有趣。 ;)

如果您愿意,可以在GitHub上的PokerHands存储库(MIT许可)中搜索这些模型和其他模型(Deck,Dealer,Player等)的其他灵感。

Swift 4.2

不再需要这些扩展程序,我们可以使用Swift提供的.shuffle().shuffled()方法。只需删除扩展名,然后重命名方法:相当于我们旧的&#34; shuffleInPlace&#34;现在是.shuffle(),相当于我们旧的&#34; shuffle&#34;现在是.shuffled()

注意:有关使用Swift 4.2的更好解决方案,请参阅Sulthan's answer

答案 3 :(得分:0)

以下是您缺少的shuffleInPlace()代码;

extension MutableCollectionType where Index == Int {
mutating func shuffleInPlace() {
    if count < 2 { return }

    for i in 0..<count - 1 {
        let j = Int(arc4random_uniform(UInt32(count - i))) + i
        guard i != j else { continue }
        swap(&self[i], &self[j])
    }
  }
}

答案 4 :(得分:0)

如何随机传播枚举值集

import Darwin // arc4random_uniform

enum E:Int {
    case E1, E2, E3, E4, E5, E6, E7, E8, E9, E10
    static var set:[E] { return (E.E1.rawValue...E.E10.rawValue).flatMap { E(rawValue: $0) }}
}

func spread(i:Int = 0, arr:[E])->([E],[E]) {
    var i = i == 0 ? arr.count : i
    var e:[E] = []
    var arr = arr
    while  i > 0 && arr.count > 0 {
        let idx = Int(arc4random_uniform(UInt32(arr.count-1)))
        e.append(arr.removeAtIndex(idx))
        i -= 1
    }
    return (e,arr)
}

let e1 = spread(3, arr: E.set)
let e2 = spread(2, arr: e1.1)
// ... spread the rest
let e3 = spread(arr: e2.1)

print(e1, e2, e3, separator:"\n")
/*
([E.E8, E.E6, E.E4], [E.E1, E.E2, E.E3, E.E5, E.E7, E.E9, E.E10])
([E.E1, E.E7], [E.E2, E.E3, E.E5, E.E9, E.E10])
([E.E5, E.E3, E.E2, E.E9, E.E10], [])
*/