CIT 591 Assignment 5: War (Card Game)
Fall 2010, David Matuszek
Play a game of War. The play will be computer vs. computer; all the human does is start the game.
Besides, no human above the age of about 6 will enjoy this game. At least, not if they're sober.
A deck of cards consists of 52 cards--13 each in four different suits. The four suits are called Spades, Hearts, Diamonds, and Clubs. Each card in a suit has a number from 1 to 13. Hence we have cards such as "the 4 of Spades" or "the 13 of Diamonds." (We do not have Ace, Jack, Queen, King cards, just numbered cards.)
There are two players, whom we will call Dick and Jane.
Here's how it goes:
Card: Represent a card as a two-tuple. The first element of the tuple is an integer between 1 and 13, inclusive. The second element of the tuple is one of the four strings 'Club', 'Heart', 'Diamond', 'Spade'. For example, (3, 'Heart').
Deck: Represent a deck as a list of 0 or more cards. A complete deck consists of all 52 possible cards.
Use Test Driven Design. You will find that almost all of these methods are extremely simple. That's okay--the idea is to get you used to writing tests first.
Write and test the following classes and methods.
class Card(object) -- represents one card.
Has a value and a suit.
__init__(self, value, suit) method). Legal values for value are the integers 1 through 13. Legal values for the suit are 'Clubs', 'Diamonds', 'Hearts', and 'Spades'. get_suit(self), get_value(self) and __str__(self) (to return a printable name for the card).compare(self, other_card) method that will return:
Card is numerically smaller than the other_card.Card is numerically equal to the other_card.Card is numerically larger than the other_card. class Deck(object) -- represents an ordered list of Cards. This is dual purpose--one deck represents the "full" deck of 52 cards, but they are dealt out to the Players, who then each have their own Deck of 26 cards.
fill(self) method to create and add all 52 possible Cards to its list.Deck knows how to shuffle itself (it has a shuffle(self) method).Deck knows how to deal(self, number)--that is, remove number Cards from itself and return a list of those Cards.Deck has a get(self) method, which removes one Card from its "top" and returns that Card to the caller.Deck has a put(self, card_list) method, which adds the Cards in the card_list to the "bottom" of itself.Deck has a size(self) method that returns the number of cards in itself. class Player(object) -- represents a person. There will be two players, dick and jane.
__init__(self, name) method). __str__(self) method to return the Player's name.Player knows how to take(self, card_list) a list of Cards and add them to its own Deck.Player knows how to play(self) a Card (take it from the top of the Player's Deck) and return it.Player knows how to count(self) the number of Cards it has.class Game(object) -- because somebody has to be in charge. Since this class needs to report (print out) what is happening as it happens, little or no unit testing is appropriate.
start() method to start up and run the game. Here's what it does:
Deck and the two Players.Deck and deals the cards to the two Players. start() do everything itself!
One way to begin is to create your war.py file with some or all of the methods in it, but each method is a stub: that is, it doesn't actually do anything. Then write a test for some method, run it and make sure it fails, then alternate between working on the method and working on its test, until you are satisfied with both. Then go on to the next method.
If a method depends on other methods (or its test depends on other methods), then you should write and test those other methods first. The more independent of one another your methods are, the easier this is. Highly interdependent methods, in addition to being bad style, are much harder to test.
Just to save you a bunch of typing, I have created "skeleton" files war.py and war_test.py that you can download.
Methods that return random results, such as the shuffle method, are harder to test, but not impossible.
For shuffle, you can test: