如何从枚举中 select 10 张随机卡片(或数字)

How to select 10 random cards (or numbers) from enum

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

enum CardName : Int{

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

我想 select didMoveToView 上的 10 个随机卡片

根据您的最后一条评论,这里有一个简化的小示例,其限制条件是必须保留您的枚举来制作卡片。

我们需要包括 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: [=13=]) })

就是这样,我们有一组随机排列的卡片:

let shuffledDeck = Array(0...51).shuffle().flatMap({ CardName(rawValue: [=14=]) }) // [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。

此示例有意保持简单:您仍然需要在抓牌前验证牌组中是否有足够的牌,以及许多未预料到的其他复杂性。但这太有趣了。 ;)

如果需要,您可以在我的 PokerHands 存储库(MIT 许可)中搜索我对这些模型和其他模型(Deck、Dealer、Player 等)的实现的其他灵感GitHub.

Swift 4.2

不需要这些扩展了,我们可以使用Swift提供的.shuffle().shuffled()方法。只需删除扩展,并重命名方法:相当于我们旧的 "shuffleInPlace" 现在是 .shuffle(),相当于我们的旧 "shuffle" 现在是 .shuffled().

注意:请参阅 以获得使用 Swift 4.2.

的更好解决方案

要获得一组唯一的随机号码,您可以执行以下操作...

使用此处的 Fisher-Yates 随机播放...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 个数字(卡片)。

然后您可以迭代此数组以获取枚举或创建所有枚举的数组以开始等等...有很多方法可以使用它。

这是您缺少的 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])
    }
  }
}

如何随机分布枚举值集

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: [=10=]) }}
}

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], [])
*/

在 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