Skip to content

Instantly share code, notes, and snippets.

@rfunduk
Created June 5, 2014 15:52
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save rfunduk/518fe227dbdd60dc0dad to your computer and use it in GitHub Desktop.
Save rfunduk/518fe227dbdd60dc0dad to your computer and use it in GitHub Desktop.
import Darwin
extension Array {
func shuffle() -> Array {
// this will sometimes crash (submitted bug #17127524)
self.sort { _,_ in arc4random_uniform(2) == 1 }
return self
}
mutating func removeAtIndexes( indexes:Int... ) {
indexes.sort(>)
for i in indexes { removeAtIndex(i) }
}
}
class CardSet {
struct Card {
enum Suit:Int {
case Hearts, Diamonds, Clubs, Spades
}
enum Rank:Int {
case Two, Three, Four, Five, Six
case Seven, Eight, Nine, Ten
case Jack, Queen, King, Ace
}
let suit:Suit
let rank:Rank
}
var cards:Card[]
init() { cards = [] }
init( _ cards:Card[] ) { self.cards = cards }
var isEmpty:Bool { return cards.isEmpty }
}
class Deck:CardSet {
init() {
let indexes = Array(0..52).shuffle()
super.init(indexes.map { index in
let suit = Card.Suit.fromRaw(index % 4)!
let rank = Card.Rank.fromRaw(index % 13)!
return Card(suit: suit, rank: rank)
})
}
func drawCard() -> Card { return cards.removeLast() }
}
class Hand:CardSet {
var canPlay:Bool {
return cards.count >= 4 && (ranksMatch() || suitsMatch())
}
func play() {
if ranksMatch() { cards.removeAtIndexes(3, 2, 1, 0) }
else if suitsMatch() { cards.removeAtIndexes(2, 1) }
}
func add( card:Card ) { cards.insert(card, atIndex: 0) }
func ranksMatch() -> Bool { return cards[0].rank == cards[3].rank }
func suitsMatch() -> Bool { return cards[1].suit == cards[2].suit }
}
struct Game {
var deck = Deck()
var hand = Hand()
func play() -> Bool {
while !deck.isEmpty {
hand.add( deck.drawCard() )
while hand.canPlay { hand.play() }
}
return hand.isEmpty
}
}
let games = 1000
var wins = 0
for _ in 0..games { if Game().play() { wins++ } }
let winningPercentage = Double(wins) / Double(games)
println("Played \(games) games, \(wins) (\(winningPercentage)%) wins.")
@rfunduk
Copy link
Author

rfunduk commented Jun 5, 2014

'Card Game' in Swift

I don't know what this card game is called. I often use it when fiddling with a new language. The rules are:

  • use a full standard deck
  • if you ever have less than 4 cards, draw cards until you have at least 4
  • look at the first (newest) 4 cards in your hand
    • if the two cards on the outside have the same value (king, 2, 6, etc) -> remove all 4
    • if the two cards on the inside have the same suit -> remove the 2 middle cards
    • if nothing matches, draw another card
  • if the deck is empty and you have 0 cards in your hand, you win

When you play it by hand you effectively never win, so I have written several of these for various languages (Python, Ruby, JavaScript, Erlang, Go, Clojure, to name a few) and have pretty much settled on an approximate 0.002% chance of winning.

To run this you need Xcode 6 (atm in beta), start a new Command-Line OSX app and paste this code into main.swift.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment