Ejemplo n.º 1
0
class Testing(unittest.TestCase):
    def setUp(self):
        self.player = Card('Hearts', 'A')
        self.playerone = Deck()

    def test_suit(self):
        self.assertEqual(self.player.suit, 'Hearts')

    def test_suit_value(self):
        self.assertEqual(self.player.value, 'A')

    def test_represent_card(self):
        self.assertEqual(repr(self.player), 'A of Hearts')

    def test_tot_cards(self):
        self.assertEqual(len(self.playerone.cards), 52)

    def test_represent_deck(self):
        self.assertEqual(repr(self.playerone), 'Deck of 52 cards')

    def test_count(self):
        self.assertEqual(self.playerone.count(), 52)

    def test_shuffle(self):
        self.assertEqual(len(self.playerone.shuffle()), 52)
        self.assertNotEqual(self.playerone.cards[0:4], self.playerone.shuffle()[0:4])

    def test_deal_card(self):
        popped = self.playerone.cards[-1]
        dealt = self.playerone.deal_card()
        self.assertEqual(dealt, popped)
        self.assertEqual(self.playerone.count(), 51)

    def test_deal_hand(self):
        popped = self.playerone.cards[-1:-11:-1]
        dealt = self.playerone.deal_hand(10)
        self.assertEqual(dealt, popped)
        self.assertEqual(self.playerone.count(), 42)

    def test_add_card_removal(self):
        with self.assertRaises(ValueError):
            self.playerone.deal_hand(52)
            self.playerone.deal_card()

    def test_full_deck_shuffle(self):
        with self.assertRaises(ValueError):
            self.playerone.deal_card()
            self.playerone.shuffle()
Ejemplo n.º 2
0
class DeckTests(unittest.TestCase):
    def setUp(self):
        self.deck = Deck()

    def test_deck_init(self):
        self.assertTrue(isinstance(self.deck.card_deck, list))

    def test_repr(self):
        self.assertEqual(repr(self.deck), "'Deck of 52 cards'")

    def test_count(self):
        self.assertEqual(self.deck.count(), 52)
        self.deck.card_deck.pop()
        self.assertEqual(self.deck.count(), 51)

    def test_deal_sufficient_cards(self):
        cards = self.deck._deal(10)
        self.assertEqual(len(cards), 10)
        self.assertEqual(self.deck.count(), 42)

    def test_deal_insufficient_cards(self):
        self.deck._deal(55)
        self.assertEqual(self.deck.count(), 0)

    def test_deal_no_cards(self):
        self.deck._deal(self.deck.count())
        with self.assertRaises(ValueError):
            self.deck._deal(55)

    def test_deal_card(self):
        card = self.deck.card_deck[-1]
        dealt_card = self.deck.deal_card()
        self.assertEqual([card], dealt_card)
        self.assertEqual(self.deck.count(), 51)

    def test_deal_hand(self):
        cards = self.deck.deal_hand(20)
        self.assertEqual(len(cards), 20)
        self.assertEqual(self.deck.count(), 32)
    
    def shuffle_full_deck(self):
        cards = self.deck.card_deck[:]
        self.deck.shuffle()
        self.assertNotEqual(cards, self.deck.card_deck)
        self.assertEqual(len(self.deck.card_deck), 52)

    def shuffle_not_full_deck(self):
        self.deck.deal_hand(20)
        with self.assertRaises(ValueError):
            self.deck.shuffle()
Ejemplo n.º 3
0
class DeckTests(unittest.TestCase):
    def setUp(self):
        self.deck = Deck()

    def test_init(self):
        """ a deck should have a cards attribute which is a list consisting of 52 cards """
        self.assertIsInstance(self.deck.cards, list)
        self.assertEqual(len(self.deck.cards), 52)

    def test_repr(self):
        self.assertEqual(repr(self.deck), "Deck of 52 cards")

    def test_count(self):
        """ count should return count of the number of cards in the deck"""
        self.assertEqual(self.deck.count(), 52)
        self.deck.cards.pop()
        self.assertEqual(self.deck.count(), 51)

    def test_deal_sufficient_cards(self):
        """ _deal should deal number of cards specified """
        self.cards = self.deck._deal(10)
        self.assertEqual(len(self.cards), 10)
        self.assertEqual(self.deck.count(), 42)

    def test_deal_insufficient_cards(self):
        """_ deal should deal number of cards left in the deck if specified number is high"""
        self.cards = self.deck._deal(100)
        self.assertEqual(len(self.cards), 52)
        self.assertEqual(self.deck.count(), 0)

    def test_deal_no_cards(self):
        """_deal should throw a ValueError if there is no cards left in the deck"""
        self.deck._deal(self.deck.count())
        with self.assertRaises(ValueError):
            self.deck._deal(1)

    def test_deal_card(self):
        """deal_card should deal a single card from the deck """
        card = self.deck.cards[-1]
        dealt_card = self.deck.deal_card()
        self.assertEqual(card, dealt_card)
        self.assertEqual(self.deck.count(), 51)

    def test_deal_hand(self):
        """ deal_hand should deal number of cards specified from the deck"""
        hand = self.deck.deal_hand(20)
        self.assertEqual(len(hand), 20)
        self.assertEqual(self.deck.count(), 32)

    def test_shuffle_deck(self):
        """ shuffle should shuffle the deck only when it is full"""
        cards = self.deck.cards[:]
        self.deck.shuffle()
        self.assertNotEqual(cards, self.deck.cards)
        self.assertEqual(self.deck.count(), 52)

    def test_shuffle_not_full_deck(self):
        """shuffle should throw a ValueError when tried shuffling not a full deck"""
        self.deck._deal(1)
        with self.assertRaises(ValueError):
            self.deck.shuffle()
Ejemplo n.º 4
0
class Solitaire:
    """
    Patience class representing a game of Golf Solitaire.

    This game has 7 columns and 5 cards in each column,
    but the methods should work with other valid values as well.
    """

    columns = 7
    cards_in_column = 5

    def __init__(self):
        """
        Constructor, do the setup here.

        After setup with Solitaire.columns = 7, Solitaire.cards_in_column = 5
        You should have:
        self.tableau -> 7 columns of cards with 5 cards in each column
        self.stock -> 16 cards
        self.waste -> 1 card
        """
        self.deck = Deck()
        self.tableau = []
        self.waste = []
        self.stock = []
        self.deck.shuffle_deck()

        for col in range(Solitaire.columns):
            column = []
            # Deal cards to each column in range of given nr.
            for cards in range(Solitaire.cards_in_column):
                column.append(self.deck.deal_card())
            self.tableau.append(column)
        self.waste.append(self.deck.deal_card())

        while not self.deck.is_empty():
            self.stock.append(self.deck.deal_card())

    def can_move(self, card) -> bool:
        """
        Validate if a card from the tableau can be moved to the waste pile.

        The card must be last in the column list and adjacent by rank
        to the topmost card of the waste pile (last in waste list).
        Example: 8 is adjacent to 7 and 9. Ace is only adjacent to 2.
        King is only adjacent to Queen.
        """
        if card.rank is not None:
            for i in self.tableau:
                if len(i) > 0:
                    if card == i[-1]:
                        return card.rank - 1 == self.waste[
                            -1].rank or card.rank + 1 == self.waste[-1].rank
        return False

    def move_card(self, col: int):
        """
        Move a card from the tableau to the waste pile.

        Does not validate the move.
        :param col: index of column
        """
        if len(self.tableau[col]) > 0:
            card = self.tableau[col].pop()
            self.waste.append(card)

    def deal_from_stock(self):
        """
        Deal last card from stock pile to the waste pile.

        If the stock is empty, do nothing.
        """
        if len(self.stock) > 0:
            self.waste.append(self.stock.pop())

    def has_won(self) -> bool:
        """Check for the winning position - no cards left in tableau."""
        for i in self.tableau:
            if len(i) != 0:
                return False
        return True

    def last_cards(self):
        """Return list of last cards in the tableau."""
        return [
            self.tableau[i][-1] for i in range(len(self.tableau))
            if len(self.tableau[i]) != 0
        ]

    def has_lost(self) -> bool:
        """
        Check for the losing position.

        Losing position: no cards left in stock and no possible moves.
        """
        return len(self.stock) == 0 and len(
            [card for card in self.last_cards() if self.can_move(card)]) == 0

    def print_game(self):
        """
        Print the game.

        Assumes:
        Card(decorated=True) by default it is already set to True
        self.tableau -> a list of lists (each list represents a column of cards)
        self.stock -> a list of Card objects that are in the stock
        self.waste_pile -> a list of Card objects that are in the waste pile

        You may modify/write your own print_game.
        """
        print(f" {'    '.join(list('0123456'))}")
        print('-' * 34)
        print("\n".join([
            (" ".join((map(str, x))))
            for x in (zip_longest(*self.tableau, fillvalue="    "))
        ]))
        print()
        print(
            f"Stock pile: {len(self.stock)} card{'s' if len(self.stock) != 1 else ''}"
        )
        print(f"Waste pile: {self.waste[-1] if self.waste else 'Empty'}")

    @staticmethod
    def rules():
        """Print the rules of the game."""
        print("Rules".center(40, "-"))
        print(
            dedent("""
                Objective: Move all the cards from each column to the waste pile.

                A card can be moved from a column to the waste pile if the
                rank of that card is one higher or lower than the topmost card
                of the waste pile. Only the first card of each column can be moved.

                You can deal cards from the stock to the waste pile.
                The game is over if the stock is finished and
                there are no more moves left.

                The game is won once the tableau is empty.

                Commands:
                  (0-6) - integer of the column, where the topmost card will be moved
                  (d) - deal a card from the stock
                  (r) - show rules
                  (q) - quit
                  """))

    def play(self):
        """
        Play a game of Golf Solitaire.

        Create the game loop here.
        Use input() for player input.
        Available commands are described in rules().
        """
        allowed_moves = ["0", "1", "2", "3", "4", "5", "6"]
        self.deck.shuffle_deck()
        while True:
            self.print_game()
            if self.has_won():
                print("You won.")
                break
            if self.has_lost():
                print("You lost.")
                break
            command = input()
            if command == "r":
                self.rules()
                continue
            if command in allowed_moves:
                cmd = int(command)
                if cmd < Solitaire.columns:
                    if self.can_move(self.tableau[cmd][-1]) and len(
                            self.tableau[cmd]) != 0:
                        self.move_card(cmd)
                continue
            if command == "d":
                self.deal_from_stock()
                continue
            if command == "q":
                break
            else:
                print("Wrong input " + str(command))
                continue
Ejemplo n.º 5
0
class DeckTests(unittest.TestCase):
    def setUp(self):
        self.deck = Deck()

    def test_init(self):
        """decks should have a cards attribute, which is a list with 52 elements"""
        self.assertTrue(isinstance(self.deck.cards, list))
        self.assertEqual(len(self.deck.cards), 52)

    def test_repr(self):
        """repr should return a string of the form 'Deck of COUNT cards.'"""
        self.assertEqual(repr(self.deck), "Deck of 52 cards")

    def test_count(self):
        """count should return a count of the number of cards in the deck."""
        self.assertEqual(self.deck.count(), 52)
        self.deck.cards.pop()
        self.assertEqual(self.deck.count(), 51)

    def test_deal_sufficient_cards(self):
        """_deal should deal the number of cards specified, if possible"""
        cards = self.deck._deal(10)
        self.assertTrue(isinstance(cards, list),
                        "_deal(10) should return a list of 10 cards")
        self.assertEqual(len(cards), 10)
        self.assertEqual(self.deck.count(), 42)

    def test_deal_insufficient_cards(self):
        """_deal should deal the number of cards left in the deck, if more cards are requested"""
        cards = self.deck._deal(100)
        self.assertTrue(
            isinstance(cards, list),
            "_deal(100) should return a list with all cards left in deck")
        self.assertEqual(len(cards), 52)
        self.assertEqual(self.deck.count(), 0)

    def test_deal_no_cards(self):
        """_deal should throw a ValueError if the deck is empty"""
        self.deck._deal(self.deck.count())
        with self.assertRaises(ValueError):
            self.deck._deal(1)

    def test_deal_card(self):
        """deal_card should deal a single card from the deck"""
        card = self.deck.cards[-1]
        dealt_card = self.deck.deal_card()
        self.assertEqual(card, dealt_card)
        self.assertEqual(self.deck.count(), 51)

    def test_deal_hand(self):
        """deal_hand should deal the number of cards passed into it"""
        cards = self.deck.deal_hand(20)
        self.assertTrue(isinstance(cards, list),
                        "_deal(20) should return a list with 20 cards in it")
        self.assertEqual(len(cards), 20)
        self.assertEqual(self.deck.count(), 32)

    def test_shuffle_full_deck(self):
        """shuffle should shuffle the deck if the deck is full"""
        cards = self.deck.cards[:]
        self.deck.shuffle()
        self.assertNotEqual(cards, self.deck.cards)
        self.assertEqual(self.deck.count(), 52)

    def test_shuffle_not_full_deck(self):
        """shuffle should throw a ValueError of the deck isn't full"""
        self.deck._deal(1)
        with self.assertRaises(ValueError):
            self.deck.shuffle()
Ejemplo n.º 6
0
class Solitaire:
    """
    Solitaire class representing a game of Golf Solitaire.

    This game has 7 columns and 5 cards in each column,
    but the methods should work with other valid values as well.
    """

    columns = 7
    cards_in_column = 5

    def __init__(self):
        """
        Constructor, do the setup here.

        After setup with Solitaire.columns = 7, Solitaire.cards_in_column = 5
        You should have:
        self.tableau -> 7 columns of cards with 5 cards in each column
        self.stock -> 16 cards
        self.waste -> 1 card
        """
        self.deck = Deck()  # -> Deck instance
        self.tableau = [
        ]  # -> list of (columns[lists] (where each list -> cards_in_column * Card instances))
        self.waste = []  # -> list of Card instances
        self.stock = []  # -> list of Card instances
        self.deck.shuffle_deck()  # ->  shuffle_deck() from package cards
        for column in range(self.columns):
            column = []
            for card in range(self.cards_in_column):
                column.append(
                    self.deck.deal_card())  # -> deal_card() from package cards
            self.tableau.append(column)
        self.waste.append(self.deck.deal_card())
        for card in range(len(self.deck.cards)):
            self.stock.append(self.deck.deal_card())

    def can_move(self, card) -> bool:
        """
        Validate if a card from the tableau can be moved to the waste pile.

        The card must be last in the column list and adjacent by rank
        to the topmost card of the waste pile (last in waste list).
        Example: 8 is adjacent to 7 and 9. Ace is only adjacent to 2.
        King is only adjacent to Queen.
        """
        if card in [card[-1] for card in self.tableau if card]:
            return abs(card.rank - self.waste[-1].rank) == 1
        return False

    def move_card(self, col: int):
        """
        Move a card from the tableau to the waste pile.

        Does not validate the move.
        :param col: index of column
        """
        if self.tableau[col]:
            self.waste.append(self.tableau[col].pop(-1))

    def deal_from_stock(self):
        """
        Deal last card from stock pile to the waste pile.

        If the stock is empty, do nothing.
        """
        if self.stock:
            self.waste.append(self.stock.pop(-1))

    def has_won(self) -> bool:
        """Check for the winning position - no cards left in tableau."""
        return all(not card for card in self.tableau)

    def has_lost(self) -> bool:
        """
        Check for the losing position.

        Losing position: no cards left in stock and no possible moves.
        """
        return not self.stock and all(
            not self.can_move(card)
            for card in [card[-1] for card in self.tableau if card])

    def print_game(self):
        """
        Print the game.

        Assumes:
        Card(decorated=True) by default it is already set to True
        self.tableau -> a list of lists (each list represents a column of cards)
        self.stock -> a list of Card objects that are in the stock
        self.waste_pile -> a list of Card objects that are in the waste pile

        You may modify/write your own print_game.
        """
        print(f" {'    '.join(list('0123456'))}")
        print('-' * 34)
        print("\n".join([
            (" ".join((map(str, x))))
            for x in (zip_longest(*self.tableau, fillvalue="    "))
        ]))
        print()
        print(
            f"Stock pile: {len(self.stock)} card{'s' if len(self.stock) != 1 else ''}"
        )
        print(f"Waste pile: {self.waste[-1] if self.waste else 'Empty'}")

    @staticmethod
    def rules():
        """Print the rules of the game."""
        print("Rules".center(40, "-"))
        print(
            dedent("""
                Objective: Move all the cards from each column to the waste pile.

                A card can be moved from a column to the waste pile if the
                rank of that card is one higher or lower than the topmost card
                of the waste pile. Only the first card of each column can be moved.

                You can deal cards from the stock to the waste pile.
                The game is over if the stock is finished and
                there are no more moves left.

                The game is won once the tableau is empty.

                Commands:
                  (0-6) - integer of the column, where the topmost card will be moved
                  (d) - deal a card from the stock
                  (r) - show rules
                  (q) - quit
                  """))

    def play(self):
        """
        Play a game of Golf Solitaire.

        Create the game loop here.
        Use input() for player input.
        Available commands are described in rules().
        """
        while True:
            command = self.ask_next_move()
            if command == "q":
                break
            if command == "r":
                self.rules()
            if command == "d":
                self.deal_from_stock()
            if command in (0, 1, 2, 3, 4, 5, 6):
                if self.can_move(self.tableau[command][-1]):
                    self.move_card(command)
                else:
                    print("Invalid move! Try again!")
            if not self.stock:
                if self.has_lost():
                    print("No more moves left! You lost!")
                    break
                if self.has_won():
                    print("Congratulations! You won!")
                    break

    def ask_next_move(self):
        """Next move from the player."""
        self.print_game()
        while True:
            action = input("Choose your next move > ")
            if action in ["0", "1", "2", "3", "4", "5", "6"]:
                return int(action)
            if action in ["d", "r", "q"]:
                return action
            print("Invalid command!")
Ejemplo n.º 7
0
class TexasHoldemState():
    """Class responsible for maintaining the state of the hand."""
    def __init__(self):
        self.deck = Deck()
        self.deck.shuffle()
        self.board = []
        self.button = 0
        
        self.big_blind = 2
        self.small_blind = 1
        self.pot = self.small_blind + self.big_blind
        self.cur_bet = 2
        # Used to determine when to move to the next street
        # If play goes around to the last aggressor, Move to next street
        # Special note may be preflop Big blind
        self.last_aggressor = Player("Not A Person")
        self.counter = 0
        # check/bet/raise/fold = 0/1/2/3
        self.last_action = 0
        self.minimum_bet_size = 2
        self.is_anti = False
        self.anti = 0

    def flop(self):
        """Deals three cards on the flop"""
        for i in range(3):
           self.board.append(self.deck.deal_card())
        self.last_action = 0
        self.cur_bet = 0
        self.clean_state()

    def turn(self):
        """Deals one card on the turn"""
        self.board.append(self.deck.deal_card())
        self.clean_state()

    def river(self):
        """Deals one card on the river"""
        self.board.append(self.deck.deal_card())
        self.clean_state()

    def reinit(self, num_of_players):
        """Reinitialize state for the beginning of a new hand"""
        self.board = []
        self.deck.shuffle()
        self.button = (self.button + 1) % num_of_players
        self.pot = self.big_blind + self.small_blind
        self.minimum_bet_size = self.big_blind
        self.cur_bet = self.big_blind
        self.last_aggressor = Player("Not a Player")
        self.counter = 0

    def clean_state(self):
        """Cleans up the state after action closes on a street"""
        self.last_action = 0
        self.cur_bet = 0
        self.minimum_bet_size = 0
        self.last_aggressor = Player("Not a PLayer")
        self.counter = 0

    def display_board(self):
        """Print the cards on the table."""
        print([str(c) for c in self.board])

    def display_state(self):
        print("current pot size is {}".format(self.pot))
        print("current bet is {}".format(self.cur_bet))
        print("current minimum bet is {}".format(self.minimum_bet_size))
        self.display_board()