CS21 Lab 6: Rack-O (TDD)

Design is due Saturday, April 3, before midnight

Full Implementation is due Saturday, April 10, before midnight

Goals

  • practice using Top-Down Design

  • write a complex program, with multiple functions, from scratch

Notes

Please read through the entire lab before starting!

This is a two-part lab, split over two weeks. For the first week you will focus on using top-down design to create the overall structure for the program. Once your proposed structure has been reviewed and approved by your professor or lab instructor, you will use bottom-up implementation to complete the full program.

You may work with a partner on the first part described above. Please be sure to let us know who your partner is or if you need a partner. Once the top-down design (the first part of the two-part lab) is complete, you and your partner must complete the implementation of the program (part two of the two-part lab) on your own.

You have two weeks to complete the full program. The first week is for the design, and the second for the full program. Your initial top-down design is due on Saturday (April 3) and the full implementation the following week (April 10). It is highly recommended that you submit your top-down design as soon as is possible so that we have time to give you feedback before you begin your full implementation. If you submit your design on the last day at midnight, it might take us a few days to get to it and send you comments.

Rack-O

In this lab, we will reimplementing a 1950s game called Rack-O. You can watch a classic Rack-O commercial from the 1950’s! Or you can watch a modern how to play Rack-O video that explains the basic rules.

Both videos show the game being played as a four player game, but we will implement the solitaire version in this lab.

Here are the rules for a solitaire (one-player) game, adapted from the original Parker Brothers rules:

  • Rack-O is played with a deck of cards numbered 1 to 40 which should be shuffled before each game.

  • You are given a rack that holds 10 cards.

  • You are dealt 10 cards. Cards must be placed in your rack in the order the cards were received: the first card goes in the first slot in the rack, the second card goes in the second slot, …​ and the tenth card goes in the tenth and final slot in the rack. You can not re-arrange the cards in your rack.

  • The remaining cards form the draw pile.

  • The top card of the draw pile is placed face up in the discard pile.

  • Each turn, you must choose to do one of the following:

    • Take the face-up top card of the discard pile. If you do, you must exchange it with a card in your rack. To exchange a card, first you select a card in your rack to discard. You remove that card and replace it with the card from the discard pile. The card you removed is placed in the discard pile.

    • Take the face-down top card of the draw pile. you may either exchange this card with a card in your rack or discard this card into the discard pile.

  • At the end of your turn, the discard pile is shuffled back into the deck and a new face-up card is placed in the discard pile.

  • Once you have all of your cards in ascending order from the first position of your rack to the last, you win! Try to do this in the fewest possible moves!

Examples

Here are a few examples of the running program to help you see how things should work. Pay attention to how the game proceeds, and how input from the player is handled. As you can see from these examples, there is no graphical component to the game: everything will be played through the terminal.

The examples above include these features:

  • Ensuring the user provides valid input (you can assume the input is always an integer)

  • Correctly replacing cards in your rack with cards from the draw pile and discard pile

  • Ending the game when the user has Rack-O or if they specify that they want to quit

Requirements

You have some freedom in how you want your game to look. Here are our requirements for the full program:

  • As part of your top-down design, your main function should have a loop that plays the game. The body of this loop should contain more than just a call to one or two functions. Instead, it should contain multiple function calls and other code that implements various parts of a single round.

  • The player should be prompted to take their turn with an informative prompt.

  • Legal choices made by the player should be handled properly and the rack should be displayed to the player at the beginning or end of each turn.

  • If a player enters an illegal value, they should be given an informative message.

  • When the game ends, display a status message saying how many turns it took the player to win (or quit).

  • All output should be clean and easy to read.

Top-Down Design Requirements

You should complete your top-down design (TDD), submit it (run handin21), and obtain feedback on it before beginning the full game implementation. Special procedures for this two-week lab:

  • create your design in design-racko.py first

  • after you have a working design (see example below), run handin21 to turn it in! Then send a short email to tdd@cs.swarthmore.edu, letting us know your design is done. We will take a look at each design and send you comments (usually within a day or two). If the design is incomplete or insufficient, you may be asked to submit a second design.

  • after you have the design done and have heard back from us, please copy the design file to racko.py and implement the full game in racko.py (i.e., leave design-racko.py as is!)

    cp design-racko.py racko.py
  • please ensure your design meets the following requirements before submitting:

    • main() should be completely written, and should perform high-level steps without focusing on details

    • main() should call the functions you create in your design, in the appropriate order, and with arguments that match parameters. Return values should be saved in main(), even if you don’t do anything with them yet.

    • all functions should be stubbed out with parameters, a block comment, and a return statement. They don’t need to actually do anything yet, except possibly call other functions.

    • if your function is meant to return something, you should return a reasonable value of the appropriate type (e.g., return 0 for an int, or [1,2,3] for a list).

    • your design should have several functions. Each function should be function worthy (i.e., not a trivial task) and also demonstrate encapsulation (one clearly defined purpose).

    • the design should run without syntax errors (although it doesn’t play the full game yet)

Your goal for the design is to completely write main(), such that it won’t need to change much as you implement and test all of the other functions.

If you are confused about how the top-down design should look, please see the following examples of a design and full program for a simple guessing game program.

Tips

Note: some of these tips may not be needed until you implement the full program in the second week of this lab, but are included here to help you with the design.

Random library: shuffle(<list>) and seed(<int>)

The random library includes a shuffle function that, given a list, will put the list in a random order. You can use the shuffle function to shuffle your deck.

While you are testing your program, it is useful to have the deck and rack start off the same way each time. You can force the random library to pick the same random numbers each time by using the seed function. If you call seed(0) at the start of main, your deck will get shuffled the same way each time. If you want to try different configurations, you can changed the value to other integers, e.g. seed(1). When you turn in your final program, be sure to remove the call the seed.

Testing the game

Once you start working on the game implementation, being able to easily test it makes debugging easier and faster. Be sure you test your program after you do the bottom-up implementation of each function!

You can assume the user always enters an integer, but you need to handle the cases where the user types in an invalid integer (e.g. 99 for a slot number).

When you think you have things running, follow each example shown above and be sure that you can get the same behavior from your program. (Obviously there will be differences due to randomness, but the general pattern should be the same for your program and the examples shown.)

Extra Challenges

These will not affect your grade or gain you extra points. They are included just as extra challenges, if you are interested (and have already finished the entire game). If you decide to add extra challenges, copy your code to a new file: cp racko.py racko_extra.py

  • Can you keep a high score saved in a file so that when the player plays again they can try to beat their high score?

  • The game is a bit easy when there is only one player. For example, you can just discard a 1 from your hand and not worry that your opponent will pick it up. Add functionality so that two players can play against each other. With multiple players, don’t shuffle the discard pile in the deck after each turn. Let the discard pile grow until the draw deck is empty and then shuffle that back into the draw back when needed.

  • If you can get two players to play against each other, can you make one of the players be the computer? An obvious and easy strategy for the computer is just to pick randomly and swap randomly…​ That will at least let you test that computer player is working. And if you can get it working, can you come up with a slightly better strategy for the computer than just random?

  • Can you make the game ask you how many players you want to play against? And how many of those players should be computer players?

Answer the Questionnaire

Please edit the Questions-06.txt file in your cs21/labs/06 directory and answer the questions in that file.

Once you’re done with that, run handin21 again.

Turning in your labs…​.

Remember to run handin21 to turn in your lab files! You may run handin21 as many times as you want. Each time it will turn in any new work. We recommend running handin21 after you complete each program or after you complete significant work on any one program.