Uno Lab
Overview
Growing up, Uno was one of Mr. Wolf’s favorite card games. Everywhere he went it seemed like we ended up playing Uno – with his friends, with his family, even with his classmates.
However, when he got older he stopped liking Uno because he thought it was all random, there was no strategy to winning.
But in this lab, you are going to prove him wrong.
Your tasks:
- Learn about how class inheritance works in Python
- Play and redesign the uno game
- Add special cards to make the game more interesting
- Write a strategy to beat a random computer player
If you’ve never played Uno before or haven’t played it in a while, you might want to try out this online version before you get started.
[0] Setup
💻 In your cs9/unit_02 directory, clone the lab-uno repository inside it.
cd cs9/unit_02
git clone https://github.com/the-isf-academy/lab-uno-YOUR-GITHUB-USERNAME.git
💻 In the lab directory, install the packages you need to run this lab by running pip install --upgrade -r requirements.txt.
[1] Classes and games
In this lab, we’ll work to solidify our understanding of classes and objects by using a text-based game, Uno, as an example.
More OOP in Python
To get started, we need first need to learn how to write a class in Python.
👀 Explore the following resources:
- Creating a Class: 12.5 Constructors
- Inheritance: 12.6 Inheritance
Modeling Inheritance
Let’s consider our model of a video game character from the bank lab.
Imagine our game has two types of characters: a player character and a non-playable character (NPC). Both types of characters should have the same properties and methods as the base Character class, but each will have additional unique attributes. For this, we can utilize inheritance.
Both the Player class and the NPC object will inherent the characteristics from the Character class and extend it to include additional features.
Map out the Uno software
Uno is a pretty significant software project - there are more classes than you’ve seen before. Fortunately, Uno’s functionality is well documented.
✏️ With your new understanding of classes and inheritance, read through the documentation pages and draw a model with your partner for how this implementation of Uno works.
For your reference, Uno has the following classes. Make sure your model includes each of them.
[2] Let’s play Uno!
The rules of Uno are pretty simple: players take turns trying to play cards from their hand. You can play a card if its color or value matches the color of value of the last card that was played. If you can’t play a card, you have to draw a card. The first player to play all their cards wins.
If you’re interested, you can find the full rules of Uno here. Our implementation varies slightly. Can you identify the differences?
Play through
💻 Now that you’ve got a model for how the Uno software should work, play through a game by running the following command in your terminal:
python game.py
Note: we’ve given you a few different decks of cards. Start with the basic deck. We’ll use the others later.
Was the gameplay different than you expected? Check you model to see if it still makes sense and change it up if it doesn’t.
Reskin
One potentially confusing part of the software is the View class. What is it and why is it important?
In many games, it’s useful to separate the logic of the game from the user interface of the game. This lets developers easily change the interface without having to mess around with the rules or state of the game. In our Uno software, View does just that.
Playing around with the View class will help you get a sense of how classes can interact in python. The View object knows nothing about the state of the game but delivers messages to users nonetheless.
💻 Reskin the Uno game by changing up the messages delivered to the user in view.py.
Maybe you want to translate the game into Chinese or make the game have an attitude. You could even try writing the game to speak in the voice of one of your favorite characters (“Aye Aye, Player 1, two Krabby Patties comin right up for Player 2!").
[3] Amp it up: special cards
Now that you’re starting to get the hang of the game, let’s make it a little more interesting with special cards.
Special cards
Uno would be pretty boring if you just went around in a circle matching colors and numbers. Fortunately for you, dear player, Uno has special cards that make the game more interesting:
- reverse: changes the direction of play from clockwise to counterclockwise or vice versa
- skip: skips the next player’s turn
- wild: can be played on any card and lets the player call the color to be played next
- draw-two: forces the next player to draw two cards (they still get a turn)
- wild-draw-four: the current player calls the color and the next player has to draw 4 cards
Other than the wild cards, all of the special cards have colors and must be played following the color/value matching rule of the game.
We’ve already implemented some of the special cards for you.
💻 Try playing again, but this time use the uno_cards_no_draw.csv deck.
Writing the special card functions
Pretty different right? Your job is to finish implementing the special cards by writing the code for:
💻 Implement the draw_two() and wild_draw_four() functions near the bottom of the game.py file in the UnoGame class.
- Note: you will also need to make sure the game calls these functions by adding calls to them in the special_card_action() function.
💻 Testing your functions by running the following scripts
- You can test the
draw_two()function by runningpython test_lab.py -k draw_two. - You can test the
wild_draw_four()function by runningpython test_lab.py -k wild.
[4] A winning strategy
Now that you’ve got a fully functional Uno game, you can start thinking about the best strategy to win games.
Write ComputerPlayer class
In this final part of the lab, you should write an extension of the ComputerPlayer class which plays Uno with a strategy that you design.
Your goal: to consistently win more than 30% of games against 3 other computer components who are using a random valid choice strategy.
Before you jump into coding this part, you should think about the rules and mechanics of Uno. Given a hand of cards, what would make playing one card better than playing another card? You might also want to go over inheritance one more time as your StudentComputerPlayer class will be a child class of the ComputerPlayer and will inherit all its properties and functions.
💻 Implement your StudentComputerPlayer class in the player.py module.
💻 Test your strategy by running python test_lab.py -k strategy
Deliverables
For this lab, you should push your lab-uno repository containing updates to the following files:
view.pygame.pyplayer.py