Created
October 19, 2018 02:18
-
-
Save jay18001/d33771e72f128eb6197e2bf127dcab32 to your computer and use it in GitHub Desktop.
Blackjack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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