Skip to content

Instantly share code, notes, and snippets.

@jay18001
Created October 19, 2018 02:18
Show Gist options
  • Save jay18001/d33771e72f128eb6197e2bf127dcab32 to your computer and use it in GitHub Desktop.
Save jay18001/d33771e72f128eb6197e2bf127dcab32 to your computer and use it in GitHub Desktop.
Blackjack
import Foundation
enum Card {
case ace
case face(value: Int)
case jack
case queen
case king
}
extension Card: Equatable {
}
extension Card {
func blackjackValue(aceHigh: Bool) -> Int {
switch self {
case .ace:
return aceHigh ? 11 : 1
case .face(let value):
return value
case .jack, .queen, .king:
return 10
}
}
}
let standardDeck: [Card] = [.ace, .face(value: 2), .face(value: 3), .face(value: 4), .face(value: 5), .face(value: 6), .face(value: 7), .face(value: 8), .face(value: 9), .face(value: 10), .jack, .queen, .king, .ace, .face(value: 2), .face(value: 3), .face(value: 4), .face(value: 5), .face(value: 6), .face(value: 7), .face(value: 8), .face(value: 9), .face(value: 10), .jack, .queen, .king, .ace, .face(value: 2), .face(value: 3), .face(value: 4), .face(value: 5), .face(value: 6), .face(value: 7), .face(value: 8), .face(value: 9), .face(value: 10), .jack, .queen, .king, .ace, .face(value: 2), .face(value: 3), .face(value: 4), .face(value: 5), .face(value: 6), .face(value: 7), .face(value: 8), .face(value: 9), .face(value: 10), .jack, .queen, .king]
let allDecks: [Card] = standardDeck + standardDeck + standardDeck + standardDeck + standardDeck
var gameDeck: [Card] = []
func setup() {
gameDeck = allDecks.shuffled()
}
struct Hand {
private(set) var cards: [Card]
var shown: Card {
return cards.first!
}
var value: Int {
return cards.reduce(0, { $0 + $1.blackjackValue(aceHigh: $0 + 11 >= 21) })
}
mutating func add(card: Card) {
cards.append(card)
}
init(cards: [Card]) {
self.cards = cards
}
}
enum Result {
case win
case lose
case tie
}
func deal(playerNumber: Int = 1) -> (dealer: Hand, players: [Hand]) {
var playerHands: [Hand] = []
for _ in 0..<playerNumber+1 {
playerHands.append(Hand(cards: [gameDeck.removeFirst(), gameDeck.removeFirst()]))
}
return (dealer: playerHands.removeFirst(), players: playerHands)
}
func processDealerTurn(hand oldHand: Hand) -> Hand {
let dealerStand = 17
var hand = oldHand
while hand.value >= 21 {
if hand.value > dealerStand {
break
}
hand.add(card: gameDeck.removeFirst())
}
return hand
}
func processPlayerTurn(hand oldHand: Hand, dealerCard: Card) -> Hand {
let stand = 16
var hand = oldHand
while hand.value >= 21 {
if hand.value > stand {
break
}
if dealerCard.blackjackValue(aceHigh: true) >= 10 {
break
}
hand.add(card: gameDeck.removeFirst())
}
return hand
}
func run() -> [Result] {
var results: [Result] = []
for _ in 0..<1000 {
if gameDeck.count <= 10 {
setup()
}
let (dealer, players) = deal()
let player = players.first!
if dealer.value == 21, dealer.value == player.value {
results.append(.tie)
continue
} else if dealer.value == 21 {
results.append(.lose)
continue
} else if player.value == 21 {
results.append(.win)
continue
}
let playerTurn = processPlayerTurn(hand: player, dealerCard: dealer.shown)
if playerTurn.value > 21 {
results.append(.lose)
continue
}
let dealerTurn = processDealerTurn(hand: dealer)
if dealerTurn.value > 21 {
results.append(.win)
continue
}
if dealerTurn.value == playerTurn.value {
results.append(.tie)
} else if playerTurn.value > dealerTurn.value {
results.append(.win)
} else {
results.append(.lose)
}
}
return results
}
for i in 1...100 {
setup()
let results = run()
let wins = results.filter { $0 == .win }.count
let loses = results.filter { $0 == .lose }.count
let ties = results.filter { $0 == .tie }.count
print("\(i),\(wins),\(loses),\(ties)")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment