This repository contains an object oriented implementation of a simple card game. The rules are a simplified version of war:
- Cards are evenly divided among the players.
- Players play a card from their hands simultaneously, the player with the highest card gets a point
- Ties are broken with a coin flip
- The game is over when the players run out of cards, which are not recycled.
The program can be run in the console with python main.py
. This is the entry point of the program. Begin there and investigate the code. Here is the class diagram. The first box contains the class name, the middle box contains the class attributes and properties, and the bottom box contains the class methods.
classDiagram
class Card{
value: int
suit: str
beats(card: Card)
}
class Deck{
cards: list[Card]
@property has_card: bool
reset()
deal_card()
shuffle()
}
class Player{
name: str
hand: list[Card]
win_rate
@property has_card: bool
@property win_rate: float
play_card()
}
class Game{
player_1: Player
player_2: Player
deck: Deck
distribute_cards()
play()
}
These tasks are designed to exercise not only how well you can write code, but how well you understand the existing code and how it can be modified. This type of activity is far more common than writing code from scratch, and gives you a starting point that you can emulate as you learn about Python.
Use these tasks as a warm up as you familiarize yourself with the codebase:
- Get player names from the user using the
input
function - Print the player win rate as a percent, rounded to the 2nd decimal place
- You could write this as a helper function in the
Player
class
- You could write this as a helper function in the
- Rewrite the list comprehension in
Player.win_rate
to use a regular for loop - Rewrite the
Deck.shuffle
method to not call the builtinshuffle
function (you'll need to use a loop!)- Bonus: try doing it without creating a new list
The Card
class currently has suit
and value
attributes. Add another attribute called name
. This attribute should be the text representation of the value according to the following table:
Value | Text |
---|---|
1 | "Ace" |
2 | "Two" |
3 | "Three" |
4 | "Four" |
5 | "Five" |
6 | "Six" |
7 | "Seven" |
8 | "Eight" |
9 | "Nine" |
10 | "Ten" |
11 | "Jack" |
12 | "Queen" |
13 | "King" |
Right now the player's hand is implemented as an attribute which is list of Card
objects within the Player
class. Your job is to refactor this code into its own class.
- Move this and all methods /properties related to this attribute into their own class called
Hand
. - Give
Player
an attribute of typeHand
. - Give player a method
add_card_to_hand
- Update the code that deals cards to players to use
add_card_to_hand
Currently, only two players are supported in the Game class. Make it so that up to 8 players can play at once.
Implement rules for a different game. You may have to completely rewrite the distribute_cards
and play
method in the Game
class. Some possibilties:
- Guessing Game: Deal a card from the deck and allow each player to guess the value. The closest player gets the card, and the player with the most cards at the end wins. If players have the same guess, they must try guessing the suit. If they tie or no one guesses the right one, no one gets the card. Otherwise, whoever guesses the suit gets the card.
- Crazy Eights (basically UNO)
- Any kind of poker
Hopefully you've been testing your changes as you make them, but it can get repetitive to have to go through all the steps to reproduce the behavior you want to see. That's why we have testing frameworks which allow us to write scripts that we can execute repetitively and deterministically. We'll be using the pytest framework. In the /tests
directory you'll find two tests already written.
- Run them in the terminal with
pytest
. - Generate a coverage report with
coverage run -m pytest
- View code coverage in the terminal with
coverage report -m
- Generate an HTML coverage report with
coverage html