Reputation: 35
I am fairly new to intermediate programming, yet have played around with code for a while. At the moment I am making a simple card game. This issue is I am not sure where to use my functions or when to make them class methods.
For example, here is a simple function that deals out 5 cards to each player (from a predefined list) and then turns a card from the top of the pack (actually all just random selections). The cards are returned as a list of items (3 lists). I have also made a class called "Player".
p1_hand = []
p2_hand = []
flip_card = []
def deal_deck():
count = 0
for i in range(0, 10, 1):
count += 1
if count % 2 == 0:
card = random.choice(deck)
p2_hand.append(card)
deck.remove(card)
else:
card = random.choice(deck)
p1_hand.append(card)
deck.remove(card)
if count == 10:
flip_card.append(random.choice(deck))
return p2_hand, p1_hand, flip_card
In this example, it's just a deal, so I wonder why it would need to be a class method of "Player"? Possibly the class "Player" does not do much at all except keep score, keep track of who is dealing and what the score is?
To put it simply I am having trouble understanding the class as an object that interacts and preforms actions, I have made other classes and they have ended up working like a mini database rather than using much complexity in the methods at all.
Upvotes: 1
Views: 97
Reputation: 77837
I originally down-voted this as too broad, but changed my mind as I wrote up my notes for you. Classes are a programming tool whose implementation doesn't receive much treatment at the level you're asking. There are many examples of good card-game classes available on the Internet ... and many bad ones. The research isn't easy for you.
Use a class to represent a unit of your system (a card game, in this case) that is cohesive (a set of data and capabilities with a readily understood boundary) and interacts with other units, or with the main program.
In this case, you have a good start: you've identified card
, player
, and hand
as entities in your game system. You may want to treat the deck as a hand
instance (just another list of cards), or you may want to give it special treatment due to different functions within the game.
The classes and functions I've seen as useful include:
Deck
The impartial source of cards
data
a list of cards
methods
reset -- shuffle all 52 cards into a list
deal(n) -- return a list of n cards
Hand
cards held by a single player
data
a list of cards
methods
reset -- whatever is needed to return the hand to a game-start state
draw(n) -- acquire n cards
play(n) -- play n cards to the game area
Card
A single card, containing all information needed to identify it to the game
data
suit
rank
methods
none
Player
Game information about each player
data
hand -- see Hand class above
game-role -- depending on the game, this could be "dealer", "idle", "active", ...
... other, depending on the game: points, money, etc.
methods
... very dependent on the game being played
Game
the overall monitor for the game
data
roster -- list of players
deck -- see Deck class above
... other, depending on the game: round, player to play next, etc.
Some of these overlap a bit, such as "Deck.deal" and "Hand.draw". One of the design decisions you face is to choose which entity will drive an interaction between two objects.
As for implementation, I do suggest that you make your basic operations a lot simpler.
For the desk, initialize by generating all 52 cards with a nested list comprehension.
shuffle
the deck, and then use list slicing to deal the cards. For instance, to deal 5 cards to each player:
def deal(n):
take = deck[:n]
deck = deck[n:]
return take
# elsewhere, to drive the initial dealing ...
for player in roster:
player.hand = deck.deal(5)
Simply reduce the interactions to match the way you talk about the game: "deal each player five cards" should look just like that in the code. Bury the mechanics within each class.
Upvotes: 2
Reputation: 54698
There is an art to designing classes and objects. The fundamental purpose of using classes is information hiding. The rest of your program should not have to know how a deck of cards is implemented, which allows you to change the implementation without redesigning the whole program. Thus, you create a Deck
class that has all of the data stored internally, and only exposes to the outside world the things you want to DO with a deck, like shuffle
and deal_card
. A Player
class might include a hand
and a score
, and functions to add another card, and the Game
object (maybe) could coordinate dealing cards into the hand and triggering the plays.
The code you have is mixing all of this. It has to know how a deck is implemented, and how a hand is implemented, and how a card is flipped.
By the way, for the sake of realism, it would be better for you to shuffle the deck and deal cards off the top, instead of using random.choice
.
Upvotes: 3