所以我正在制作纸牌游戏,Ring of Fire。我存储了这样的图像:
var picture:[UIImage] = [
UIImage(named: "Card2")!,
UIImage(named: "Card3")!,
UIImage(named: "Card4")!,
UIImage(named: "Card5")!,
UIImage(named: "Card6")!,
UIImage(named: "Card7")!,
UIImage(named: "Card8")!,
UIImage(named: "Card9")!,
UIImage(named: "Card10")!,
UIImage(named: "CardJack")!,
UIImage(named: "CardQueen")!,
UIImage(named: "CardKing")!,
UIImage(named: "CardAce")!,
]
每张卡片都有当前卡片下方显示的文字:
var name:String = ""
var files = ["Velg en som må drikke", // 2
"Drikk selv", // 3
"Alle jenter må drikke", // 4
"Tommelen", // 5
"Alle gutter må drikke", // 6
"Pek på himmelen", // 7
"Drikkepartner", // 8
"Rim", // 9
"Kategori", // 10
"Lag en regel", // Jack
"Spørsmålsrunde", // Queen
"Hell drikke i koppen", // King
"Fossefall"] // Ace
这就是我选择随机卡的方式:
func imageTapped(img: AnyObject){
if(cardsleftLabel.text != "0") {
let randomNumber = Int(arc4random_uniform(UInt32(files.count)))
let image = picture[randomNumber]
cardImage.image = image
name = files[randomNumber]
}
else{
print("No more cards")
}
}
问题是该卡可能会多次出现,这是错误的。每张卡有4张,所以如何在游戏中控制它?那么CardJack
不会出现6次?
答案 0 :(得分:5)
一种方法是生成代表您的卡片的索引数组。随机播放该数组,然后在绘制卡片时从该数组中删除索引。
// generate random list of indices from 0...12 four each
var cardIndices = (0...51).map {($0 % 13, arc4random())}.sort{$0.1 < $1.1}.map{$0.0}
// To get a card, remove last card from deck
let last = cardIndices.removeLast()
// use the index to look up the picture
let randomCard = picture[last]
// It's also easy to check how many cards you have left in your deck
let remaining = cardIndices.count
这首先创建一个元组数组,其中包含0 ... 12的数字和一些随机整数。然后该元组按元组中的随机整数元素排序,然后map
用于分隔索引数组,为您留下一个Int
的随机数组,其值为0 ... 12(每个的四个值)。
这是课堂形式。
import UIKit
struct Card {
let image: UIImage
let text: String
}
class Deck {
private let cards:[Card] = [
Card(image: UIImage(named: "Card2")!, text: "Velg en som må drikke"),
Card(image: UIImage(named: "Card3")!, text: "Drikk selv"),
Card(image: UIImage(named: "Card4")!, text: "Alle jenter må drikke"),
Card(image: UIImage(named: "Card5")!, text: "Tommelen"),
Card(image: UIImage(named: "Card6")!, text: "Alle gutter må drikke"),
Card(image: UIImage(named: "Card7")!, text: "Pek på himmelen"),
Card(image: UIImage(named: "Card8")!, text: "Drikkepartner"),
Card(image: UIImage(named: "Card9")!, text: "Rim"),
Card(image: UIImage(named: "Card10")!, text: "Kategori"),
Card(image: UIImage(named: "CardJack")!, text: "Lag en regel"),
Card(image: UIImage(named: "CardQueen")!, text: "Spørsmålsrunde"),
Card(image: UIImage(named: "CardKing")!, text: "Hell drikke i koppen"),
Card(image: UIImage(named: "CardAce")!, text: "Fossefall")
]
private var cardIndices = [Int]()
var cardsInDeck: Int { return cardIndices.count }
func shuffleCards() {
cardIndices = (0...51).map{($0 % 13, arc4random())}.sort{$0.1 < $1.1}.map{$0.0}
}
func drawCard() -> Card {
if cardIndices.count == 0 {
shuffleCards()
}
let last = cardIndices.removeLast()
return cards[last]
}
}
注意:
cards
和cardIndices
已private
隐藏Deck
用户的详细信息。struct
来表示卡片。这样可以将数据保存在一起,并提供可以从drawCard
返回的漂亮值。Deck
的用户可以使用Deck
创建Deck()
,他们可以调用shuffleCards()
随机化套牌,查看cardsInDeck
属性以查找有多少洗牌可用,他们可以拨打drawCard()
从牌组中取出下一张牌。对于控制套牌的viewController,将属性添加到viewController:
class MyGame: UIViewController {
var deck = Deck()
// the rest of the code
}
然后,当您需要一张卡片时,例如在@IBAction
内的按钮,只需拨打deck.drawCard
:
@IBAction func turnOverNextCard(button: UIButton) {
let card = deck.drawCard()
// Use the image and text to update the UI
topCardImageView.image = card.image
topCardLabel.text = card.text
// I'm not going to wait for the deck to shuffle itself
if deck.cardsInDeck < 10 {
deck.shuffleCards()
}
}
我的随机播放程序通过将随机UInt32
与每张卡相关联然后按照这些值对牌组进行排序来对牌组进行洗牌。如果为两张牌生成相同的随机数,那么牌组中的早期牌可能比后来的牌更受青睐(反之亦然,取决于排序算法)。这真的是分裂的头发,但为了提供最好的洗牌,我提供以下选择:
func shuffleCards() {
cardIndices = (0...51).map {$0 % 13}
for i in (1...51).reverse() {
let rand = Int(arc4random_uniform(UInt32(i + 1)))
(cardIndices[i], cardIndices[rand]) = (cardIndices[rand], cardIndices[i])
}
}
此算法基于Fisher-Yates shuffle。
答案 1 :(得分:1)
你需要一个班级代表卡片的Deck
,就像这样。
class Deck {
static let seeds = 4
var images : [UIImage:Int] = [
UIImage(named: "Card2")! : seeds,
UIImage(named: "Card3")! : seeds,
UIImage(named: "Card4")! : seeds,
UIImage(named: "Card5")! : seeds,
UIImage(named: "Card6")! : seeds,
UIImage(named: "Card7")! : seeds,
UIImage(named: "Card8")! : seeds,
UIImage(named: "Card9")! : seeds,
UIImage(named: "Card10")! : seeds,
UIImage(named: "CardJack")! : seeds,
UIImage(named: "CardQueen")! : seeds,
UIImage(named: "CardKing")! : seeds,
UIImage(named: "CardAce")! : seeds
]
func extractRandomCard() -> UIImage? {
let flatten = images.reduce([UIImage]()) { [UIImage](count: $0.1.1, repeatedValue: $0.1.0) }
guard !flatten.isEmpty else { return nil }
let random = Int(arc4random_uniform(UInt32(flatten.count)))
let selectedCard = flatten[random]
images[selectedCard] = images[selectedCard]! - 1
return selectedCard
}
}
现在你可以从牌组中提取牌
let deck = Deck()
let image = deck.extractRandomCard()
每次提取卡片时,Deck会对其进行跟踪,并且不会让您提取相同卡片的4倍以上。
我没有测试它......但它应该可以工作
答案 2 :(得分:0)
随机方法的另一种方法是使用Apple的一些很好的GamePlayKit,这些东西是为这些用例创建的。如果你有cards
数组,你可以这么做:
let shuffled2 = GKRandomSource().arrayByShufflingObjectsInArray(cards) as! [Card]
或者你可以保持数组未被清洗,而是改变你请求的索引:
let indexes = GKShuffledDistribution.init(forDieWithSideCount: 52)
// going through all the cards randomly
for _ in cards {
let card = cards[indexes.nextInt()]
}
答案 3 :(得分:0)
public enum Palo: Int
{
case Corazones = 1
case Treboles = 2
case Picas = 3
case Diamantes = 4
}
public struct Card
{
public var text: String
public var position: Int
public var palo: Palo
public func description() -> String
{
return "\(self.position) of \(self.palo) -- \(self.text)"
}
}
public struct Deck
{
public var cards: [Card]
public init()
{
cards = [Card]()
for number in 1...13
{
for palo in 1...4
{
let card: Card = Card(text: "", position: number, palo: Palo(rawValue: palo)!)
cards.append(card)
}
}
}
/**
Return cards one by one
*/
public mutating func randomCard() -> Card?
{
guard !self.cards.isEmpty else
{
return nil
}
let position: Int = Int(arc4random_uniform(UInt32(self.cards.count)))
let card: Card = self.cards.removeAtIndex(position)
return card
}
}
//
// TEST
//
var deck: Deck = Deck()
for index in 1...200
{
if let card = deck.randomCard()
{
print("\(index) -- \(card.description())")
}
}