CSE 413 Au12 Assignment 6 - Go Fish!

Due: Online via the Catalyst Dropbox by 11 pm, Tuesday, Nov. 20, 2012.

Goals

For this project you will implement a computerized version of the card game Go Fish! The rules of the game are summarized below. The goals of this assignment are to gain experience with Ruby programming and with designing object-oriented programs. This writeup describes the basic constraints for the program you should produce, but many of the details are up to you. In particular, the game rules may or may not correspond exactly to other versions of Go Fish you know, but that shouldn't pose a problem. The goal is to gain experience with Ruby and object-oriented program design, not to become an expert at a particular card game.

The Game

Go Fish is played with a regular deck of 52 playing cards. Cards in a deck have one of four possible suits (Hearts, Diamonds, Spades, and Clubs), and face values of 2-10, Jack, Queen, King, and Ace. A game is played as follows.

  • The deck of cards is shuffled into some random order, and each player gets 7 cards as their starting hand. The remaining cards are left in the deck.
  • The players take turns. At each turn, one player asks the other for cards with a particular rank (2-10, Jack, Queen, King, Ace).
    • If the other player has one or more cards with that rank, they are given to the player who asked for them.
    • If the other player has no cards with that rank, then the player doing the asking draws the next card from the deck of remaining cards. The other player may optionally say (or shout) "Go Fish!" to tell the player to draw from the deck.
    Once a player either receives cards from the other player or draws one from the deck, if that player has any pairs of cards with the same rank, the player discards those pairs.
  • The players continue alternating turns until one player runs out of cards.

(There are variations on these rules in the real card game. For instance, in most versions, a player may only ask for cards that match the rank of one or more cards that they already hold. Also, in the real game, a player has a choice of whether to discard pairs or not. You can add these rules as extensions to your game, but they are not required.)

The Program

You should write a Ruby program that allows the user to play Go Fish with the computer. When the user runs the program, it should behave as follows:

  • The computer should shuffle the 52 cards randomly, then deal 7 of them into two separate hands for the user and the computer.
  • Repeat the following steps until the game is over:
    • Display the contents of the user's hand and report the number of cards in the computer's hand (but not display them).
    • Ask the user for a move. The user can enter any of the following commands:
      • Request a card from the computer by entering a rank 2-10, j, q, k, or a. You can optionally allow J, Q, K, and A to be used.
      • Quit the game by entering x.
      • Start a new game by entering n.
    • When the user requests a card, the computer should do the following:
      • If the computer is holding one or more cards with that rank in its hand, transfer those cards from the computer's hand to the user's hand.
      • If the computer does not hold any cards with that rank, draw one card from the deck and add it to the user's hand.
    • After transferring or drawing cards, any pairs of cards with the same rank in the user's hand should be discarded.
    • The computer should then play a turn by picking a rank to request from the user's hand and either transfer or draw cards, depending on what is in the user's hand, and discard pairs if the computer holds any. The computer should pick a rank to ask for either randomly (easiest) or by asking for a rank that matches one in the computer's hand (a little harder).
    • When either the user's or computer's hand is empty, the computer should announce the winner and ask the user whether to play again.

The program should print additional messages to describe the progress of the game as needed.

Implementation

One of your jobs in this assignment is to decide what classes and objects you need, what messages those objects should respond to, and how the parts of your program should fit together. There are a few constraints that you must follow, given here. Beyond these specific requirements, your classes and objects should describe well thought-out individual concepts, and the parts of the program should interact with each other through small, simple interfaces.

Your implementation must include at least the following classes:

  • Card: a single playing card. A card has a suit and a rank. This class should be very simple, with an initialize method to construct a new Card given a suit and a rank, a to_s method to return a string representation of the card, and any accessor methods needed to access the suit and rank of the card.
  • Hand: one player's Cards. This is a collection of Card objects representing the cards held by a single player. It is not necessarily ordered. It should include appropriate methods to add and remove cards, produce a string representation of a hand, search for Cards in the hand, etc.
  • Deck: the Cards remaining in the original deck. This is an ordered list of Card objects with methods to deal a Card object from the Deck and so forth.

Beyond these bare specifications, you will need logic to do things like create a randomly shuffled deck of 52 cards to start a game, interact with the user, play the game on behalf of the computer, and so forth.

You should be prepared to let your design evolve as you work on the program. It is normal in designing object-oriented (or other) code to discover that decisions you made early in the process ought to be changed to make things simpler and cleaner. Don't be afraid to change things as you go - don't get over-committed to your early decisions, and don't continue to hack at a design to get it to "work" when it would be better to do something different now that you have a better understanding of the problem.

Your code should use Ruby collections, iterators, and blocks where this makes sense. For example, use the each method instead of writing something like a Java for-loop to iterate through the elements in a collection, etc.

Your Ruby code can, if you wish, be stored in a single file, or you can split it up into separate files for individual classes or related classes. For this project, do whichever is simplest for you.

However, you should have at least one source file named fish.rb, and it should be possible to run your game with the command ruby fish.rb (or its equivalent on your system)

Extra Credit

A small amount of extra credit will be awarded for programs that include interesting extensions. A simple extension would enforce the restriction that players can only ask for cards that have the same rank as one they already hold in their hand. A more complex extension would be to make the computer smarter in its game play, for instance, instead of randomly asking for a particular card rank, keep track of the previous moves in the game and make smarter choices. A devious extension would be to add various "cheating" modes, where either the computer or the human user could peek at the other player's hand or do other evil things.

If you implement any extensions, include a file readme.txt with your submission that gives a brief explanation of your extensions. If you add any commands or options to the game, include instructions on how to use them.

What to Hand In

Turn in a copy of your Ruby source files and, if you have one, the readme.txt file using the regular online collection dropbox. Be sure that your name is included at the beginning of each of your files in a comment.