CSC108H Assignment 3, Summer 2012

Part 1 Due 2012-08-11 23:55

Part 2 Due 2012-08-13 23:55

Introduction

The purpose of this assignment is to give you practice with classes, testing, and with raw input to get information from the user. The focus is not on inheritance, but rather in how classes allow us chunk problems into simpler bits of code.

You should spend at least one hour reading through this handout to make sure you understand what is required, so that you don't waste your time going in circles, or worse yet, hand in something you think is correct and find out later that you misunderstood the specifications. Highlight the handout, scribble on it, and find all the things you're not sure about as soon as possible.

It is probably worth spending at least a day thinking about the assignment before writing code of any sort. Try to think through potential problems to catch them before they appear. This will save hours of frustrating debugging time.

Overview

You've been tasked with writing a very basic blackjack game, along with some test for the parts of the game that don't require direct input from the user. This assignment has two parts - writing the test cases, and writing the blackjack game itself.

Blackjack

Blackjack is a simple betting card game played with a standard deck. A card in a standard deck has a suit and a value. The suit may be one of the four following options: Club, Diamond, Heart, Spade. The value may be one of the following 13 options: Ace, 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King. We will implement a very simple version of blackjack with one player and one dealer. They will each start with some non-0 amount of money specified by the user. The amount of money can be different for the player and the dealer. These two players will play rounds of blackjack until either the player or dealer have no cash left or the player decides to finish the game. At least one round of blackjack will be played.

A round of blackjack proceeds as follows. First, the player decides how much money they are willing to bet this round. Then, this amount of money is added put into a 'pot' by both the dealer and the player. Two cards are then dealt to the dealer and the player. The player's two cards are revealed. The player is then free to hit until either the score of their hand is over 21 or they decides to stay. A hit by the player means that they are dealt one more card, and their hand size is increased by 1. A stay means the player is happy with their hand and does not want any more cards. A player is free to stay with their two initial cards, and can hit as many times as they like. When the player has stayed, the two cards of the dealer are revealed. The dealer is then free to hit/stay in the same way as the player. When the dealer has finished, the pot goes to whoever has the highest scoring hand whose score does not exceed 21. If both the dealer and the player have the same score, then the pot is split between them.

The score of a blackjack hand is calculated as follows: 10 for each face(Jack, Queen, King) card in the hand. Cards with number values are worth the number on the card. (So a 2 of clubs is worth 2, a 5 of diamonds is worth 5, and so on). Aces are worth either 1, or 11, depending on what gets the score closest to 21 without going over. If the hand of a player or a dealer goes above 21, then the player or dealer is said to bust. The suit of a card plays no role in blackjack.

Your task

This assignment includes two parts - one is writing the code, the other is writing the test cases. Because the point of the assignment is to get comfortable with using classes, a lot of the class structure is enforced. First download the following files: cards.py and blackjack.py. You will note that each of these contains several classes, with several method stubs. Your job is to complete the method stubs. You may write additional helper functions/methods if you find it useful. You should not change the order of the classes. You are to update the docstrings/change the variable names. We will go through these by file and by class.

First we look at cards.py. This file contains three classes: Card, Deck and BlackjackHand.

Card is a class we define to represent playing cards. It has two instance variables, value which is a str that contains the value of the Card object, and suit which is a str that contains the suit of the Card object. You need to implement the following methods:

Note that we don't put any restrictions on the values and suits of the card. These restrictions are made in the Deck Class. Conceivably this would allow us to use our card class for other decks that have different types of cards. Our Deck class represents a regular deck of playing cards. You should have an instance variable that is a list of Card objects to represent these cards. You may find it useful to have other instance variables as well. You need to implement the following methods:

The last class in cards.py is BlackjackHand. This class represents a hand of blackjack. This hand may belong to a player or a dealer. It also contains cards, but does so in a very different way than a deck. You need to implement the following methods:

blackjack.py contains more complicated classes. These classes are: BlackjackPlayer, BlackjackDealer, BlackjackGame.

BlackjackPlayer is a class that represents the player playing the game. This means that a lot of the functions will ask for user input. You are required to ensure that the input obtained from the user is legal. It must have an instance variable cash that represents how much money the player has. It must have an instance variable hand to represent the player's hand. You need to implement the following methods:

BlackjackDealer is a complementary class to BlackjackPlayer. This class represents the dealer. It differs from the player in that the dealer is not a human player. None of the methods in this class should require user input. It also differs from the player in that a BlackjackDealer contains a deck that is used to deal the cards. Note that in practice, blackjack dealers often draw their cards from several decks to prevent card counting. To somewhat model this, we allow a BlackjackDealer to use several decks to draw cards from. This class must have an instance variable cash that represents how much money the dealer has. It must have an instance variable hand to represent the dealer's hand.You need to implement the following methods:

The final class is called BlackjackGame. This class should control the interactions between the player and the dealer. Of particular importance is the instance variable which represents the literal pot. The code skeleton given is structured in such a way that money should never go directly from the player to the dealer or vice versa. Money should go from the player and dealer into the pot, and then back to the dealer or player. Your task is to complete the following methods:

This assignment has two parts. For the second part, you need to complete the methods listed above. For the first part you need to create test files that use nose for Deck, BlackjackHand, and BlackjackDealer. These should be submitted in a zip archive called tests.zip. Each test file should have the word test as part of it's filename. You do not need write tests for Card as it is too simple to create meaningful tests for. You do not need to create tests for BlackjackPlayer and BlackjackGame as these classes require user input to test. Your tests should not require user input. You will note that the tests are due before the assignment. This is to think about tests early. We will run your tests against your code.

Additional requirements

Clarification

How to tackle this assignment

Here is our suggestion. First download the code from cards.py and blackjack.py. Some of the more simple Classes like Card can be finished immediately. Beyond that, you should break up the larger more complicated methods into chunks. Imagine how you would solve the problem with real world objects. Then transfer those ideas to virtual objects. One of the advantages of using Objects, is that they are a powerful abstraction that allows us to apply 'real world' logic to computer problems. Finally, make sure you write the tests before writing the code. Thinking about how to break classes, and how the classes behave in corner cases should allow you to develop a good intuition for how they are meant to be used.

Principles:

Marking

These are the aspects of your work that we will focus on in the marking:

Submitting your assignment

Submit a file named tests.zip to markus for the first part. For the second, submit two files - one named cards.py, and another named blackjack.py. Once you have submitted, be sure to check that you have submitted the correct version; new or missing files will not be accepted after the due date.

If you wish to work with a partner, one of you needs to invite the other to be a partner, and then they need to accept the invitation. To invite a partner, navigate to the Assignment 2 page, find "Group Information", and click on "Invite". You will be prompted for the other student's cdf user name; enter it. To accept an invitation, find "Group Information" on the Assignment 2 page, find the invitation listed there, and click on "Join". Note that, when working in a pair, only one person should submit the assignment.

Remember that spelling of filenames, including case, counts. If your file is not named exactly as above, your code will receive zero for correctness.