Programming Assignment
Due:
Please make sure you adhere to the policies on
academic honesty.
Please see the general programming webpage for details about
the programming environment for this course, and specifically for
directions in how to submit your programming assignment electronically.
The files you need for this assignment can be
downloaded here.
Contents:
Your goal for this program will be to design a class Hand
which will be used to simulate playing a game of cards. Every card
will have a "suit" and a "value" specified. Your task is to implement
the following two routines:
- void Hand.insertCard(Card c)
Add a given card into the hand.
- Card Hand.playDown(int suit) throws
EmptyHandException
This routine removes a card from the hand and returns it.
More specifically, if the hand contains any cards of the desired suit,
one of those cards must be played (the choice of which can be
arbitrary). If the hand does not contain any cards of the desired
suit, a card of some other suit should be played. If the hand is
empty, this routine should throw an EmptyHandException.
For the routine insertCard(c), you may assume that the card is
given with a valid suit and value. Furthermore, you do not need to
worry about whether a new card is identical to an existing card. Just
keep them both, as if they are two different cards. (In fact, those
who have played Pinochle know that your hand may indeed have two cards
with identical value and suit).
The semantics of the playDown(suit) routine is meant to model
the rules of many common games (e.g., Hearts, Bridge, Pinochle) which
require a player to "follow suit" when possible. Because of this
requirement, players often find it convenient to organize their hand
so that all cards of the same suit are consecutive in the hand (though
the order of the suits, and the order of the cards within a particular
suit may remain arbitrary).
A naive implementation for maintaining cards of the same suit grouped
might still require a linear walk through the entire hand. When
inserting a new card, one might have to walk from one end of the list
until finding other cards of the same suit (or realizing that there
are none). Similarly, when trying to play a card of a particular
suit, one might have to scan the entire hand.
A better approach is to maintain four "fingers" into the hand, one
for each suit, allowing insertions and deletions to be implemented in
constant time (no matter how large the size of the hand becomes).
You are required to implement this constant time approach based
on the use of underyling List and Position ADTs. A
single List will be used to store all cards, and each
"finger" will be represented by a Position in that List.
The files you need for this assignment can be
downloaded here.
For this assignment, we will be providing you with what might seem
like an enormous number of different files which you will need in your
project. We will briefly discuss the purpose of each file:
- Hand.java
this is the only file you should modify. The
provided file is a template which provides you with the blueprint for
the methods. (you must fill in the details)
- CardsDriver.java
this driver will allow you to test your
code. As was the case with previous drivers, it takes input from the
keyboard by default, but it can read lines from a file instead if you
provide the filename as a runtime argument.
- Card.java
This defines a simple class for representing
one card. An object, c, of class Card has two public
variables c.suit and c.value. Both of these variables are
represented using the int primitive data type. The convention
for suit is that it will be an integer between 0 and 3,
denoting the four suits, clubs (), diamonds
(), hearts () and spades ()
respectively. The value will be between 1 and 13, though the driver
maps the values 1, 10, 11, 12, and 13 to the standard cards Ace, Ten,
Jack, Queen and King respectively.
- List.java and Position.java
These define the
official List and Position interfaces, as given in
Chapter 5.2 of the text. Please note, since a Position is
defined as an interface, it is acceptable to define a reference
variable such as
Position finger = null;
however it is not acceptable to try to create a new position such as
Position finger = new Position();
The only way to get a valid, non-null position is by saving a position
reference as returned by one of the List methods.
- ListImplemenation.java
This file implements the
List and Position interface. (It happens to use a
doubly-linked list, of course you really do not need to know this!)
- BoundaryViolationException.java, EmptyContainerException.java,
EmptyHandException.java and InvalidPositionException.java
Our interfaces rely on a variety of exceptions. Each one must unfortunately
be defined with a separate file.
- ObjectIterator.java
This defines the interface
discussed in Chapter 5.5 of the text. This is only relevant to
students attempting the extra credit challenge, however the file must
techincally exist for all students in order to compile our driver.
In the end, meeting the requirements for this assignment can be easy.
A perfect solution can be written using less than 40 lines of
additional code in Hand.java (not counting the extra credit).
At the same time, past students have submitted solutions in excess of
300 additional lines of code yet flawed.
Our real goal of this programming assignment is to give you
familiarity with the List and Position ADTs from the
text. In a sense, you will be stepping to the other side of the wall
we often discuss when defining interfaces in this class. That is, you
will not be required to implement the List data structure;
the book as already done this and we will provide you with the
implementation. All you need to know is the high-level List
ADT, and how to use the methods it provides to accomlish the task at
hand. Although the program does not necessarily involve a great deal
of work, you should expect to use a good deal of time in learning the
proper syntax and semantics of the List interface.
Our strict requirement for this assignment is that you must store all of
the cards in a single instantiation of the List ADT (that is,
you cannot create four separate lists for the four suits).
Within that list, you should use the Position abstracton to
somehow represent where, in the large list, cards of a given suit
might be found. This will allow you to insert or remove desired cards
without having to traverse the entire list.
The rest of the design details are left to your choice. We will add a
few words of advice though.
We will again ask each student to submit a file "inputfile" which we
will use in a round-robin competition. The assignment is worth 10
points. Eight points will be awarded based on our own evaluation of
your assignment. One additional point will be awarded fractionally
based on how well your program performs on other students' inputs.
The final point will be awarded fractionally based on how well your
input fools other students' programs.
You will find in developing your program that many different special
case exists for this assignment. These range from how to represent a
"finger" when a hand contains zero cards of a particular suit, as
well as simply being careful in dealing with the List interface
in a way so that you do not end up with any unwanted exceptions.
Your file should be formatted perfectly to work as input to
CardsDriver. You may use at most 100 commands, and you are not
allowed to call the extra credit methods (as students are not required
to implement these).
You should submit at least three files:
- Hand.java - which contains your implementation.
Please note that if you decide to define any additional classes in completing
this assignment, you must provide us with those ".java" files.
- readme - a brief summary of your program, and
any further comments you wish to make to the grader. If you do the
extra credit, please make this clear.
- inputfile - discussed earlier.
If you are not familiar with cards or card games, do not worry. All
that really matters for this assignment is that a card is defined as a
member of the cross-product . Feel
free to ask if you have additional questions.
You may receive 1 additional point if you implement the following
two routines in Hand.java:
- ObjectIterator allCards()
This routine should create an ObjectIterator, where the iteration
allows one to iterate through all of the Card's in the hand.
- ObjectIterator allOfSuit(int suit)
This routine should create an ObjectIterator, where the iteration
allows one to iterate through all of the Card's in the given
suit.
Iterators (and the ObjectIterator ADT) are discussed in
Chapter 5.5 of the text. From your point of view, it might seem easy
to imagine code which walks through the List your maintain (or a
subset of that list). The purpose of an iterator is to give the user
sequential access to a particular group of objects, while still
managing to avoid giving away information about the details of
your implementation (such as the fact that you decided to use a
List).
There is not necessarily a great deal of code required to implement
these methods, however it will require a very clear understanding of
the abstractions involved. In particular, ObjectIterator is
simply an interface, and you will have to create a new class which
will implement this interface. Of course, designing such a class
requires very close interaction with the Hand class which you
will have already defined.
Last modified: 6 September 2002