Project 8

blackjack

The Project

*** I accidentally destroyed parts of this page by overwriting it with the Roguelike project and don't have the energy to fix it right now, sorry!! ***

What’s A Roguelike?

In the old days, there was a game called Rogue. It looked like this:

The player’s character is the little yellow smiley face. Wikipedia says: In Rogue, players control a character as they explore several levels of a dungeon as they seek the Amulet of Yendor located in the dungeon’s lowest level. The player-character must fend off an array of monsters that roam the dungeons. Along the way, they can collect treasures that can help them offensively or defensively, such as weapons, armor, potions, scrolls, and other magical items. Rogue is turn-based taking place on a square grid represented in ASCII.

A lot of the ideas originally found in Rogue have since spread to tons of other video games, and we call those games roguelikes. Here’s a very complex one called Brogue:

In this project, you’ll be building a roguelike of your own.

How to Program a Card Game

This project comes with code for an extremely basic game. You’re the @ sign, you can move around, you can’t go through walls, and you can quit the game when you get bored. It looks like this:

#######################
#                     #
#                     #
#                     #
#                     #
#                     ###############
#                                   #
#                                   #
#                                   #
#                                   #
#                                   #
#                                   #
#############################  ######
                      #    @        #
                      #             #
                      #             #
                      #             #
                      #             #
                      ###############                                                                                                                                               

Please enter a command and then press Enter.                                                                                                                                        Available commands:                                                                       [u]p - move up                                                                            [r]ight - move right                                                                      [d]own - move down                                                                        [l]eft - move left                                                                        [q]uit - quit the game                                                                    
> 


Getting Started: Reading The Code

The starter code comes with three files:

1: level.txt

A simple text file. It’s the level! If you want the game’s level to look different, you can go ahead and edit level.txt.

For the starter code, a '#' is a wall, a ' ' is an empty space, and a '@' is the player’s starting position.

NOTE

Make sure your level is a rectangle, even if you have to put spaces at the end of a line.


2: roguelib.py

A Python file that contains some useful functions that can be combined together in order to make a simple roguelike game. Go ahead and read through this file - you don’t have fully read and understand every single line of code right now before you’ve started working on the project, but it’d be a good idea to look through the file and see what functions it defines and what their docstrings say the functions do.

You’ll have to make changes to some of these functions when you add new features to the game!


3: main.py

A small Python file that combines the functions from roguelib.py together into a simple game loop. Read the game loop and convince yourself that you understand how it works. Refer back to the code in roguelib.py whenever main.py uses a function that don’t fully understand.

Feel free to add more code to this file. You can also create more files to hold parts of your code, it’s a useful thing to do as your project gets bigger.

As a general rule: it’s hard to read and understand a big complicated file with 1000 lines of code in it and a vague name like program.py; it’s much easier to read and understand several smaller files, each of which has 150-200 lines of code and a good clear name like ai.py or physics.py or quest.py.

Seriously, Read Those Files

This is what programming in real life is like. It’s almost never the case that you’re starting a new program completely from scratch - you’ll almost always be working on a (probably really big!) program that someone else wrote years ago, or that you wrote a few weeks ago but it’s been long enough that now you don’t really remember what all the code does.

This is what you do: you read through the preexisting code, convince yourself that you understand what it does and how it fits together, and then, once you’re familiar with the codebase, you can start making changes and adding features.

The Goal

The point of this project is for you to come up with some cool features and then build them. Here are some ideas:

  • Monsters that just sit there and don’t do anything
  • A goal space (if the player makes it to this space, they’ve beaten the game!)
  • A combat system (when you bump into a monster, you fight it!)
  • XP / leveling up / stats
  • Monster AI (monsters follow you around!)
  • A combat log that says stuff like “you strike the skeleton for 3 damage!”
  • A dog that you can pet
  • Items / power-ups
  • Doors / traps
  • Spells / ranged combat
  • Puzzles
  • Quests
  • Randomly generated levels

That’s just some stuff off the top of my head. If you come up with an idea you like better, you can do that instead!


Dealing Hands

Now that your deck’s shuffled, you should deal two cards to the player and dealer so that they each have a hand, which is a list of cards like: [[10, "spades"], [5, "clubs"]]

Keep these hands in variables named something like player_hand and dealer_hand.


removing cards from the deck

Make sure that whenever you deal a card to someone, that card is removed from the deck. There should only ever be fifty-two cards at a time throughout your program—if the player has 2 cards and the dealer has 2 cards, then the deck should have 48 cards: 2 + 2 + 48 = 52.

You might remember Python's built-in pop function... it is really useful here because it both removes and returns the "top" card in the deck. You can do something like

card = deck.pop()

or

player_hand += deck.pop()

to take a card out of the deck and put it somewhere safe.


The value of each hand

You’ll also want to know how much each hand is worth so you know whether to hit or stand, or if someone busted.


It might help to create variables named something like player_count and dealer_count and update these variables whenever the player or dealer gets dealt a new card.

If player_hand is [[10, "spades"], [5, "clubs"]], then player_count would be 15.


You might also find it helpful to write a function called something like score_hand(hand) that takes a hand (a list of cards) and returns its score (a number like 12 or 3 or 25). That would make it so that you don’t have to maintain these player_count and dealer_count variables, since instead you could just call score_hand(player_hand) whenever you want to determine the player’s count. Up to you!

Displaying Output

You’ve done a lot of good stuff so far! Now let's show it as output.

Add a line to your program that uses the function called print_game_status() given in the starter code. This line should be after the cards are dealt to the player and dealer. You could also add it at the beginning, before dealing the cards, to show

At this point, your program should look like this when it’s run:

Your hand: [[10, 'diamonds'], [10, 'spades']]                                             
Your count: 20                                                                            
Dealer's hand: [[5, 'spades'], [5, 'clubs']]                                              
Dealer's count: 10                                                                        
Number of cards in deck: 48                                                               
------------------------------------                                                                                                                               

The cards and counts your program prints out will be different every time the program is run, so it’s fine that they’ll be different from what you see in the demo above.


Player’s Turn

Once 2 cards have been dealt to the player and dealer, it’s the player’s turn. In our simple version of Blackjack, the player has two options:

  1. The player can draw another card by saying "hit". They can do this as many times as they want, as long as their count is below 21. Each time the player says "hit", you should call print_game_status() after giving them a new card, so that they can see their updated hand.
  2. The player can end their turn by saying "stand".

Note: If the player inputs something that’s not "hit" or "stand" - for instance, if they enter the word "pizza" for their move - your program should not crash.

Note: If the player draws too many cards and their count goes over 21, that’s called “busting”, and it’s game over for the player. End the game immediately (don't let the dealer have a turn), call print_game_status() to print out the current state of the game, and tell them that they lost.


Your program should prompt the user for input over and over until they say "stand" or they bust, at which point their turn is over. You’ll want to use a while True: loop with one or more break statements in it. Print out something like "Do you want to 'hit' or 'stand'?" when you’re prompting the player for input.


Dealer’s Turn

Once the player has said "stand", it’s time for the dealer’s turn. Remember the dealer already has 2 cards.

Here’s what should happen during the dealer’s turn:

  • If the dealer’s count is less than 17, the dealer should draw cards until its count is 17 or higher.
  • If at any point dealer’s count is 17 or higher, the dealer’s turn immediately ends.
  • If the dealer’s count goes over 21, the dealer busts and the player wins.

Note: If the player busted during their turn, the game should end immediately and you should skip the dealer’s turn.


Once the dealer’s turn is over, you should call print_game_status() so that the player can see what happened. You can only call it a single time at the end of the dealer’s turn, you don’t need to call it every time the dealer draws a card.


Declare a winner

Once the dealer’s turn is over, compare the player’s count to the dealer’s count.

  • If the player’s count is higher than the dealer’s count, the player wins. You won!
  • If the player’s count is lower than the dealer’s count, the player loses. You lost :(
  • If the two counts are equal, it’s a tie! It's a tie.

Note: If the player busted during their turn, you should skip the dealer’s turn AND this count-checking phase. If the player busted, they lost the game, so in this case there’s no need to check their count against the dealer’s count.

Note: If the dealer busted during its turn, you should skip this count-checking phase. If the dealer busted, the player won the game (the player must not have busted or the dealer wouldn't have gotten a turn), so in this case there’s no need to check the player’s count against the dealer’s count.


The last line of your program’s output should clearly declare the outcome of the game.


Congratulations, you’ve implemented Blackjack!

Go through your program and double-check to make sure that you didn’t forget to implement anything.


Submitting your project

Before submitting your project, review the rubric and make sure to test your program a bunch of times to make sure it works!


Your CODE should follow the style guidelines. The part about descriptive names is important! For instance:

  • n is a bad name, username is a good one.
  • ns is a bad name, number_of_symbols is a good one.


On the first line of your code, write a comment with your name on it, like this:

# Tamara O'Malley


Submit your program on Google Classroom.

  • If you used repl.it, submit a link (it will look something like https://repl.it/@tomalley/Blackjack).
  • If you used IDLE, submit a file (name it like this: blackjack_yourname.py).


Most of the projects in this class were created by JR Heard, a TEALS volunteer at Madison, 2017-2019. His version of this project lives at https://blog.jrheard.com/python/blackjack.