Exercise 6: Solitaire

To get some practice with lists and loops, this week you'll be writing a basic card game.

  • solitaire.py - as with last week's t_test.py, this is the program that will run. Note: this program is uncommented; I encourage you to go through and add comments for your own understanding.
  • gameBoard.py - implement some functions to complete the game in solitaire.py. This part may be completed in pairs if you wish.
  • Conditions Practice - a brief problem set on Learn@UW (under Quizzes) to practice evaluating boolean expressions.

Conditions "Quiz"

This week we'll have a brief problem set with some conditions for you to practice evaluating - it's available under Quizzes on Learn@UW.

You will have two attempts on this quiz — I recommend trying at least the first time with paper and pencil. This is intended to help you pinpoint your misunderstandings with booleans and conditions! Jumping right to coding up your responses will help you on this homework, but may hurt you on the next exam.

Anyway! Back to programming:

program background

This is a peculiar but very simple game in which the player makes only ONE choice: where to begin. The number on the card that you draw (ignoring suit) will determine which pile you draw your next card from.

The object of the game is to pick up all of the cards.

Here are the first few moves of a game using our interface:

The next move would be to pick up card C7 from pile 11 - see if you can figure out why.

program requirements

To begin, download solitaire.py and our simple skeleton for your code, gameBoard.py, and put them in the same project (as you did last time). You'll be adding your code to gameBoard.py.

In high level terms, your gameBoard.py file will:

  1. Create each card as a two-character combination of a suit (C, H, S, or D) and a value (0-9, J, Q, or K). This code has been written for you.
  2. Deal the cards out into piles on the game board.
  3. Determine whether a provided board is in a win state (no cards left) or a loss, and return a message.
  4. Format and display the current contents of the board.
  5. Check whether a pile has any cards left in it.
  6. Translate a two-character card value to a numeric pile value.

And the specifics:

Translating a card

The argument to num_on_card(card) is a two-character card string in the format suit+value, such as CK (king of clubs).

The return value from this function should be the numeric value of that card, where Jacks (J) are 10, Queens (Q) are 11, and Kings (K) are 12. If I were calling this function from the interpreter:

>>> num_on_card('CK')
12
>>> num_on_card('S0')
0
>>> num_on_card('HJ')
10

Dealing the cards

IMPORTANT: you must follow these steps EXACTLY, in order for us to be able to grade your code effectively.

The board for this game should be constructed as a list of 13 piles, one for each card value. Each pile, too, should be a list of 4 card strings.

To deal out the already-shuffled cards:

  1. Create a board list. This is what you will put the piles into.
  2. For each of the 13 piles, create a list:
    1. append the current last card in the cards list - try using the pop() function without an argument to get the last card in a list AND remove it from the list simultaneously!
    2. once the pile has 4 cards in it, append it to the board list.
  3. Once all 13 piles are complete, the cards list should have length 0.

Note: if you do anything differently, your results will be different. If I were calling this function from an interpreter:

>>> get_board(0)
[['D4', 'SK', 'H8', 'CK'], ['HQ', 'H6', 'SJ', 'H0'], ['H7', 'HK', 'DQ', 'DK'], 
 ['CQ', 'S3', 'HJ', 'C9'], ['S6', 'S8', 'S1', 'D2'], ['D6', 'H9', 'S0', 'D7'],
 ['D5', 'C2', 'D0', 'H2'], ['DJ', 'S4', 'CJ', 'H5'], ['C5', 'D8', 'S5', 'C0'],
 ['D3', 'S2', 'D1', 'C8'], ['H3', 'H1', 'D9', 'S9'], ['H4', 'C6', 'C1', 'C7'],
 ['S7', 'C4', 'SQ', 'C3']]

YOUR RESULTS SHOULD MATCH THESE EXACTLY. If you have any questions, please ask!

Checking a pile

Every pile in the board is a list - if that list variable's name were just the argument i, you'd be able to tell easily if it were empty, right? Well, now its name is board[i], so it's still perfectly easy.

Return True if it's empty, False if it's not.

Win or lose

If there are no cards left on the board when the check_board(board) function is called, you should return the win message. If there are cards left, you should add that number to the loss message and return it.

As you saw in the previous lab, to add a number to a string that contains %d, you can use code like this:

>>> x = 'This is a number: %d' % len('number')
>>> x
This is a number: 6

That is, after the string, add the % operator and whatever literal, variable, or calculation you want to appear in the string instead of %d.

Print the board

When a card is picked in this game, it's popped from the pile - that means that the last card in the list is used, so the end of each list should actually be at the top of the displayed board.

Here's how I thought about this:

  1. For each possible pile position, starting at the end and going to the beginning:
    1. For each pile in the board:
      1. Is this pile long enough to have this position? If not, print two spaces.
      2. If this pile IS long enough, print the card at that position.
    2. Once you've printed all the cards at that position in the pile, start a new line.

Again, if I were calling this function from an interpreter:

>>> print_board(get_board(0))
*************************************** Top
CK H0 DK C9 D2 D7 H2 H5 C0 C8 S9 C7 C3
H8 SJ DQ HJ S1 S0 D0 CJ S5 D1 D9 C1 SQ
SK H6 HK S3 S8 H9 C2 S4 D8 S2 H1 C6 C4
D4 HQ H7 CQ S6 D6 D5 DJ C5 D3 H3 H4 S7
*************************************** Bottom
00 01 02 03 04 05 06 07 08 09 10 11 12  Pile

YOUR RESULTS SHOULD MATCH THESE EXACTLY. If you have any questions, please ask!

Commenting your code

Once again, some of your program points will come from commenting your code.

  • Add a 1-2 sentence description of the program and its function to the top of your code.
  • Include comments within your code describing what you're doing. You don't need to comment on every line of code, but be clear in your explanations.

Submitting your files

As usual, you'll be handing in your lab work via the course Learn@UW dropboxes. Navigate to our 301 course page, and click the Dropbox link in the top navigation bar. You should see a dropbox for Program 6 - this is where you should hand in your gameBoard.py file. You will ONLY submit gameBoard.py.

If you worked in a pair, only one person will need to hand in the code.

Note that the dropbox will close at noon on 10 March, so be sure to submit your files before then.