Week 10 Lab

Goals:

In this lab, we will implement a computer model for a playing card, a deck of playing cards, and a very simple version of the card game War.

Step 1: Getting started

Open Eclipse, switch to S:\workspace, make a new folder called lab10. In this, create a new file called card.py.

In this lab we are going to be manipulating tuples a lot. Recall that a tuple is very similar to a list, except that it is immutable -- i.e., it cannot be changed after it has been created. But, like lists, you can index a tuple, search a tuple, etc. To create a tuple you use parentheses and a comma:

aTuple = (3, 'D')

anotherTuple = ('this', 'is', 'a', '4-ple')

You can index a tuple to get parts out of it:

print("The number is", aTuple[0])

Step 2: Create function newCard()

A playing card has two important properties: its number and its suit. Its number is 2 - 10, J, Q, K, A, and its suit is one of Hearts, Clubs, Diamonds, Spades. We can model a playing card as a simple tuple. (Why use a tuple instead of a list of 2 items?) Then, we can do all kinds of interesting things with cards: create them, sort them, deal them, compare them, etc.

Let's start with a function to create a card. This function is what we'll call a "constructor" function.

Name newCard Creates a new card and returns it.
Input Parameters
  • number
  • suit
  • an integer 2 - 14 representing the number. An 11 represents a Jack, 12 is a Queen, 13 is a King, and 14 is an Ace.
  • a single character representing the suit: one of "H", "D", "C", "S".
Return Value a tuple

the first item in the tuple is the number, the second item is the suit

Implement the above function. NOTE: make sure you create a nice docstring for this function, and for all subsequent functions in this assignment for the rest of this course!

NOTE: I know this is a silly little one-liner function. But, hey, you have to start somewhere!

Step 3: Test newCard()

Next, we'll have some code to test the above function. In the "main code" portion of the file, add this magical code:

if __name__ == "__main__":

Inside this if statement, write a function call or two to test your newCard function. Use assert to test the results of the function calls. E.g.,

if __name__ == "__main__":    # unit tests below
card = newCard(3, "D")
assert card == (3, 'D') # if the value of card is not this tuple, we have a problem!

Note: when run your code, if you see NO errors, that means that the above assert calls succeeded. That is good. If you see an AssertionError, that means that the comparison did not succeed. You need to figure out what went wrong and fix it.

Step 4: Create cardToString()

Now, let's create a function to generate a nice string representation of a card, so that we can print it in a nice readable format.

Name cardToString Returns a string representation of a card
Input Parameters a card tuple  
Return Value a string

a string, like this: "3 of Hearts", or "Ace of Spades". Remember that 11 is a Jack, 12 is a Queen, 13 is a King, and 14 is an Ace.

This function has a good amount of code in it. Think about what you have to do:

HINTS:

Add code to your unit test area at the bottom of the file, to test this new function on a couple of cards.

Step 5: Create newDeck()

Now, we need to create some more functions. Let's first create a function to create a deck of cards. The deck will be implemented as a list of the card tuples.

Name newDeck Creates a new deck of cards, stored in a list, and returns it. The cards are tuples, of course.
Input Parameters None  
Return Value a list of tuples

The tuples represent cards. They are 2 - 14 of Hearts, then 2 - 14 of Spades, then Clubs, then Diamonds. I.e., the list looks like
[ (2, 'H'), (3, 'H'), (4, 'H'), ... (14, 'H'), (2, 'S'), (3, 'S'), ... etc. ]

Notice the ordering of the deck: 2 through Ace of one suit, followed by 2 - Ace of the next suit, etc. To implement this, you'll need nested loops, and call newCard() to create each card.

Testing this code is difficult. Just put a print statement in the main code to print out the deck, so that you can see if it looks right. One test would be to assert that there are 52 cards in the list.

Step 6: Create shuffleDeck()

Decks need to be shuffled, of course. Create this function:

Name shuffleDeck Shuffles a deck.
Input Parameters list of card tuples  
Return Value None

The given deck (list) is shuffled. Use a really handy function in the random module called shuffle().

Add code to test this -- at least print out the shuffled list to make sure it is shuffled. Note that you call this function this way:
shuffleDeck(aDeckYouCreated)

The code will shuffle the input parameter "in place" -- i.e., it will change the parameter and not return anything.

Step 7: Create compare()

When we play cards, we are always comparing cards against each other. So, we need a function to do this.

Name compare Compare two cards against each other.
Input Parameters
  • card1 (a tuple)
  • card2 (a tuple)
  • a card
  • another card
Return Value integer

If the first card has a lower value than the second card, return -1. If they have the same value, return 0. Otherwise, return 1. For this exercise, value is simply determined by the card's number, not its suit. Ace is high.

Write tests to make sure this is code is correct.

Step 8: Create the main code to simulate War

Now, we have a nice set of functions that operate on card "objects". We need some code to do something with those cards.

Create a second file called main.py. In this file, at the top, put this code:

from card import *

This line pulls in the functions you created in card.py.

Now, let's first implement a very simple game of war. The algorithm follows, but first look at these hints:

HINTS

Algorithm:

  1. Create a deck of cards.
  2. Shuffle the deck.
  3. "Deal" every other card off the deck to two players' hands. (How will you represent a player's hand?)
  4. while neither hand is empty:
    1. pop the two cards off the players' hands. Store these in variables.
    2. compare the cards. If player 1's card wins, put both cards at the end of player 1's hand, in this order: player 1's card, then player 2's card.
      else If player 2 wins, put both cards at the end of player 2's hand, in this order: player 2's card, then player 1's card.
      else If they are the same, pick a random number, 0 or 1. (To get a random number, 0 or 1, google "python random" and do a bit of studying there.) If you get a 1, player 1 gets both cards. Otherwise, player 2 gets both cards. Put the cards back into the player's hand in the order specified above.
    3. In the above step, add print statements so you can see what is happening.
  5. When one player wins, print out who won!

Extra credit:

  1. Replace the code for when the cards are the same -- i.e., when there is a war. Make your own rules for what happens in this case, and document this thoroughly in a comment. NOTE: this is a good challenge.

Step 9: Submission

Add your standard comment to the top of the file, describing who you are, what the date is, and what the assignment is.

To submit your final version of card.py, you’ll need to use Windows Explorer.

 


Grading Rubric: 15 points total (18 with extra credit)

10 points: program that runs correctly.  There are many parts to handle in this program, so make sure all work correctly.
1 points: correct comments at the top of the file.
2 points for good tests in the testing portion of card.py
2 points: code is clean and neat and uses good comments and variable names. I.e., the code is hospitable.

Extra credit points: 3 points for correct implementation.