Skip to content

Instantly share code, notes, and snippets.

@davidolesch
Last active June 15, 2017 23:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidolesch/26338baf8cf0f85688ee02217d0ad8b8 to your computer and use it in GitHub Desktop.
Save davidolesch/26338baf8cf0f85688ee02217d0ad8b8 to your computer and use it in GitHub Desktop.
import Foundation
protocol Randomizable {
init?(rawValue:Int)
static var min:Int { get }
static var max:Int { get }
}
extension Randomizable {
static var random:Self? {
let index = min + Int(arc4random_uniform(UInt32(max)))
return Self(rawValue:index)
}
}
struct BlackjackCard {
enum Suit: Int, Randomizable, CustomStringConvertible {
var description: String {
switch self {
case .spades:
return "♠"
case .hearts:
return "♡"
case .diamonds:
return "♢"
case .clubs:
return "♣"
}
}
case spades, hearts, diamonds, clubs
static let min = Suit.spades.rawValue
static let max = Suit.clubs.rawValue
}
enum Rank: Int, Randomizable {
case two = 2, three, four, five, six, seven, eight, nine, ten
case jack, queen, king, ace
struct Values {
let first: Int, second: Int?
}
var values: Values {
switch self {
case .ace:
return Values(first: 1, second: 11)
case .jack, .queen, .king:
return Values(first: 10, second: nil)
default:
return Values(first: self.rawValue, second: nil)
}
}
static let min = Rank.two.rawValue
static let max = Rank.ace.rawValue
}
let rank: Rank, suit: Suit
var description: String {
var output = "[\(rank.values.first)"
if let second = rank.values .second {
output += " or \(second)"
}
output += " of \(suit.description)]"
return output
}
static func randomCard() -> BlackjackCard {
return BlackjackCard(rank: Rank.random ?? .two, suit: Suit.random ?? .spades)
}
}
class Hand {
var cards:[BlackjackCard] = []
var value:Int {
var v = 0
for card in cards {
v += card.rank.values.first
}
if soft && containsAce {
v += 10;
}
return v
}
var containsAce: Bool {
get {
return self.cards.contains { return $0.rank == .ace }
}
}
var soft:Bool {
var v = 0
for card in cards {
v += card.rank.values.first
}
return v < 12
}
var busted:Bool {
return value > 21
}
var description:String {
var d = ""
for card in cards {
d += card.description + " "
}
return d
}
}
class Participant {
var hand = Hand()
}
class Dealer: Participant {
var upCard:BlackjackCard? {
return self.hand.cards.last
}
func dealInitialHandsToParticipants(participants: [Participant]) {
for participant in participants {
dealACardToParticipant(participant: participant)
dealACardToParticipant(participant: participant)
}
}
func dealACardToParticipant(participant: Participant) -> BlackjackCard {
let card = BlackjackCard.randomCard()
participant.hand.cards.append(card)
return card
}
func dealToFinish() -> Hand {
while hand.value < 17 {
dealACardToParticipant(participant: self)
}
return hand
}
func beat(player:Player) -> Bool {
if player.hand.busted {
return true
}
if self.hand.busted {
return false
}
return player.hand.value <= self.hand.value
}
}
class Player: Participant {
func playAgainstDealer(dealer:Dealer, upCard:BlackjackCard) -> Hand {
while hand.value < upCard.rank.values.first + 10 {
dealer.dealACardToParticipant(participant: self)
}
return hand
}
}
//Mark - tests
var testHand = Hand()
let fiveOfSpades = BlackjackCard(rank: .five, suit: .spades)
let fourOfHearts = BlackjackCard(rank: .four, suit: .hearts)
testHand.cards.append(contentsOf: [fiveOfSpades, fourOfHearts])
assert(testHand.value == 9)
let aceOfHearts = BlackjackCard(rank: .ace, suit: .hearts)
testHand.cards.append(aceOfHearts)
assert(testHand.value == 20)
testHand = Hand()
testHand.cards.append(contentsOf: [fiveOfSpades, fourOfHearts, fourOfHearts])
assert(testHand.value == 13)
testHand.cards.append(aceOfHearts)
assert(testHand.value == 14)
//Mark - play
let dealer = Dealer()
let player1 = Player()
let player2 = Player()
dealer.dealInitialHandsToParticipants(participants: [dealer, player1, player2])
if let upCard = dealer.upCard {
print("|**** Initial Hands ****|")
print("Dealer Hand: [ ?? of ??] \(upCard.description)")
print("Player 1 Hand: \(player1.hand.description)")
print("Player 2 Hand: \(player2.hand.description)")
player1.playAgainstDealer(dealer: dealer, upCard: upCard)
player2.playAgainstDealer(dealer: dealer, upCard: upCard)
dealer.dealToFinish()
print("\n|**** Final Hands ****|")
print("Dealer Hand: \(dealer.hand.description)")
print("Player 1 Hand: \(player1.hand.description)")
print("Player 2 Hand: \(player2.hand.description)")
print("\n|**** Result ****|")
print("Player 1 \(dealer.beat(player: player1) ? "Loses" : "Wins")")
print("Player 2 \(dealer.beat(player: player2) ? "Loses" : "Wins")")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment