Skip to content

Instantly share code, notes, and snippets.

@beaucarnes
Last active August 10, 2023 19:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beaucarnes/c505f2940eb283879c2ab2cf3b9cec7b to your computer and use it in GitHub Desktop.
Save beaucarnes/c505f2940eb283879c2ab2cf3b9cec7b to your computer and use it in GitHub Desktop.
python_blackjack_instructions.md

TOTAL STEPS: 140

You are going to build a blackjack card game in Python.

Every card in blackjack has a suit, rank, and value. For example, the king of hearts has a rank of "king", a suit of "hearts", and a value of 10 (In blackjack, face cards are worth 10).


suit = "hearts"

FIRST TEST

Let's represent the king of hearts with Python code. Variables store data. The code already has a variable named suit that is set to the value of "hearts". Add a variable named rank and set it to the value of "K" (for king).


suit = "hearts"
rank = "K"

When variables are set to equal a string, the string should be surounded by quotation marks. If a variable equals a number, quotation marks are not used around the number. Add a variable named value and set it to 10.


suit = "hearts"
rank = "K"
value = 10

The code print("Hello world") calls the print() function and to prints the text "Hello World" to the console. Print the the text "Your card is:" to the console.


suit = "hearts"
rank = "K"
value = 10
print("Your card is:")

Instead of passing in a string to the print() function (i.e. "Your card is:"), you can also pass in a variable and the value of the variable will print to the console. Print the value of the rank variable to the console.


suit = "hearts"
rank = "K"
value = 10
print("Your card is:")
print(rank)

The + operator can concatenate strings and/or variables together. Update your code so that the print() function is only called one time. It should print the following text to the console, using a variable for the rank: "Your card is: K"

Hints:

name = "Quincy"
print("My name is " + name)

That would print "My name is Quincy" to the console.

suit = "hearts"
rank = "K"
value = 10
print("Your card is: " + rank)

You can concatenate as many strings and variables as you want. Update your code so that the print() function prints the following text to the console, using variables for the rank and suit: "Your card is: K of hearts"

suit = "hearts"
rank = "K"
value = 10
print("Your card is: " + rank + " of " + suit)

You can use a list in python to store multiple values or items at a time. Here is an example of a list of strings: place = ["first", "second", "third"]. Below the suit variable, create a suits variable and assign it to a list of suits (spades, clubs, hearts, diamonds).


suits = ["spades", "clubs", "hearts", "diamonds"]
suit = "hearts"
rank = "K"
value = 10
print("Your card is: " + rank + " of " + suit)

The bracket operator can be used to access a specific element in a list. The number inside the bracket specifies the index of the list to access (indices start at 0). For example, the following code prints "first" to the console:

place = ["first", "second", "third"]
which = place[0]
print(which)

Update the suit variable so that the value of "hearts" comes from the suits list.


suits = ["spades", "clubs", "hearts", "diamonds"]
suit = suits[2]
rank = "K"
value = 10
print("Your card is: " + rank + " of " + suit)

  1. You can use a for loop go through each item in a list:
friends = ['Kris', 'Tom', 'Oliver']
for friend in friends:
    print(friend)

The above code goes through each item in the friends list, stores the value in the friend variable on each iteration, then prints it. Add a for loop to the end of your code that prints each suit.


suits = ["spades", "clubs", "hearts", "diamonds"]
suit = suits[2]
rank = "K"
value = 10
print("Your card is: " + rank + " of " + suit)
for suit in suits:
    print(suit)

Let's add another item to the suits list, just to see how it works. You can add a new value at the end of a list with append. For instance, here is how to add a new name to the friends list: friends.append('Beau'). Add the string "snakes" to the end of the suits list using append. Add the new line of code before the for loop so the loop will print the list with the new element.


suits = ["spades", "clubs", "hearts", "diamonds"]
suit = suits[2]
rank = "K"
value = 10
print("Your card is: " + rank + " of " + suit)
suits.append("snakes")
for suit in suits:
    print(suit)

Now you will start the process of representing a full deck of cards with Python code. Keep the first line and the last two lines but delete everything else. It won't be needed for the deck. Changing or improving previously written code is called refactoring.


suits = ["spades", "clubs", "hearts", "diamonds"]
for suit in suits:
    print(suit)

You have the list of suits. After that line create a list of ranks. (A, 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K)


suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    print(suit)

Before the suits list, create a new variable called cards and assign an empty list ([]) to the variable.


cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    print(suit)

In the cards list, there should be an item for each card in the deck. Each item in the suits list should be combined with each item in the ranks list for a total of 52 items (cards). We'll work our way up to that. Update the print statement in the for loop so that it prints a list with two elements. The first element should be suit and the second should be the first element of the ranks list. This will print an ace ("A") in every suit.


cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    print([suit, ranks[0]])

Now, instead of just printing an ace in every suit, let's print every rank in every suit. This can be done easily with a for loop nested within another for loop. Inside the for loop, add another for loop that loops through the ranks. The print command should then be inside the second for loop instead of the first for loop (the print command should be indented 8 spaces from the beginning of the line, instead of 4).


cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        print([suit, ranks[0]])

If you run the code, you will see that it isn't quite what we want. It doesn't print all the ranks because the print command specifies the exact same rank in every iteration. Change ranks[0] to rank.


cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        print([suit, rank])

Great! Now all 52 cards are printed as two-item lists. An element in a list can be another list. Instead of printing 52 two-item lists, append those 52 lists to the cards list.


cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

Check what the cards list looks like by printing it out at the end of your code. If you run the code, you can see the result.


cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

print(cards)

You may notice that all the cards are in order in the cards list. For a game like this, the cards must be shuffled. To help with this, add import random as the first line in your code. This imports the random module, which contains a variety of things related to random number generation. When you import a Python module, it allows you to use additional commands in your code.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

print(cards)

Now you can call the random.shuffle() function. Call that function right above the print command and put cards in between the parenthesis to pass the cards list into the function. If you run your code afterwards, you should notice that the cards have been shuffled.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

random.shuffle(cards)
print(cards)

Let's remove a single element from the cards list. This is similar to dealing a card from a deck. This can be done with the pop method. Consider this code:

people = ["abbey", "mrugesh", "miya"]
person = people.pop()

After running that code, person equals "miya" and people equals ["abbey", "mrugesh"]. After shuffling the cards, remove the last item from the cards list and store it in a variable named card.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

random.shuffle(cards)

card = cards.pop()

print(card)

When you call the random.shuffle() function, the program is running a sequence of statements (i.e. lines of code) to performs a computation. You can't see the sequence of statements but they are there inside the random module. You can create your own functions that will run the same sequence of statements everytime they are called. Here is an example of how to define a function called greeting that prints "Hi" everytime it is called (def is short for "define").

def greeting():
    print("Hi")

Put the line that shuffles the cards into a function called shuffle.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

card = cards.pop()

print(cards)

Right before the print statement, call the shuffle function. The code inside a function will not run until it is called. Here is how you would call a function named "greeting": greeting()


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

card = cards.pop()

shuffle()
print(cards)

Create a function named deal and put the line card = cards.pop() into the function.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal():
    card = cards.pop()

shuffle()
print(cards)

Variables can only be accessed in the context they were created. The card variable will not be available ouside of the deal function. You can get a value out of a function by returning a result using the return statement. At the end of the deal function add return card. Every line in a function must be indented the same number of spaces (in this case, 4 spaces).


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal():
    card = cards.pop()
    return card

shuffle()
print(cards)

After the shuffle function is called, call the deal function and assign the returned value to a variable named card. Then update the print function to print card instead of cards.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal():
    card = cards.pop()
    return card

shuffle()
card = deal()
print(card)

What if you want the deal function to deal more than one card? Let's refactor the deal function to accept an argument. Any number of arguments can apear inside the parentheses when a function is created, seperated by commas. Inside the function, the arguments are assigned to variables called parameters. Here is an example of a function that takes an argument:

def print_twice(bruce):
    print(bruce)
    print(bruce)

This function assigns the argument to a parameter named bruce. When the function is called, it prints the value of the parameter (whatever it is) twice. Make it so the deal function takes an argument named number. Then, call the function with the new parameter by upadating the last two lines of your code to:

cards_dealt = deal(2)
print(cards_dealt)

import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    card = cards.pop()
    return card

shuffle()
cards_dealt = deal(2)
print(cards_dealt)

The deal function is now going to return a list of cards instead of a single card. In the first line of the function create an empty list named cards_dealt. Then update the last line of the function to return cards_dealt.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    card = cards.pop()
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)

The range function can be used in a for loop to determine the number of loops. The following code will print "Hi" six times:

for x in range(6):
  print("Hi")

Put the line card = cards.pop() into a for loop that also appends the card onto the cards_dealt list. The loop should run the amount of times equal to the number parameter.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)

Let's seperate out a single card from the two cards dealt. At the end of your code create a variable called card and set it equal to the first item in the cards_dealt list. Then print the card.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
print(card)

Let's seperate out the rank part of the single card. After the line where the variable card is created, create a variable named rank and assign it the rank from card. (Tip: The rank is at index 1.)


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]
print(card)

Each rank has a different value. The value of "A" is 11 (or sometimes 1, but we'll get to that later). "J", "Q", and "K" have the value of 10. The numbers have the value of the number. You need to check what the rank is and set the value depending on the rank. This is the perfect time for a conditional statement, specifically, an if statement. Here is an example:

if x == y:
    print('x and y are equal')

That code will only print 'x and y are equal' IF the variables names x and y are equal to the same value. Take special note of the doulble equal sign (==). This is used to check if two values are equal. Make sure to not confuse it with a single equal sign (=), which is used to assign a value to a variable.

Before the print statement, add an if statement to check if rank == "A". If so, assign 11 to a variable named value.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11

print(card)

If rank does not equal "A", you'll want to check if it equals "J", "Q", or "K". That can be done with elif, which is an abbreviation of “else if.” For example:

if age < 13:
    print("You are a kid")
elif age > 17:
    print("You are an adult")

Notice in that example that you can use the greater than (>) and less than (<) signs in conditional statements. Some other comparison operators include =! (not equal to), <= (less that or equal to), and >= (greater than or equal to).

After the if statement, add the line elif rank == "J":. Then inside the elif statement assign 10 to value.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11
elif rank == "J":
    value = 10

print(card)

There are three logical operators: and, or, and not. You can use these operators in conditional statements to check multiple conditions at once. Update elif rank == "J": to elif rank == "J" or rank == "Q" or rank == "K":

import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11
elif rank == "J" or rank == "Q" or rank == "K":
    value = 10

print(card)

There can be any number of elif statements after an if statement. At the end, there can be an else statement. The block of code in an else statement executes if the if and all elif statements evaluate to False. Here is an example:

if age < 13:
    print("You are a kid")
elif age > 17:
    print("You are an adult")
else:
    print("You are a teenager")

After the elif statement, add an else statement. Inside, assign rank to value.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11
elif rank == "J" or rank == "Q" or rank == "K":
    value = 10
else:
    value = rank

print(card)

Update the print statement at the end to print(rank, value). Then try running the code a few times. You should see a different result each time. (Note: When mutiple values in a print statement are listed with a comma speraing them, both values are printed with a space in between.)


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11
elif rank == "J" or rank == "Q" or rank == "K":
    value = 10
else:
    value = rank

print(rank, value)

A Python dictionary is like a list, but more general. You can think of a dictionary as a mapping between a set of indices (which are called keys) and a set of values. Each key maps to a value. The association of a key and a value is called a key-value pair or sometimes an item. Here is a dictionary that maps from English to Spanish. They keys are the English words and the values are the Spanish words.

eng2sp = {"one": "uno", "two": "dos", "three": "tres"}

Above the print statement, create varialbe called rank_dict and assign to it this dictionary: {"rank": rank, "value": value}.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11
elif rank == "J" or rank == "Q" or rank == "K":
    value = 10
else
    value = rank

rank_dict = {"rank": rank, "value": value}

print(rank, value)

eng2sp = {"one": "uno", "two": "dos", "three": "tres"}
print(eng2sp["one"])

The code above will print "uno". Just like you access an item in a list by specifiying the index inside [], you can access an item in a dictionary by specifying the key inside []. Update the print statement so that you are accessing the rank and value from rank_dict instead of directly from the variables.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
cards_dealt = deal(2)
print(cards_dealt)
card = cards_dealt[0]
rank = card[1]

if rank == "A":
    value = 11
elif rank == "J" or rank == "Q" or rank == "K":
    value = 10
else
    value = rank

rank_dict = {"rank": rank, "value": value}

print(rank_dict["rank"], rank_dict["value"])

When writing a program, there are many ways to do almost everthing. Now you will refactor your code to get the value of each rank without using an if statement. Instead, you will store both the rank name and value in the ranks list using dictionaries. Delete all the lines of code after shuffle().


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()

Get a single card not in a list by adding the following line at the end of your code: card = deal(1)[0].


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
card = deal(1)[0]

Now, update the ranks list. Each element in the list should be a dictionary. When lists or list elements are long, it is common to put each element on it's own line. Here is the beginning of the new ranks list:

ranks = [
        {"rank": "A", "value": 11},
        {"rank": "2", "value": 2},
        {"rank": "3", "value": 3},
        ...
    ]

Update ranks in your code using the section above as a starting point. Replace "..." with the other ranks and values. (Remember, "J", "K", and "Q" have a value of 10 and the numers have the value of the number.)


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = [
        {"rank": "A", "value": 11},
        {"rank": "2", "value": 2},
        {"rank": "3", "value": 3},
        {"rank": "4", "value": 4},
        {"rank": "5", "value": 5},
        {"rank": "6", "value": 6},
        {"rank": "7", "value": 7},
        {"rank": "8", "value": 8},
        {"rank": "9", "value": 9},
        {"rank": "10", "value": 10},
        {"rank": "J", "value": 10},
        {"rank": "Q", "value": 10},
        {"rank": "K", "value": 10},
    ]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
card = deal(1)[0]

At the end of your code, print card. Try running your program to see what prints now that you have updated the ranks list.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = [
        {"rank": "A", "value": 11},
        {"rank": "2", "value": 2},
        {"rank": "3", "value": 3},
        {"rank": "4", "value": 4},
        {"rank": "5", "value": 5},
        {"rank": "6", "value": 6},
        {"rank": "7", "value": 7},
        {"rank": "8", "value": 8},
        {"rank": "9", "value": 9},
        {"rank": "10", "value": 10},
        {"rank": "J", "value": 10},
        {"rank": "Q", "value": 10},
        {"rank": "K", "value": 10},
    ]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
card = deal(1)[0]

print(card)

If you want to get just the rank of card, you will first have to access the second element in the list, then you will have to access the "rank" item in the dictionary. Because you are accessing something two times, there will be two sets of brackets. Look at this example:

card = ["clubs", {"rank": "J", "value": 10}]
rank = card[1]["rank"]

In that code, rank now equals "J". Think about the code until you understand why. Update your code so the print statement will print just the value in card.


import random

cards = []
suits = ["spades", "clubs", "hearts", "diamonds"]
ranks = [
        {"rank": "A", "value": 11},
        {"rank": "2", "value": 2},
        {"rank": "3", "value": 3},
        {"rank": "4", "value": 4},
        {"rank": "5", "value": 5},
        {"rank": "6", "value": 6},
        {"rank": "7", "value": 7},
        {"rank": "8", "value": 8},
        {"rank": "9", "value": 9},
        {"rank": "10", "value": 10},
        {"rank": "J", "value": 10},
        {"rank": "Q", "value": 10},
        {"rank": "K", "value": 10},
    ]
for suit in suits:
    for rank in ranks:
        cards.append([suit, rank])

def shuffle():
    random.shuffle(cards)

def deal(number):
    cards_dealt = []
    for x in range(number):
        card = cards.pop()
        cards_dealt.append(card)
    return cards_dealt

shuffle()
card = deal(1)[0]

print(card[1]["value"])

Now you will start defining classes that will be used in order to separate out different aspects of the game. Classes provide a way of bundling data and functionality together. Creating a new class creates a new type of object, allowing new instances of that type to be made. An object can contain a number of functions (which we call methods) as well as data that is used by those functions (called attributes). You will use classes to model three parts of the game: Card, Deck, and Hand. So far, you've mainly worked on elements of the Deck class.

Right after the import statement at the top, add this line: class Deck:. Then, highlight all the code after that line and hit the "Tab" key on your keyboard. This will indent all the code and make it part of the Deck class.


import random

class Deck:
    cards = []
    suits = ["spades", "clubs", "hearts", "diamonds"]
    ranks = [
            {"rank": "A", "value": 11},
            {"rank": "2", "value": 2},
            {"rank": "3", "value": 3},
            {"rank": "4", "value": 4},
            {"rank": "5", "value": 5},
            {"rank": "6", "value": 6},
            {"rank": "7", "value": 7},
            {"rank": "8", "value": 8},
            {"rank": "9", "value": 9},
            {"rank": "10", "value": 10},
            {"rank": "J", "value": 10},
            {"rank": "Q", "value": 10},
            {"rank": "K", "value": 10},
        ]
    for suit in suits:
        for rank in ranks:
            cards.append([suit, rank])

    def shuffle():
        random.shuffle(cards)

    def deal(number):
        cards_dealt = []
        for x in range(number):
            card = cards.pop()
            cards_dealt.append(card)
        return cards_dealt

    shuffle()
    card = deal(1)[0]

    print(card[1]["value"])

Remove the uneeded code in the Deck class by removing the last three lines of code.


import random

class Deck:
    cards = []
    suits = ["spades", "clubs", "hearts", "diamonds"]
    ranks = [
            {"rank": "A", "value": 11},
            {"rank": "2", "value": 2},
            {"rank": "3", "value": 3},
            {"rank": "4", "value": 4},
            {"rank": "5", "value": 5},
            {"rank": "6", "value": 6},
            {"rank": "7", "value": 7},
            {"rank": "8", "value": 8},
            {"rank": "9", "value": 9},
            {"rank": "10", "value": 10},
            {"rank": "J", "value": 10},
            {"rank": "Q", "value": 10},
            {"rank": "K", "value": 10},
        ]
    for suit in suits:
        for rank in ranks:
            cards.append([suit, rank])

    def shuffle():
        random.shuffle(cards)

    def deal(number):
        cards_dealt = []
        for x in range(number):
            card = cards.pop()
            cards_dealt.append(card)
        return cards_dealt

A class is like a template. You can use that class to create an instance of the class, called an object. Then you can use the instance. Each instance keeps it's own state so you can update an instance created from a class and it won't impact other objects created from the same class. Soon, you will see an example of what all this means so it will be easier to understand.

First, let's prepare our class to create an instance from it. When you create an instance of a class, Python automatically calls a funtion (also called a method) in the class named __init__. The contents of this method shoud be code that is run one time to initialize the instance. Define this function by adding the following line of code directly under class Deck:: def __init__(self):. Now indent all the code that is not part of the shuffle or deal functions so the code will be part of this new function.


import random

class Deck:
    def __init__(self):
        cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                cards.append([suit, rank])

    def shuffle():
        random.shuffle(cards)

    def deal(number):
        cards_dealt = []
        for x in range(number):
            card = cards.pop()
            cards_dealt.append(card)
        return cards_dealt

Notice the word "self" in the parenthesis of the function you just added. When defining a function, anything inside the parentheses is called an argument. These are variables passed in from the caller to the function. All functions in a class should recieve self as an argument. self represents the instance of the class. By using the self keyword, the function can access the attributes and methods of the class. For example, this would allow you to call the shuffle function from within the __init__ function. Add the self as the first item inside the parentheses on the definitions of the shuffle and deal functions.


import random

class Deck:
    def __init__(self):
        cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = cards.pop()
            cards_dealt.append(card)
        return cards_dealt

If you look at the variables defined inside the __init__ function, only cards is used in other functions. Inside a class, in order to access a variable in multiple functions (also called methods), the variable has to start with self.. Change all instances of cards in every function to self.cards.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = self.cards.pop()
            cards_dealt.append(card)
        return cards_dealt

You can now create an instance (also called object) of the deck class. At the very end of your code add the line deck1 = Deck() (with no indentation).


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = self.cards.pop()
            cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()

If you have an instance of a class named car with an attribute named model, you can access the value of the attribute with car.model. In your code, cards is an attribute of the deck1 instance created from the Deck class. Print the cards attribute.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = self.cards.pop()
            cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
print(deck1.cards)

If you run the code now, you should see the cards list from deck with the cards in order. You already created an instance of the Deck class called deck1. Underneath that and before the print statement, create another instance of the Deck class called deck2.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = self.cards.pop()
            cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
print(deck1.cards)

If you have an instance of a class named car with an method named drive, you can call the method with car.drive(). In your code, shuffle is a method of the deck2 instance created from the Deck class. Call that method right before the print statement.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = self.cards.pop()
            cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)

At the end of your code, print the cards attribute from the deck2 instance. If you run the code, you will see that the order of the cards list is different each time it is printed. That is because each instance stores the state of it's variables seperately. In the deck2 instance, the cards were shuffled. In the deck1 instance, the cards were not shuffled.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            card = self.cards.pop()
            cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

SEE IF PEOPLE CAN FIX ERROR OF 0 CARDS

The Deck works. Now let's add safeguards to prevent errors. Everytime the deal function is called, a card is removed from the cards list. You can only remove a card if there are cards to remove. So before the program tries to pop() a card off of self.cards, it should check if the length of self.cards is greater than (>) 0. You can get the number of items in a list with len(). Here is an example: len(self.cards). Inside the deal function, put all the code inside the appropriate if statement.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

A deck with only one card does not need to be shuffled. Add the appropriate if statement to the shuffle function.


import random

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

Since a "Card" is a seperate concept than a "Deck", next you'll make a Card class. Using the Deck class as an example, create a Card class above the Deck class. Add an __init__ function and inside that fuction set self.suit to equal "hearts".


import random

class Card:
    def __init__(self):
        self.suit = "hearts"

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

Also inside __init__, create a variable called self.rank and set it to "A".


import random

class Card:
    def __init__(self):
        self.suit = "hearts"
        self.rank = "A"

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

Currently, anytime a Card is created, it will be an Ace of Hearts. Refactor the code so the suit and rank are specified when a Card object is constructed. The __self__ method can take additioinal parameters (besides self) that are passed into it as the object is constructed. Here is an example of a Person class where the name and age are specified when an object is constructed:

class Person:
   def __init__(self, name, age):
     self.name = name
     self.age = age

sally = Person("Sally", 32)
print("Name: " + sally.name + ", Age: " + sally.age)

That code prints out "Sally 32".


import random

class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

When a class has a __str__ method, it is called when print() is invoked on an object from the class. In the Card class, add a __str__ method. Inside the method add return self.rank['rank'] + " of " + self.suit to return what should display when a card is printed.


import random

class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return self.rank['rank'] + " of " + self.suit

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

deck1 = Deck()
deck2 = Deck()
deck2.shuffle()
print(deck1.cards)
print(deck2.cards)

Try out the new __str__ method. Delete the last five lines in the code (everything after the Deck class). Add the following lines:

card1 = Card("diamonds", {"rank": "A", "value": 11})
card2 = Card("spades", {"rank": "5", "value": 5})
print(card1)
print(card2)

import random

class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return self.rank['rank'] + " of " + self.suit

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

card1 = Card("diamonds", {"rank": "A", "value": 11})
card2 = Card("spades", {"rank": "5", "value": 5})
print(card1)
print(card2)

F-strings allow you to include variables inside of strings so you don't have to concatenate the strings. Here is how you would create an f-string with the variables name and age inside: f"My name is {name} and I am {age} years old". Notice it begins with "f" and the variables are within curly braces. Update the return statement in __str__ to use an f-string.


import random

class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return f"{self.rank['rank']} of {self.suit}"

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append([suit, rank])

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

card1 = Card("diamonds", {"rank": "A", "value": 11})
card2 = Card("spades", {"rank": "5", "value": 5})
print(card1)
print(card2)

Currently, in the Deck class, the last line of the __init__ method appends a list as an item to the cards list. Instead of appending the list ([suit, rank]), create and append an instance of the Card class (Card(suit, rank)). Afterwards, when a Deck is created, it is filled with Cards.


import random

class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return f"{self.rank['rank']} of {self.suit}"

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append(Card(suit, rank))

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

card1 = Card("diamonds", {"rank": "A", "value": 11})
card2 = Card("spades", {"rank": "5", "value": 5})
print(card1)
print(card2)

The Deck and Card classes could be used for any card game. Now make a Hand class. This will represent a hand in the game of blackjack. Add a __init__ method inside the Hand class that intializes a variable called self.cards that is set to an empty list. Remove the code at the end that are not in a class.


import random

class Card:
    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank

    def __str__(self):
        return f"{self.rank['rank']} of {self.suit}"

class Deck:
    def __init__(self):
        self.cards = []
        suits = ["spades", "clubs", "hearts", "diamonds"]
        ranks = [
                {"rank": "A", "value": 11},
                {"rank": "2", "value": 2},
                {"rank": "3", "value": 3},
                {"rank": "4", "value": 4},
                {"rank": "5", "value": 5},
                {"rank": "6", "value": 6},
                {"rank": "7", "value": 7},
                {"rank": "8", "value": 8},
                {"rank": "9", "value": 9},
                {"rank": "10", "value": 10},
                {"rank": "J", "value": 10},
                {"rank": "Q", "value": 10},
                {"rank": "K", "value": 10},
            ]
        for suit in suits:
            for rank in ranks:
                self.cards.append(Card(suit, rank))

    def shuffle(self):
        if len(self.cards) > 1:
            random.shuffle(self.cards)

    def deal(self, number):
        cards_dealt = []
        for x in range(number):
            if len(self.cards) > 0:
                card = self.cards.pop()
                cards_dealt.append(card)
        return cards_dealt

class Hand:
    def __init__(self):
        self.cards = []

PART TWO IS HERE: https://gist.github.com/beaucarnes/05903eb6f4be455dd47506c8f3470be2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment