Reputation: 41
I'm taking a first course in python, and since my text book is quite shallow I am trying to get familiar with classes by hands on experience.
I am wanting to write a program that deals a number of texas hold'em poker hands (one hand to begin with), then deals five cards to the table, before it looks at all the possible hand permutations with 5 table cards and 2 hand cards. (One can combine the two cards of ones hand with three of the five cards of the table). Eventually i want to expand it to compare and evaluate the hands, and nominate a winner. But that will be for later.
What I am curious to find out is a good way to structure this problem with classes.
Would it be wise to make a Hand class that holds a deal-function and contains the different hands dealt, and let deck be a global variable?
#The hand-class is a class for the dealt poker-hands.
import random
deck = [i for i in range (102, 115)]
deck += [i for i in range(202, 215)]
deck += [i for i in range(302, 315)]
deck += [i for i in range(402, 415)]
# I define a card by a prefix number - the suit - and the card value. Jack of spades = 111 if spades corresponds to 1.
class Hand:
def __init__(self):
return None
def deal_hand(self):
self.hand = []
for i in range (0,2):
card = random.choice(deck)
self.hand.append(card)
deck.remove(card)
#def score():
#a function to determine the sore of the hand..
What I am asking is: What is the correct way to use classes for this purpose? Should I make another class to hold the five cards dealt to the poker table, and yet another class to hold the different permutations?
Or should both the hands, the hand's score, the table's dealt cards and the different permutations of the hand's cards to the table's all belong to the same class?
I am not asking anybody to write me any code, but if you had time to give me a quick hint on which direction I should be looking in, I would be very thankfull! Thanks! Marius
Upvotes: 4
Views: 3563
Reputation: 4022
You don't need to use classes for the sake of using classes (unless you're using Java)
The way I approach classes, is I first think about what "object" or "thing" I am going to need, and then define properties and methods that will define that thing. If I am going to create multiple instances of the same thing, then a class is useful. If I am only ever going to need 1 instance, then a module or global variable will most likely suffice.
For instance, in your example, you don't really need classes. However, if you do something like wanting to support multiple decks for your game, then you would want to define a Deck class that can contain and control all the information about its own cards.
Think about poker itself - how does it work?
You have a dealer, you have players, a dealer has one or more decks of cards. The dealer shuffles and then deals cards to the players and to the table. How would you want to define each of these processes as objects?
I would look at the real-world example and break it into its reusable parts, and that becomes your classes. So for example, I would probably look at it and say:
class Deck(object):
""" class for managing a deck of cards """
class Player(object):
""" defines properties and methods that an individual player would have """
def __init__( self ):
self._cards = [] # hold a player current cards
self._chips = 10 # define how much money a player has
def clearCards( self ):
self._cards = []
def dealCard( self, card ):
self._cards.append(card)
class Dealer(object):
""" defines properties and methods that a dealer would have """
def __init__( self ):
self._decks = [] # hold multiple decks for playing with
self._stack = [] # holds all the shuffled cards as a
def nextCard( self ):
""" pop a card off the stack and return it """
return self._stack.pop()
def shuffle( self ):
for deck in self._decks:
deck.shuffle() # shuffle each individual deck
# re-populate a shuffled stack of cards
self._stack = []
# randomly go through each deck and put each card into the stack
def deal( self, *players ):
""" Create a new hand based on the current deck stack """
# determine if i need to shuffle
if ( len(self._stack) < self._minimumStackCount ):
self.shuffle()
return Hand(self, *players)
class Hand(object):
def __init__( self, dealer, *players ):
self._dealer = dealer # points back to the dealer
self._players = players # defines all the players in the hand
self._table = [] # defines the cards on the table
self._round = 1
for player in players:
player.clearCards()
self.deal()
def deal( self ):
# in holdem, each round you get a different card combination per round
round = self._round
self._round += 1
# deal each player 2 cards in round 1
if ( round == 1 ):
for i in range(2):
for player in players:
player.dealCard( self._dealer.nextCard() )
# deal the table 3 cards in round 2 (flop)
elif ( round == 2 ):
self._table = [self._dealer.nextCard() for i in range(3)]
# deal the table 1 card in round 2 (turn)
elif ( round == 3 ):
self._table.append(self._dealer.nextCard())
# deal the table 1 card in round 3 (river)
else:
self._table.append(self._dealer.nextCard())
So on and so forth.
All that code is generally pseudo code to illustrate how to mentally visualize the way to break things up. Really the easiest way is to think about the real-life scenario and write down in plain english how it works and then the classes will start to visualize themselves.
Upvotes: 2
Reputation: 3706
First off, there is no "correct" way to go about this. It is all in personal preference and design considerations.
Personally, the way I would go about this is that i would create 3 data classes:
Deck
to deal cards, and keep track of which cards have already been dealt
I would give this class a generic draw
method which returns a random card from the available cards
Player
to keep track of each of the player's cards, which can be determined by calling Deck.draw()
twice
Table
to keep track of the cards on the table
Then, I would wrap this all in a Game
class which handled all of the game logic, like making sure the cards on the table were drawn at the correct time
Upvotes: 3
Reputation: 527183
If you want to go with classes, an often-used rule of thumb is to have the class(es) be the thing(s) doing the action(s) or that the actions are done with.
For instance, a hand doesn't tend to deal itself, and you don't deal a hand with that hand; a hand is dealt with a deck. So you might create a Deck
class that has a .deal_hand()
method which would return a Hand
.
The Hand
class would have a .score()
method, any anything else related to what you would actually do with a hand.
That said, you don't need to use classes for this. If you want to, that's fine - but decks and hands could both easily be represented by set
.
Upvotes: 2