Master Object-Oriented Programming by Creating a Card Game

Create your own Card Game using Object-Oriented programming in Python

The best way to learn Object-Oriented Programming is by creating something object-oriented in Python. In this tutorial, we will create a simple card game.

Step 1: What is Object-Oriented Programming?

At its core, Object-Oriented Programming helps you with structuring your program to resemble reality.

That is, you declare objects with parameters and methods (functions) you need on them.

The best way is to learn it by creating an easy example you can relate to.

Consider the following.

This diagram represents three objects we want to model. The first is a Card, the second a Deck, and finally a Hand.

There are many things to notice, but first, that Hand is actually a sub-class of Deck. What does that mean? Don’t worry, we’ll get there.

Step 2: Implement the Card class using Object-Oriented Programming in Python

What does it all mean?

Well, first of all, there are many ways to represent a class and the above is just one possible option. But then if we look at Card, we have two groups to look at. First, suit and rank. Second, __str__() and __lt__(other).

The suit and rank are instance variables, while __str__() and __lt__(other) are class methods.

Instance variables are variables only available to a specific object instance. Hence, different instances of the same class can have different values.

Class methods are methods you can call on an object instance.

The function __str__() is a special method, which will give the string representation of the object instance. This is how the object will be represented if printed.

The function __lt__(other) is also a special method, which returns whether the object and another object other is greater. Hence, it returns a truth statement.

One way to implement this is as follows (see more about lists here).

class Card:
    suits = ['\u2666', '\u2665', '\u2663', '\u2660']
    ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
    
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank
        
    def __str__(self):
        return f"{Card.ranks[self.rank]}{Card.suits[self.suit]}"
    
    def __lt__(self, other):
        if self.rank == other.rank:
            return self.suit < other.suit
        else:
            return self.rank < other.rank

Notice we also have class variables suits and ranks (with s). They are used to give a representation in the __str__() method.

Class variables are available and the same across all objects.

Also, notice the __init__(self, suit, rank), which is a method that is called at the creation of the object, and it assigns variables to the instance variables (the ones with self)

Step 3: Implement the Deck class

A Deck should represent a pile of cards.

Here we want it to create a newly shuffled deck of cards when you create a new instance of the Deck object.

That can be accomplished as follows.

import random
class Deck:
    def __init__(self):
        self.deck = []
        for suit in range(4):
            for rank in range(13):
                self.deck.append(Card(suit, rank))
        self.shuffle()
        
    def __len__(self):
        return len(self.deck)
    
    def add_card(self, card):
        self.deck.append(card)
        
    def pop_card(self):
        return self.deck.pop()
    
    def shuffle(self):
        random.shuffle(self.deck)

Notice that the __len__() method is also special, and returns the length of the object. This is handy if you want to use len(…) on an object instance of Deck.

The rest of the methods are simple and straightforward.

Step 4: Implement the Hand class

The hand class is a sub-class of Deck. How does that make sense?

Well, it will share the same instance variable and methods with some additional ones.

Think about it, a Hand is like a Deck of cards, as it is a collection of cards.

How to implement that.

class Hand(Deck):
    def __init__(self, label):
        self.deck = []
        self.label = label
        self.win_count = 0
        
    def __str__(self):
        return self.label + ': ' + ' '.join([str(card) for card in self.deck])
    
    def get_label(self):
        return self.label
    
    def get_win_count(self):
        return self.win_count
    
    def round_winner(self):
        self.win_count = self.win_count + 1

Notice that we overwrite the __init__(…) method, as we do not want to create a full deck of cards. Here we start with empty hands.

Step 5: A simple game

  • Create a Deck of cards.
  • Create 4 players (P1, P2, P3, P4)
  • Divided all cards into 4 players.
  • Assume you are P1 and print the hand of P1.
  • The game has 13 rounds:
    • Each player plays 1 card.
    • The player with the highest card wins.
    • Update the score for the winning hand.
    • Print cards played in the round and the winner (with the winning card).
  • After the 13 rounds – print the score for all players (P1, P2, P3, P4).

How to do that?

deck = Deck()
hands = []
for i in range(1, 5):
    hands.append(Hand(f'P{i}'))
    
while len(deck) > 0:
    for hand in hands:
        hand.add_card(deck.pop_card())
        
print(hands[0])
for i in range(13):
    input()
    played_cards = []
    for hand in hands:
        played_cards.append(hand.pop_card())
    
    winner_card = max(played_cards)
    winner_hand = hands[played_cards.index(winner_card)]
    winner_hand.round_winner()
    
    print(f"R{i}: " + ' '.join([str(card) for card in played_cards]) + f' Winner: {winner_hand.get_label()} {str(winner_card)}')
    
for hand in hands:
    print(f"Score for {hand.get_label()}: {hand.get_win_count()}")

Amazing, right?

Want to learn more?

If this is something you like and you want to get started with Python, then this is part of an 8 hours FREE video course with full explanations, projects on each level, and guided solutions.

The course is structured with the following resources to improve your learning experience.

  • 17 video lessons teaching you everything you need to know to get started with Python.
  • 34 Jupyter Notebooks with lesson code and projects.
  • 2 FREE eBooks to support your Python learning.

See the full FREE course page here.

Learn Python

Learn Python A BEGINNERS GUIDE TO PYTHON

  • 70 pages to get you started on your journey to master Python.
  • How to install your setup with Anaconda.
  • Written description and introduction to all concepts.
  • Jupyter Notebooks prepared for 17 projects.

Python 101: A CRASH COURSE

  1. How to get started with this 8 hours Python 101: A CRASH COURSE.
  2. Best practices for learning Python.
  3. How to download the material to follow along and create projects.
  4. A chapter for each lesson with a descriptioncode snippets for easy reference, and links to a lesson video.

Expert Data Science Blueprint

Expert Data Science Blueprint

  • Master the Data Science Workflow for actionable data insights.
  • How to download the material to follow along and create projects.
  • A chapter to each lesson with a Description, Learning Objective, and link to the lesson video.

Machine Learning

Machine Learning – The Simple Path to Mastery

  • How to get started with Machine Learning.
  • How to download the material to follow along and make the projects.
  • One chapter for each lesson with a Description, Learning Objectives, and link to the lesson video.

Leave a Comment