1
\$\begingroup\$

I'm making a Texas Hold'em game for multiple players. So far, I have finished the flow control for betting / calling sequences, player stack / pot updating, and just now - the part responsible for drawing cards and distributing them. It is this last part that I would like reviewed, if possible.

Essentially, I wanted to know what I could do differently / more efficiently, suggested changes, really just anything that could be helpful. Things like checks for proper input from player etc are not yet in place so please ignore them.

import itertools
import random

player_count = int(input("How many players? "))

suits = ['s', 'c', 'd', 'h']
faces = ['A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K']

# Defining deck and drawing cards (5 + 2 per player):

deck = set(itertools.product(faces, suits))
drawn_cards = random.sample(deck,(5 + 2 * player_count))

# Storing a list with player object instances

players = []

class Players:

    def __init__(self, stack):

        self.stack = stack
        self.last_action = "none"  ## last action taken (check, call etc). 
        self.street_bets = 0       ## total bets on current street

    def holecards(self):

## pop cards from list and pritifying their display. Cards will later be 
## run through a function for checking value of hands:

        card1 = drawn_cards.pop(len(drawn_cards)-1) 
        card2 = drawn_cards.pop(len(drawn_cards)-1) 
        self.card1 = (card1[0]+"["+card1[1]+"]")    
        self.card2 = (card2[0]+"["+card2[1]+"]")     
        self.cards = self.card1+ " - " +self.card2
        print (self.cards)      

class Table:

    def __init__(self):     

        self.total_pot = 0

    def flop(self):

        card1 = drawn_cards.pop(len(drawn_cards)-1)
        card2 = drawn_cards.pop(len(drawn_cards)-1) 
        card2 = drawn_cards.pop(len(drawn_cards)-1)
        self.card1 = (card1[0]+"["+card1[1]+"]")
        self.card2 = (card2[0]+"["+card2[1]+"]")     
        self.card3 = (card2[0]+"["+card2[1]+"]")
        self.flop = self.card1+ " - " + self.card2 + " - " + self.card3
        print (self.flop)

    def turn(self):

        card = drawn_cards.pop(len(drawn_cards)-1)
        self.card = (card[0]+"["+card[1]+"]")
        self.turn = self.card
        print (self.turn)

    def river(self):

        card = drawn_cards.pop(len(drawn_cards)-1)
        self.card = (card[0]+"["+card[1]+"]")
        self.river = self.card
        print (self.river)



# Add player stacks and distribute holecards:

for i in range(player_count):
    players.append(i)
    players[i] = Players(100)
    players[i].holecards()

# Add dealer to table:

dealer = Table()

dealer.flop()
dealer.turn()
dealer.river()
\$\endgroup\$

2 Answers 2

4
\$\begingroup\$

Reasonable quality code. Here are a few comments:

1) I'd add a method drawNextCard, which encapsulates retrieval of the next card, and makes the code a bit more readable

def draw_next_card(drawn_cards):
    card = drawn_cards.pop(len(drawn_cards)-1)
    return readable_card_name(card)

def readable_card_name(short_card_name):
    return (short_card_name[0]+"["+short_card_name[1]+"]")

Then, for example, your flop() method would look like this:

def flop(self):
    (self.card1, self.card2, self.card3) = (draw_next_card(drawn_cards), draw_next_card(drawn_cards), draw_next_card(drawn_cards)) 
     self.flop = self.card1+ " - " + self.card2 + " - " + self.card3
     print (self.flop)

More readable, shorter, and on the way we fixed a copy/paste defect where you initialized card2 twice instead of card2 and card3.

2) You convert each drawn card to a readable representation. It's good for your debugging, but not so good for adding future functionality for actually calculating poker hands, and developing strategy. So, while my draw_next_card above returns a readable representation, you're better off creating a class Card, which has an __str__ method that has the same implementation as readable_class_name. The flop method would remain the same, but it will be much easier to extend the code.

3) Note that flop and river are copy/pastes. Both could just call draw_next_card. Also, while the flow and river are true to the game terms, they're not much benefit to software; you'd be better off collapsing flop, turn and river to a table_cards[5] vector. Once you start developing the actual game, it will make things much easier for you.

Hope this helps.

\$\endgroup\$
-2
\$\begingroup\$

I found no direct way to reply to you RomanK, but I had to say thank you. So - thank you!

EDIT: sorry for the "Thank you", I guess.

Another question: after thinking it through, does using a class for dealing and distributing the flop, turn and river make sense at all? Wouldn't I be better off just using a function for this? The more I think of it the less I see any reason for having this part of the code in a class - seems to be more of a problem than a convenience.

Essentially, after the hole cards have been dealt to the players, what remains in the drawn_cards list are the 5 cards for the board. All I need to do now is display them with a function:

def deal_community_cards(street):

    if street == "flop":
        flop = drawn_cards[0:3]
        return flop

    elif street == "turn":
        turn = drawn_cards[3]
        return turn

    else:
        river = drawn_cards[4]
        return river    

and finally I'd use another function to "pritify" the card display. Wouldn't this be a better solution than creating a whole class for this?

\$\endgroup\$
3
  • \$\begingroup\$ Firstly, as forsvarir says, you're better off editing your own post, rather than adding an answer. Secondly, welcome. As to your new question: consider that you don't always draw 5 cards - what happens if everyone folds after the flop? Also, as mentioned in my answer: not sure that you even need variables called flop, turn and river - they are helpful for poker players, but not to your code's logic. \$\endgroup\$
    – RomanK
    Oct 22, 2016 at 13:09
  • \$\begingroup\$ Thanks again. So what you are suggesting is that, essentially, when I want to show the flop/turn/river cards to players, that all I do is just display the cards to them, ie. just print (drawn_cards[0:3]) for the flop, and that's all. Do I understand correctly? \$\endgroup\$ Oct 22, 2016 at 14:41
  • \$\begingroup\$ Yes, that is the idea. \$\endgroup\$
    – RomanK
    Oct 22, 2016 at 17:41

Not the answer you're looking for? Browse other questions tagged or ask your own question.