This assignment is due on Tuesday, March 4, 2008 at 5:00 PM.

Change Log

Introduction

The purpose of this assignment is to give you some initial experience writing Java code using fundamental Object-Oriented programming concepts and the List Abstract Data Type.

Note
You must do this assignment individually.
Note
Assignments are structured with three levels: C, B, and A. The grading for the assignments will be done so that doing everything correctly for a particular level will result in a grade equivalent to that letter grade. The levels are also cumulative — to receive a B, you must do everything in both the C and B levels (usually, the work in each level will depend on the earlier levels).
Warning
When an assignment description tells you to give something a particular name, you must give it exactly that name. Failure to do so may result in a very low or zero score due to inability to properly run your code.

Overview

Your task in this assignment is to write a simple card game program for one player. You will define classes to represent cards and decks of cards, define basic operations on decks, and implement rules to play a simple Solitaire game.

At the C level, your program will do basic operations on a deck of cards such as shuffle, draw, look, add, display and so on.

At the B level, you will implement the rules to play a simple Solitaire game.

Following is a sample of the output at the B level:

Queen of Clubs, 4 of Clubs, Queen of Hearts, Queen of Diamonds, 8 of Diamonds
8 of Diamonds, 4 of Clubs, Queen of Hearts
End of the game, 3 cards left.
You win.

At the A level, you will create a new type of Deck, one that always maintains cards in a sorted order (as specified below). You also will write a JUnit test case.

Getting started

In Eclipse, create a new Java project.

Download the following files, and import them into your project:

C level

To receive a C, you must create a class Card and a class Deck. The Card class has two attributes (suit and rank). The Deck class consists of attributes and operations of a deck of cards.

We provide implementations of Suit and Rank. (Suit.java and Rank.java) using Java's enum construct. You do not need to understand the details of how enums work, but you must use the exact code we provide. Moreover, we encounrage you to look at the Suit and Rank classes before implementing the C level, so that you can see what operations, etc. are available.

You should implement the following in your Card class:

  1. Instance variable : You need variables to store the Suit and Rank of the card. You may name them whatever you wish.

  2. Card(Suit s, Rank r) : Constructor for Card. It creates a new Card with the specified Rank and Suit.

  3. You must implement all the operations specified in Card.html. You must define methods with precisely the names and signatures (number and type of parameters) shown there.

You must implement the following in your Deck class:

  1. Instance variable : A Deck keeps track of the list of Cards in it.

    private ArrayList<Card> deck = new ArrayList<Card>()
    OR
    private LinkedList<Card> deck = new LinkedList<Card>() 

    You may create an object that is either an ArrayList<Card> or LinkedList<Card>.

  2. Deck () : The constructor creates a new Deck object with 52 cards: the Two through Ace of each of the four Suits.

  3. You must implement all the operations specified in Deck.html. You must define methods with precisely the names and signatures (number and type of parameters) shown there.

Note
Use CardTest.java and DeckTest.java to check your classes. We provide 6 tests to help you get started. When we test your submission, we will use other tests to check all the required functionality. We encounrage you to write additional tests yourself to help in your own testing.

B level

Add code to your Level C solution to play a Solitaire game. Create a Solitaire class with a main method. You will also need to implement another method for the Solitaire class, playTurn(Deck d)

In the main method, you will create a Deck object. Shuffle it, then call playTurn until the game is over (See rules below). In other words, the logic is:

Deck deck = new Deck();
deck.shuffle();
while ( game not finished )
	playTurn(deck);
public static void playTurn(Deck deck)

Rules

Here are the rules that describe how to play a turn in the game.

  1. look at the first 4 cards. If all cards are the same suit, remove all.

  2. if all 4 cards are the same rank, remove all.

  3. if 1 & 4 are the same rank, remove 1 and 4 cards. After removing cards, put the ones that you didn't remove back into the back of the deck.

    Example
    Queen of Clubs, 4 of Clubs, Queen of Hearts, Queen of Diamonds, 8 of Diamonds
    8 of Diamonds, 4 of Clubs, Queen of Hearts
    
  4. if 1 & 4 are the same suit, remove 2 and 3 cards. After removing cards, put the ones that you didn't remove back into the back of the deck.

    Example
    4 of Clubs, 8 of Clubs, Queen of Spades, Queen of Clubs, 8 of Diamonds
    8 of Diamonds, 4 of Clubs, Queen of Clubs
    
  5. if 1 & 4 are neither the same rank nor the same suit, if 1 & 4 are from the same color group, (Consider spades and clubs as a black color group and hearts and diamonds as a red color group.) remove 1 card. put the ones that you didn't remove back into the back of the deck.

    Example
    4 of Diamonds, 8 of Clubs, Queen of Spades, Queen of Hearts, 8 of Diamonds
    8 of Diamonds, 8 of Clubs, Queen of Spades, Queen of Hearts
    
  6. if all condition are not satisfied, put all of them into the back of the deck.
    Example
    4 of Spades, 8 of Clubs, Queen of Spades, Queen of Hearts, 8 of Diamonds
    8 of Diamonds, 4 of Spades, 8 of Clubs, Queen of Spades, Queen of Hearts
    

Here are the rules that define the stopping condition for the game.

  1. if the number of total left cards is less than 5. In this case, you win the game.

  2. if you play the game (run the playTurn) more than 1000 times. In this case, you lose the game.

Print the list of cards at every step. Finally indicate "You win" or "You lose". If you drop all cards or the number of total left card is less than 5, "You win". Otherwise, "You lose".

Note
Use the given SolitaireTest.java to check your classes. We provide a test. It covers only from rule 1 to rule 4. You have to test other rules by yourself. Feel free to change SolitaireTest.java for other rules.

A level

For this level, you need to add the following: First, implement your JUnit test code for OVERRIDING add function (add(Card c)). Second, create a new type of Deck that maintains its cards in a sorted order. To do this, you will have to change the Card class too.

  1. Change your Card class so that it implements Comparable. The compareTo() method in Card class returns an ordering by suits: spades > hearts > diamonds > clubs and then by rank A > K > ... > 2.
  2. Create a class called SortedCardDeck. SortedCardDeck class is a subclass of Deck class. For the A level, you should change the access modifier for the instance variable deck from private to protected. A SortedCardDeck object must guarantee that the cards in the deck are sorted when it is created. Your constructor must make sure this is the case. Moreover, you must override the two add operations (inherited from the Deck class) so that any time a Card is added to the Deck, it will be added in sorted order.
  3. Implement a JUnit test case to test the overridden add method (add(Card c)). The name of your JUnit test should be SortedCardDeckTest.java.
  4. Two methods inherited from Deck do not make sense for SortedCardDeck, shuffle() and add(int n, Card c). You should override these methods with 'null implementations' here. That is, the body of the method either should be empty or else should contain just a statement that prints a message saying this method is not implemented for a SortedCardDeck.
  5. Open the Solitaire.java. Create one sorted order deck in the main method. (So, you have two decks. One is original deck and the other is sorted order deck.) Play two decks and show two results. (This shouldn't mess up the original Deck.)
  6. Finally, you may find it useful (but it is not required) to define another constructor for SortedCardDeck that initializes the deck variable to contain an empty list of Card. You can then invoke the add method a number of times with different Card objects to verify that they are added in the proper order.
Note
At least 24 hours prior to the due date of this assignment, we will publish additional unit tests for you to use in testing the B- and A-level code. The purpose of this is to enable you to perform final debugging before submitting the assignment.

Submitting your assignment

Before you submit your assignment, you must create a text file called readme.txt in your project directory. In this file, put your name and x.500 ID.

Copy all your own code and other files (include all given java files such as CardTest.java, DeckTest.java, SolitaireTest.java and so on) to an ITLabs computer for final testing. On the ITLabs computer, run ant run in your code's directory and make sure the program works. Then run ant package to create the HW package, and submit the resulting hw2.tgz file via Submit.