CIT 591 Assignment 5: War (Card Game)
Fall 2010, David Matuszek

# Purposes of this assignment

• To gain some initial understanding of classes and objects
• To give you experience with unit testing and TDD (Test-Driven Design)

# General idea of the assignment

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.

## The rules:

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:

1. The deck is shuffled. This randomizes the order of the cards, but there are still 52 different cards--no card ever occurs twice.
2. The cards are dealt. Each player gets 26 cards.
3. Play then proceeds as follows:
1. Each player takes the top card from his or her deck, and plays it.
2. If one card is numerically larger than the other, the player who played the higher-numbered card takes both cards and puts them on the bottom of their deck.
3. If the two cards are numerically equal, this is a "war." To fight a war, each player plays four more cards from the top of their deck.
1. It doesn't matter what the first three cards are; only the last (fourth) cards matter.
2. The fourth cards are compared, and if one is numerically larger than the other, the person playing the higher-numbered card collects all the cards and puts them on the bottom of their deck.
3. If the two (fourth) cards are numerically equal, the "war" continues--each player plays four more cards, and the last cards played are compared.
4. Play continues until one player has all the cards, and wins.
• Since an actual game of war typically takes over an hour, your program should just play, let's say, about 25 times (counting a war as 1).

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 `suit` and a `value`.
• The class should have a constructor (an `__init__(self)` method).
• The class should have methods `get_suit(self)`, `get_value(self)` and `__str__(self)` (to return a printable name for the card).
• The class should have a `compare(self, other_card)` method that will return:
• A negative number if this `Card` is numerically smaller than the `other_card`.
• Zero if this `Card` is numerically equal to the `other_card`.
• A positive number if this `Card` is numerically larger than the `other_card`.
• `class Deck(object)` -- represents an ordered list of `Card`s. This is dual purpose--one deck represents the "full" deck of 52 cards, but they are dealt out to the `Player`s, who then each have their own `Deck` of 26 cards.
• The class should have a constructor to create an initially empty list of cards.
• The class should have a `fill(self) `method to create and add all 52 possible `Card`s to its list.
• A `Deck` knows how to shuffle itself (it has a `shuffle(self)` method).
• A `Deck` knows how to `deal(self, number)`--that is, remove `number` `Card`s from itself and return a list of those `Card`s.
• A `Deck` has a `get(self)` method, which removes one `Card` from its "top" and returns that `Card` to the caller.
• A `Deck` has a `put(self, card_list)` method, which adds the `Card`s in the `card_list` to the "bottom" of itself.
• A `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`.
• The class should have a constructor (an `__init__(self, name)` method).
• The class should have a` __str__(self)` method to return the `Player`'s `name`.
• A `Player` knows how to t`ake(self, card_list)` a list of `Card`s and add them to its own `Deck`.
• A `Player` knows how to `play(self)` a `Card` (take it from the top of the `Player`'s `Deck`) and return it.
• A `Player` knows how to `count(self)` the number of `Card`s 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.
• The class may need a constructor; detail are up to you.
• The class should have a` start() `method to start up and run the game. Here's what it does:
• Creates the `Deck` and the two `Player`s.
• Shuffles the `Deck` and deals the cards to the two `Player`s.
• Tells each Player when to play, keeps track of which cards are played, decides who won or lost (or if there is a war), and tells the winning player to take the cards.
• Tell (print out) what is happening.
• Stop the game after a reasonable time.
• Helper methods. Don't make` start() `do everything itself!
• If any method needs to do a significant amount of computation, try to make it I/O free so that you can test it.

# How to begin

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.

# Randomness

Methods that return random results, such as the `shuffle` method, are harder to test, but not impossible.

For `shuffle`, you can test:

• Whether your result consists of all 52 cards, in some order.
• Whether the cards are in a different order than before you shuffled them. (This isn't totally reliable, since there is a 1 in 80658175170943878571660636856403766975289505440883277824000000000000 chance that a totally random shuffle will leave the cards in the original order, but for class it's probably good enough.)

# Due date

Thursday, October 14, before midnight. Hand in one project with both your names on it; zip up the entire project directory and hand it in via Blackboard.