コード例 #1
0
class TestPlayer(TestCase):
    def setUp(self):
        self.test_player_one = Player(1000)
        self.test_player_two = Player(0)
        self.test_card_one = Card(3, "spades")
        self.test_card_two = Card("ace", "diamonds")
        self.test_card_three = Card(4, "hearts")

    def test_invalid_player(self):
        with self.assertRaises(ValueError):
            Player(-1)

    def test_make_bet(self):
        self.assertEqual(self.test_player_one.bet, 0)
        self.test_player_one.make_bet(200)
        self.assertEqual(self.test_player_one.bet, 200)
        self.assertEqual(self.test_player_one.balance, 800)

    def test_make_bet_error(self):
        with self.assertRaises(ValueError):
            self.test_player_one.make_bet(2000)
        with self.assertRaises(ValueError):
            self.test_player_two.make_bet(1)

    def test_add_card_basic(self):
        self.assertEqual(len(self.test_player_one.hand), 0)
        self.test_player_one.add_card(self.test_card_one)
        self.assertEqual(len(self.test_player_one.hand), 1)
        self.assertEqual(self.test_player_one.hand[0].describe(),
                         "The 3 of spades.")

    def test_add_card_complex(self):
        self.assertEqual(len(self.test_player_one.hand), 0)
        self.test_player_one.add_card(self.test_card_one)
        self.test_player_one.add_card(self.test_card_two)
        self.assertEqual(self.test_player_one.hand[0].describe(),
                         "The 3 of spades.")
        self.assertEqual(self.test_player_one.hand[1].describe(),
                         "The ace of diamonds.")
        self.test_player_one.add_card(self.test_card_three)
        self.assertEqual(self.test_player_one.hand[2].describe(),
                         "The 4 of hearts.")

    def test_clear_hand(self):
        self.test_add_card_complex()
        self.assertEqual(len(self.test_player_one.hand), 3)
        self.test_player_one.clear_hand()
        self.assertEqual(len(self.test_player_one.hand), 0)
コード例 #2
0
class SimpleBlackjackModel(object):

    def __init__(self, num_deck):
        """
        Represents a simple model for a blackjack game between a single player and a dealer.
        :param num_deck: the number of decks used for the game
        """
        player_starting_amt = int(input("How much do you want to start with:\n"))
        Utils.require_non_negative(num_deck)
        Utils.require_non_negative(player_starting_amt)
        self.dealer = Dealer()
        self.player = Player(player_starting_amt)
        self.deck = Deck(num_deck)
        self.is_player_turn = True  # True if the players turn. False if the dealers turn

    def play(self):
        """
        Plays a simple blackjack game.
        :return: void method
        """
        # Pregame
        print(f"The player has ${self.player.balance} available")
        player_bet = int(input("Please make a bet:\n"))
        print("----------------------------------")

        # Bet made -> deal cards
        self.player.make_bet(player_bet)
        self.deal()
        print(self.get_game_state())

        # Gameplay
        while not self.is_hand_over():
            action = input(f"Do you want to 'HIT' or 'STAY'\n")
            print("----------------------------------")
            if action == "HIT":
                self.hit()
                print(self.get_game_state())
            elif action == "STAY":
                self.stay()
                print(self.get_game_state())
            else:
                print("Please enter either 'HIT' or 'STAY'\n")

        # Do you want to play again? If not, return the result of the blackjack session
        play_again = input("Do you want to play again? (YES / NO):\n")
        print("----------------------------------")
        if play_again == "YES":
            self.clear()
            self.play()
        else:
            print(f"The player currently has: ${self.player.balance}\n")
            print(f"Thank you for playing!")
            print(f"The number of cards left in the deck: {len(self.deck.cards)}")

    # ----------------SET UP METHODS-------------------
    def deal(self):
        """
        Deals out two cards to all players and the dealer at a table. Starts with the player to the left of the dealer.
        :return: None
        """
        deal_player = True
        i = 0
        while i < 4:
            if deal_player:
                self.player.add_card(self.deck.draw())
                deal_player = False
            else:
                self.dealer.add_card(self.deck.draw())
                deal_player = True
            i += 1

    def is_hand_over(self):
        """
        When playing, a hand is over when:
        - it is the players turn and they have busted (hand value > 21)
        - it is the players turn and they have blackjack (hand value = 21)
            -> if the dealer has 21, PUSH, otherwise, the player gets 1.5X their betting amount
        - it is the dealers turn and they have busted
        - it is the dealers turn and they have > 16, but < 21
        :return: boolean. True if hand is over, False if not.
        """
        player_hand_val = self.hand_value(self.player.hand)
        dealer_hand_val = self.hand_value(self.dealer.hand)

        # It is the players turn, so the dealer has <= 21
        if self.is_player_turn:
            if player_hand_val > 21:
                print("LOSE")
                return True
            elif player_hand_val == 21: # blackjack case
                if dealer_hand_val == 21:
                    print("PUSH")
                    self.player.balance += self.player.bet
                else:
                    print("WIN")
                    self.player.balance += 2.5 * self.player.bet
                return True
        # It is the dealers turn, so the player has <= 21
        else:
            if dealer_hand_val > 21:
                print("WIN")
                self.player.balance += 2 * self.player.bet
                return True
            elif dealer_hand_val > player_hand_val:
                print("LOSE")
                return True
            elif player_hand_val == dealer_hand_val:
                print("PUSH")
                self.player.balance += self.player.bet
                return True
            elif dealer_hand_val >= 17:
                if player_hand_val > dealer_hand_val:
                    print("WIN")
                    self.player.balance += 2 * self.player.bet
                    return True
        return False

    def get_game_state(self) -> str:
        """
        Represents the true current state of the blackjack game as a string.
        :return: a string representing the true current state
        """
        result = ""
        turn = "PLAYER" if self.is_player_turn else "DEALER"
        dealer_hand = [self.card_value(card) for card in self.dealer.hand]
        player_hand = [self.card_value(card) for card in self.player.hand]
        if self.is_player_turn:
            turn = "PLAYER" if self.is_player_turn else "DEALER"
            dealer_hand_hidden = ["?", dealer_hand[1]]
            result += f"Dealer's Hand: {dealer_hand_hidden} -> ?\n\n"
        else:
            result += f"Dealer's Hand: {dealer_hand} -> {self.hand_value(self.dealer.hand)}\n\n"
        result += f"Player's Balance: {self.player.balance}\n"
        result += f"Player's Bet: {self.player.bet}\n"
        result += f"Player's Hand: {player_hand} -> {self.hand_value(self.player.hand)}\n\n"
        result += f"It is the {turn}'s turn"
        return result

    @staticmethod
    def card_value(card: Card) -> int:
        """
        Returns the value of a card in a blackjack game. Aces are either 1 or 11.
        :return: an integer representing the value of a card
        """
        if isinstance(card.rank, int):
            return card.rank
        elif card.rank == "ace":
            return 11
        else:
            return 10

    def hand_value(self, hand: list) -> int:
        """
        Converts a list representing a hand into its game value.
        :param hand: the player or dealer hand
        :return: int
        """
        val = 0
        num_aces = 0
        for card in hand:
            if card.rank == 'ace':
                num_aces += 1
                val += self.card_value(card)
            else:
                val += self.card_value(card)
        while num_aces > 0:
            if val > 21:
                val -= 10
            num_aces -= 1
        return val

    # ----------------GAME PLAY METHODS-------------------
     def hit(self) -> str:
        """
        Deals a card to the current player or dealer depending on whose turn it is.
        :return: n/a. void method
        """
        if self.is_player_turn:
            self.player.add_card(self.deck.draw())
        else:
            self.dealer.add_card(self.deck.draw())

    def stay(self):
        """
        A stay action from the player or the dealer. If the player stays, it is then
        the dealers turn. If the dealer stays, evaluate the hand to see who wins
        :return: n/a. void method
        """
        if self.is_player_turn:
            self.is_player_turn = False
        else:
            self.is_hand_over()

    def clear(self):
        """
        Clears the hands of the player(s) and dealer.
        :return: None
        """
        self.is_player_turn = True
        self.player.clear_hand()
        self.dealer.clear_hand()