yego.me
💡 Stop wasting time. Read Youtube instead of watch. Download Chrome Extension

Dealing cards with functions | Intro to CS - Python | Khan Academy


4m read
·Nov 10, 2024

Let's design a program with functions and nested function calls. We want to build a program that lets the user play several different car games. That means every game is going to need to share functionality for dealing a deck of playing cards.

The first thing that comes to mind is that I'll probably want a function that can draw a random card from the deck. I'm thinking I probably want to represent a card as a string, so this might return something like "Queen of Hearts." For now, I'm going to go ahead and stick that in as a placeholder return value.

The other task I can see wanting to perform over and over again is drawing a hand of cards. Different games use different hand sizes, so I'll want this to be generalizable. The function should take, as a parameter, the number of cards in the hand.

Okay, so how should this function work? I guess really what I want is to draw a number of cards equal to that parameter. Maybe I accumulate all of those card strings into one giant string and then return that at the end. That sounds like a good use case for a loop. On each iteration, I draw a card and then I concatenate that card to our hand.

Before we get ahead of ourselves, let's test out what we did so far by calling draw hand. To be safe, let's test it out with a few different arguments.

Oh, okay, um, that's a little hard to read. What if instead I put each card on a separate line? In Python, we can achieve this with a new line character, which is just a backslash followed by "n." Instead of displaying this as it appears, Python interprets this essentially as us hitting the enter key.

So now with my hand nicely formatted, I feel confident that my draw hand function works. But I don't want my hand to be full of Queens every time, so it's time to go back in and fill in our draw card function. A playing card consists of two pieces: the suit and the rank.

To draw a random card, then, I want to pick a random suit and random rank, which sounds like two different tasks, which means two different functions. Let's start out with the suit, since that only has four options, and we'll import the random module at the top of the file.

Okay, well, we want this function to return either hearts, diamonds, spades, or clubs with equal likelihood. So we'll generate a random number between 1 and 4 and based on that number choose which suit to return. Then we can go back to the draw card function and replace that hardcoded "hearts" with a call to get suit.

When I run those draw hand function calls now, I get all different kinds of Queens. The last thing we need to add is a get rank function. A playing card can have a rank of Ace, 2 through 10, or Jack, Queen, King. That means in total there are 13 possible ranks, so we'll generate a number between 1 and 13.

If we get one, we'll return the rank Ace; if we get 11, we'll return Jack; if we get 12, Queen; and 13, King. Any other rank, like 8, is just represented by its number, so we can return num. Now, just like before, let's go back to draw a card and call get rank.

What does this stack trace mean? When we read stack traces that involve function calls, we generally want to focus on the bottom because that is what will tell us what the actual error is and what line it came from. The rest of the stack trace just tells us the path of execution the computer took to reach that line.

So it started by executing draw hand, which then called draw a card, which then had the error. This type error tells us that we're adding an integer and a string, so get rank must be returning an integer. Somehow these cases are definitely returning a string, but down here when we return num, num is an integer.

As a general rule, a function should be consistent about which data type it returns. Always that way, callers can know what to expect. So since get rank needs to return a string in the Ace, Jack, Queen, King case, we also want to cast num to a string before we return it.

There's one last feature we want to add. Some of our card games don't use face cards, that is, Ace, Jack, Queen, King, because face cards can either be enabled or disabled. We can support this option with a Boolean parameter. If we don't want face cards, we can just generate a random number between 2 and 10 instead. That way we're excluding the options 1, 11, 12, and 13.

Now when I call get rank inside draw a card, I'll need to pass that parameter. But how do I know if it should be true or false? Well, I don't know. I want to let the caller decide, so draw a card will also take that parameter and pass it through to get rank, and then that extends to draw hand as well.

Oops, and now I need to update my calls to draw hand to take in that extra argument. Now that it's all working, what are the limitations of this approach? Well, the deck I modeled here isn't actually hateful. It's possible my hand has two Ace of Spades.

Depending on our use case, this might actually be a feature because some games use multiple decks or don't want players to count cards. But in other games where the rules strictly assume exactly one of each card, this might be a bug. For this collection of games, I actually think the simplification is pretty nice, but it might not be for someone else's use case.

More Articles

View All
Measuring angles with a circular protractor | Math | 4th grade | Khan Academy
Measure the angle in degrees. So here we have this blue angle that we want to measure in degrees, and it’s sitting on top of this circle. That circle is actually a protractor. Sometimes we see, and maybe what you’re used to seeing, is protractors that are…
How To Get Rich According To Richard Branson
There are a million ways to make a million dollars, and in this video, we’re looking at how the rebel billionaire himself, Richard Branson, did it. When he left high school, his headmaster told him, “You’re either going to become a billionaire or end up i…
Welcome to Earth | Official Trailer - Audio Description | Disney+
A six-part Disney Plus original series. Will Smith steps out of a red SUV. “I’ve got a confession to make,” words appear over a blue and green sphere from National Geographic. “I’ve never climbed a mountain,” Will repels down a volcano. Academy Award nomi…
The water cycle | Ecology | Khan Academy
Let’s talk a little bit about the water cycle, which we’re all familiar with. In fact, we’re all part of the water cycle every moment of our lives. We might not fully appreciate it, so let’s just jump into the cycle. I’ll start with evaporation. So, we c…
How To Become Whole (Carl Jung & The Individuation Process)
Conscious and unconscious do not make a whole when one of them is suppressed and injured by the other. If they must contend, let it at least be a fair fight with equal rights on both sides. Both are aspects of life. — Carl Jung. In my previous videos ab…
Building with the Brothers | Life Below Zero
♪ CHIP: You’re creating things, it’s so much fun. When you stop creating things, I think life just gets dull. ♪ ♪ ♪ (puppy barking) WILLIE: This is the last load, huh? CHIP: Yeah. So, we got the door. We got the insulation. We got plastic, but the w…