Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import random
- import typing as t
- from enum import Enum
- from functools import partial
- import os
- import attr
- lock = partial(attr.s, auto_attribs=True, slots=True)
- State = Enum("State", "IDLE ACTIVE STAND BUST")
- def ask_question(question):
- while True:
- print(f"{question} [y/n]?")
- ans = input("> ").casefold()
- if ans in ("y", "n"):
- return ans == "y"
- def clear_console():
- os.system("cls" if os.name == "nt" else "clear")
- def ask_bet(money):
- clear_console()
- print(f"Money: ${money}")
- print("How much money do you want to bet?")
- while True:
- money_bet = input("> ")
- try:
- cash_bet = int(money_bet)
- except ValueError:
- cash_bet = -1
- if money >= cash_bet > 0:
- return cash_bet
- print("Please input a valid bet.")
- def build_deck():
- suits = ["Hearts", "Clubs", "Diamonds", "Spades"]
- values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
- cards = [Card(value, suit) for value in values for suit in suits]
- return cards
- @lock
- class Card:
- value: str
- suit: str
- def score(self):
- if self.value in "JQK":
- return 10
- elif self.value == "A":
- return 1
- else:
- return int(self.value)
- def __str__(self):
- return f"{self.value} of {self.suit}"
- @lock
- class Shoe:
- cards: t.List[Card] = attr.ib(factory=build_deck)
- def shuffle(self):
- random.shuffle(self.cards)
- def draw_card(self):
- if not self.cards:
- raise Exception("No more cards: empty deck!")
- return self.cards.pop()
- def __str__(self):
- cards = [str(c) for c in self.cards]
- return str(cards)
- @lock
- class Hand:
- cards: t.List[Card] = attr.ib(default=[])
- def add(self, card):
- self.cards.append(card)
- def score(self):
- total = sum(card.score() for card in self.cards)
- if any(card.value == "A" for card in self.cards) and total <= 11:
- total += 10
- return total
- def __str__(self):
- return "{} ({})".format(
- "".join("[{}]".format(card) for card in self.cards), self.score()
- )
- @lock
- class Player:
- money: int
- bet: int = attr.ib(default=None)
- hand: Hand = attr.ib(factory=Hand)
- state: State = attr.ib(default=State.IDLE)
- def player_bet(self):
- self.bet = ask_bet(self.money)
- def update(self):
- hand_score = self.hand.score()
- if hand_score > 21:
- self.state = State.BUST
- elif hand_score == 21:
- self.state = State.STAND
- else:
- self.state = State.ACTIVE
- def is_busted(self):
- return self.state == State.BUST
- def is_standing(self):
- return self.state == State.STAND
- def is_idle(self):
- return self.state == State.IDLE
- def is_broke(self):
- return self.money == 0
- def hit(self, dealer):
- card = dealer.draw_card()
- self.hand.add(card)
- def play(self, dealer):
- if ask_question("Do you want to hit"):
- self.hit(dealer)
- self.update()
- else:
- self.state = State.STAND
- def __str__(self):
- return (
- f"Player Info:\nMoney: {self.money}\nMoney bet: {self.bet}\n"
- f"State: {self.state.name.capitalize()}\nHand: {self.hand}"
- )
- @lock
- class Dealer:
- shoe: Shoe = attr.ib(factory=Shoe)
- hand: Hand = attr.ib(factory=Hand)
- state: State = attr.ib(default=State.IDLE)
- def draw_card(self):
- card = self.shoe.draw_card()
- return card
- def hit(self):
- card = self.draw_card()
- self.hand.add(card)
- def update(self):
- hand_score = self.hand.score()
- if hand_score > 21:
- self.state = State.BUST
- elif hand_score >= 17:
- self.state = State.STAND
- else:
- self.state = State.ACTIVE
- def is_busted(self):
- return self.state == State.BUST
- def is_standing(self):
- return self.state == State.STAND
- def is_idle(self):
- return self.state == State.IDLE
- def play(self):
- if self.hand.score() < 17:
- self.hit()
- self.update()
- def deal(self, player, game):
- while True:
- player.play(self)
- game.display_info()
- if player.is_busted():
- player.money -= player.bet
- player.hand.cards = []
- break
- if player.is_standing():
- break
- def show_cards(self, player):
- if player.state == State.ACTIVE:
- print(f"Dealer Info:\nHand: [{self.hand.cards[0]}][?]")
- elif player.state == State.STAND:
- print(f"Dealer Info:\nHand:{self.hand}")
- @lock
- class Game:
- player: Player
- dealer: Dealer = attr.ib(factory=Dealer)
- def open(self):
- if self.player.is_broke():
- raise Exception("Unfortunately you don't have any money.")
- self.player.player_bet()
- self.dealer.shoe.shuffle()
- c1 = self.dealer.draw_card()
- c2 = self.dealer.draw_card()
- self.player.hand = Hand([c1, c2])
- self.player.update()
- c1 = self.dealer.draw_card()
- c2 = self.dealer.draw_card()
- self.dealer.hand = Hand([c1, c2])
- self.dealer.update()
- self.display_info()
- def is_finished(self):
- if self.dealer.hand.score() >= 21:
- return True
- if self.player.is_busted() or self.player.is_standing():
- return True
- return False
- def close(self):
- dealer_score = self.dealer.hand.score()
- if not self.player.is_busted():
- if dealer_score > 21:
- self.player.money += self.player.bet * 2
- else:
- if self.player.hand.score() < dealer_score:
- self.player.money -= self.player.bet
- elif self.player.hand.score() > dealer_score:
- self.player.money += self.player.bet * 2
- self.display_info()
- self.player.hand.cards = []
- self.player.state = State.IDLE
- self.dealer.hand.cards = []
- self.dealer.state = State.IDLE
- self.dealer.shoe = Shoe()
- self.dealer.shoe.shuffle()
- def run(self):
- self.open()
- if self.is_finished():
- self.close()
- return
- self.dealer.deal(self.player, self)
- while True:
- self.dealer.play()
- if self.dealer.is_busted() or self.dealer.is_standing():
- break
- self.close()
- def display_info(self):
- clear_console()
- print(f"{self.player}\n")
- self.dealer.show_cards(self.player)
- player_score = self.player.hand.score()
- dealer_score = self.dealer.hand.score()
- if player_score == 21:
- print("Blackjack! You won!")
- elif dealer_score == 21:
- print("Dealer has got a blackjack. You lost!")
- elif self.player.is_busted():
- print("Busted! You lost!")
- elif self.player.is_standing():
- if self.dealer.is_busted():
- print("Dealer busted! You won!")
- elif player_score > dealer_score:
- print("You beat the dealer! You won!")
- elif player_score < dealer_score:
- print("Dealer has beaten you. You lost!")
- else:
- print("Push. Nobody wins or losses.")
- def main():
- playing = True
- p = Player(1000)
- while playing:
- g = Game(p)
- g.run()
- playing = ask_question("Do you want to play again")
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement