Due: Monday, October 8, 2007 28, 11:59:59:999 p.m. EST
In this project you will implement the PlayingCard class we have used in
class for a number of examples.
You will also implement a BlackJackHand class to model a hand in the
popular card game of Black Jack.
We will not concern ourselves with how to store the cards in a hand to
simplify matters. Later on if we
actually implement the entire game we can deal with that detail. Implementing these classes will give
you more practice in class structure, implementation, and the conditional if
statement we have started to discuss in class. The project is based on Exercise P5.2 on p. 197 from your
textbook (you can find a nice table of the card codes there).
To assist you in your task I will provide you with skeletons of both
classes. Additionally, I will give
you tester classes that I found to be useful in my implementation. Use them, modify them, or ignore them
as you wish. You can download the
compressed file containing the project with these classes here.
NOTE: To see the entire output of the PlayingCardTester class' main method you
may need to select "Unlimited buffering" from the Options menu when
the Terminal window is active (love those context sensitive menus!).
Please do not change the names of any public methods
or instance variables (constants), or the order or type of any method
parameters. Doing so makes more
work for the graders: bad for you and me.
You may change the name or type, or omit any private methods or instance
variables. You may also change the
parameter names for any method to names
more meaningful to you. Add any
additional private or public instance variables or methods you need to
implement the methods specified in the skeleton. Also add comments and @param and @return tags to support
generation of web documentation for the methods and any public constants.
Additional Details:
1.
Both constructors should explicitly initialize all instance
variables to an appropriate default value (you may wish to make these defaults
class constants). Note that the
value of the cards is determined by the game played with them. Consequently, the game itself will
determine (assign them) their values, but you should initialize them to some
default value. Do not leave instance
variables with null values, especially if you add additional instance
variables.
a)
One constructor takes a single String parameter that denote a
code for a card, e.g. the string "AH" should produce an Ace of Hearts
card. Note that "Ah",
"ah", and "aH" should all create the same card, i.e. the
codes need not be given in uppercase, but I recommend storing them as upper
case.
b)
The other constructor takes two String parameters: the first
is a code for the rank and the second is a code for the suit, e.g.
PlayingCard("AH") and PlayingCard("A","H") both
should produce an Ace of Hearts.
2.
The following get methods and set method should be self
explanatory
a) getRank(): return the rank code as an
upper case String
b) getSuit(): return the suit code as an
upper case String
c)
getValue()
d)
setValue()
3.
Implement the following three methods by adding a (boolean)
instance variable to your class and using it in them (don't forget to
initialize it in your constructors).
a) isFaceUp()
b) isFaceDown()
c)
flipOver()
4.
The getDescription()
method should return a nicely formatted string of the form "Ace of
Clubs" if the card is created using the code "AC". I have supplied class constants for
each rank and suit code as well at their labels. Please use these and don't change them or the syntax of the
output of this method. Again, if
everyone's method outputs the same phrase, testing and grading is greatly
simplified. You may use the
following two private methods if you wish to help implement your getDescription() method, but they
aren't required. The method should return the contents of the constant
UNKNOWN_CARD_PHRASE and nothing more if either the suit or rank code is
invalid.
a)
getRankDescription()
b) getSuitDescription()
5.
[Optional/extra credit choices]
a) Expand/extend
the suit and rank notation to allow for two Joker cards. The two jokers should be
distinguishable from one another by their description. Add and document PlayingCard class
constants for the Joker ranks and suit and descriptive labels for them. Modify your getDescription() method to print out
a nicely formatted string of the form "Red Joker"/"Black
Joker" or "Big Joker"/"Little Joker" for example. Also add a method called isJoker() that returns a boolean. It should return true if the card is one of the two
Jokers and false
otherwise. See http://www.usplayingcard.com/gamerules/glossary-index.html
for a Joker terminology
b)
Create a drawing for your cards and add a display() method that shows the card
in a graphical window.
c)
Your ideas.
Please do not change the names of any public methods
or instance variables (constants), or the order or type of any method parameters
for the reasons previously stated.
Again, you may change the name or type, or omit any private methods or
instance variables. You may also
change the parameter names for any
method to names more meaningful to you.
Add any additional private or public instance variables or methods you
need to implement the methods specified in the skeleton. Also add comments and @param and
@return tags to support generation of web documentation for the methods and any
public constants.
Additional Details:
1.
Both constructors should explicitly initialize all instance
variables to an appropriate default value (you may wish to make these defaults
class constants). Do not leave
instance variables with null values, especially if you add additional instance
variables.
a.
One constructor takes no parameters and sets the instance
variables (numberOfCards and value and whatever others you add) to some default
values.
b.
The other constructor takes two int parameters: this first is
the number of cards in the hand, and the second the total value of the hand.
2.
The following get methods should be self-explanatory and
depend on the number and type of cards that have been added to the hand.
a. getNumberOfCards()
b.
getValue()
(note this is different from the method of the same name in the PlayingCard
class)
3.
The addCard()
takes a single parameter, a PlayingCard and adjusts the value and number of
cards in the hand accordingly.
More precisely, the number of cards should increase by one for every
card added and the value of the hand should increase by the value of the card
being added where the card values are class constants in the BlackJackHand
class. So for example if a card
has two cards in it and a value of 7, then after adding the Ten of Diamonds to
the hand using hand.addCard(),getNumberOfCards() and getValue() when called on that hand
should return 3 and 17, respectively (see the BlackJackHandTester class for
more details).
NOTE: You should not worry about hanging onto or managing the cards that have
been added to the hand. You only
need to keep the number of cards and value of the hand.
NOTE: For simplicity treat all Ace cards as having a value of 11. See the extra credit list below for
treatment of Ace as 11 or 1.
4.
[Optional/extra credit choices]
a)
Add a method called isBust()
that returns a boolean. It should
return true if the value
of the hand exceeds the maximum allowable hand value of 21 (as public class
constant?) and false
otherwise.
b)
Add a method called isFiveCardCharlie()
that returns a boolean. It should
return true if the number
of the cards in the hand is 5 and the value of the hand is less than or equal
to 21 (the maximum allowable hand), and false
otherwise.
c)
Modify the class to value an Ace card as 11 unless this would
cause the value of the hand to exceed the maximum allowable value, i.e. to
cause the hand to be a bust. In
that case value the Ace as 1 (even if this still causes the hand to bust). Again you should not keep in any way
the cards that have been added, but you may keep additional information about
the hand as a whole.
HINT: Track the value of the hand and number of cards excluding Aces.
d)
Create a method called split()
that works only if the hand has two cards of the same rank. The method should return a
BlackJackHand with one card and half the value of the hand you are
splitting. It should also change
the hand from which it is called in the same way. You may also want to create a boolean method isSplitable() to decide if a hand can
be split or not.
First implement the get and set methods and constructors and make sure they
work before moving on to the more challenging methods. No additional class methods other than
the String class methods are needed.
You may use a series of nested if else if ... statement or the switch
statement (see the tester classes and Advanced
Topic 5.2 Internet content for your book). Before trying to write the code for any method, try to work
out what it is supposed to do on paper with some simple examples.
Start early and try to make a little progress each day. Test early and often. Sections 2.8, 3.6, and 5.5 of your book
discuss different aspects of testing.
You can use BlueJ to test constructors and simple methods
interactively. The tester classes
I provide should also help you find problems. Make use of the online documentation, the lab TAs, your
fellow classmates (to the extent allowed by the Collaboration Policy) and me
early and often. Don't put it off
until the last minute.
All constructors, methods, and public instance variables should be commented
using @param and @return tags to facilitate the generation of .html
documentation similar to the Java Class Libraries on the Web via the Javadoc
utility. BlueJ automatically
generates this documentation for your class when you switch from
"Implementation" to "Interface" in the class editor
window. We've discussed the use of
these tags in class and additional information is in section 3.3 of your
textbook.
Your code should adhere to the stylistic guidelines we have been discussing
and which are in Appendix A of your textbook as much as possible. In particular group different constructors,
instance variables, and similar methods together. Use meaningful variable names and internally comment your
code liberally (with // or /*
*/ pairs).
The graders will be instructed to determine approximately 10-15% of your
project grade based on style, readability, and documentation. Please use indentation, white space,
and other stylistic techniques to make your code easier to read (and grade).
You will again submit your projects electronically. To do so
1.
Connect to the Academics volume of the server called
fileserver1. From a Mac choose
"Connect to Server ..." from the "Go" menu in the Finder,
type afp://fileserver1 in the dialog box, and select Academics from the volume
list. From Windows machine open
Windows Explorer, select "Map Network Drive" from the tools menu,
pick a free drive letter and type \\fileserver1\Academics
or just type it directly into the address filed. When prompted for your user name and password, type COLBY\username, where username is your Colby username and enter your password. These instructions are adapted from http://www.colby.edu/administration_cs/its/support/fileserver1.cfm.
2.
On the Academics volume inside of the COMP/CS151
folder/directory you will see a folder with your Colby e-mail/login name and
within that a private folder. Copy
your PlayingCard.java and BlackJackHand.java files from your project directory
to your private folder. DO NOT
submit a .zip file, a project directory or any other files. If you attempted
some part of the extra credit please also include a brief readme.txt file
explaining what additional functionality you have added and would like the
graders to evaluate. Just copy
these files to the private directory right from your project directory.
As indicated in the preface, the card coding scheme is from Exercise P5.2 on
p. 197 of Java Concepts for
Java 5 and 6, 5th Edition by Cay S. Horstmann.