part I due by 10 p.m. on Wednesday, July 15, 2026
part II due by 10 p.m. on Friday, July 17, 2026
In your work on this assignment, make sure to abide by the policies on academic conduct for this course.
If you have questions while working on this assignment, please come to office hours, post them on Ed Discussion, or email
cscis111-staff@lists.fas.harvard.edu
50 points total
Create a subfolder called ps5 within
your s111 folder, and put all of the files for this assignment
in that folder.
The problems from Part I will all be completed in a single PDF file. To create it, you should do the following:
Access the template that we have created by clicking on this link and signing into your Google account as needed.
When asked, click on the Make a copy button, which will save a copy of the template file to your Google Drive.
Select File->Rename, and change the name of the file to
ps5_partI.
Add your work for the problems from Part I to this file.
Once you have completed all of these problems, choose
File->Download->PDF document, and save the PDF file on your
machine. The resulting PDF file (ps5_partI.pdf) is the one
that you will submit. See the submission guidelines at the end
of Part I.
Rectangle class revisited11 points total; individual-only
Recall the Rectangle class that we defined in lecture. (The final
version of this class is available
here.)
Consider a potential instance method named shrink that would
take an integer value as a parameter and reduce both of the
dimensions of a Rectangle by that value. For example, if a
Rectangle‘s dimensions are 80 x 40, then calling the shrink
method with a parameter of 10 would give the Rectangle
dimensions of 70 x 30.
shrink be, an
accessor or mutator?Now consider a potential instance method named diagonal that
would return the length of the rectangle’s diagonal as a real
number. For example, if a Rectangle‘s dimensions are 30 x 40,
then the diagonal method would return 50.0.
diagonal be,
an accessor or mutator?Consider the following client code — i.e., code from another
class that uses a Rectangle object:
Rectangle rect = new Rectangle(10, 20, 30, 40); System.out.println("width = " + rect.width); rect.x = rect.x + rect.y; System.out.println(rect);
Because our Rectangle class employs appropriate encapsulation,
this code fragment will not compile.
9 points total; individual-only
Recall the RectangleClient class that we defined in lecture. (The
final version of this class is available here.)
(5 points) In the provided RectangleClient, all of the client
code is inside of the main method. However, client code
can also include static methods that take one or more
objects of the relevant class as a parameter.
Write a static method called largerThan that takes two
Rectangle objects r1 and r2 as parameters. The method should
return true if r1 has a larger area than r2, and false
otherwise.
For example, given the following two Rectangle objects:
Rectangle r1 = new Rectangle(20, 6); Rectangle r2 = new Rectangle(25, 4);
the call largerThan(r1, r2) should return true, but the call
largerThan(r2, r1) should return false.
Notes:
The method must be written as client code – i.e., it should
work correctly if it is added to a class other than the
Rectangle class itself.
For full credit, your method should take advantage of the
non-static methods that are inside every Rectangle object
so that the method doesn’t need to do too much work on its
own.
To test your method, you could either download our
RectangleClient class (see above) or create a new client
class of your own. Add your method to the class, and then
add some test code for it to a main method.
Once you are satisfied that your method works correctly,
add it to your ps5_partI file.
(4 points) In ps5_partI, write client code for the Rectangle
class that does the following:
Creates a Rectangle object with a position of (0, 0),
a width of 40, and a height of 50, and assigns it to a
variable r. (Note: Since the position is (0, 0), you
should take advantage of the constructor that assumes
that both the x and y values are 0.)
Prints the dimensions of r – taking advantage of the
way that the provided toString() method works.
Uses the grow method to increase the width of r by 5 and
the height of r by 12.
Prints the new dimensions of r – taking advantage of the
way that the provided toString() method works.
If your client code works correctly, its output should be:
40 x 50 45 x 62
6 points total; 3 points each part; individual-only
When designing a blueprint class, we can include both non-static and static methods. A non-static method is required if the method must have access to the fields of a particular called object. However, if a method does not need a called object – i.e., if all of the information that it needs is supplied by its parameters – then we typically make it static. Non-static methods must be called on an object of the class. Static methods may be called on an object of the class, but it is better style to call them using the name of the class instead.
Recall our Grade class from lecture, which is a blueprint class
for objects that encapsulate both a raw score and a late penalty.
Assume that you are considering adding two methods to this class.
The first method is called addExtraCredit. It takes a
parameter of type double called amount and increases the raw
score of a Grade object by the specified amount.
addExtraCredit be — static or
non-static? Explain briefly.Grade class. If you need a Grade object to
call the method, assume that the variable g represents
that object, and that the object has already been created.The second method is called computePercent. It takes two
parameters of type double – one called pointsEarned and
another called possiblePoints – and it returns pointsEarned
as a percentage of possiblePoints. For example, if
pointsEarned is 30.0 and possiblePoints is 50.0, the method
should return 60.0, because 30 is 60 percent of 50.
computePercent be — static or
non-static? Explain briefly.Grade class. If you need a Grade object to
call the method, assume that the variable g represents
that object.8 points total; individual-only
Recall the set of vehicle classes that we defined in lecture. Although we
discussed the possibility of a MovingVan class (and included it in
some of the inheritance-hierarchy diagrams in the lecture notes) we
never actually defined this class. In this problem, you will write a
definition for this class that takes full advantage of inheritance.
A MovingVan object should have all of the same state and behavior
as a Truck object. In addition, it should maintain additional
state that keeps track of:
When a MovingVan object is printed, we want to see its
capacity, its distance to the cargo area, and whether it has a ramp.
For example:
capacity = 10000, distance to cargo = 5, has a ramp
In your ps5_partI file, add a definition of this class that includes
the following:
MovingVan object. Make sure
that you take inheritance into account when deciding which
fields to include.6 points total; 2 points each part; individual-only
Consider again our set of vehicle classes. Which of the following assignments are valid, and which are not? Explain each answer briefly.
Limousine l = new Automobile("Cadillac", "El Dorado", 2024);Limousine class,
but we did include it in the inheritance hierarchy for the
vehicle classes that is found in the lecture notes.)Object o = new Motorcycle("Harley", "1200 Custom", 2020);Vehicle v = new Truck("Ford", "F-150", 2023, 4);10 points total; 2 points each part; individual-only
Consider the following four classes:
public class Gee { public String first() { return "fee"; } public String second() { return "fi"; } } public class Tee extends Yee { public String first() { return "fo"; } public String second() { return "fum" + this.first(); } } public class Zee extends Gee { public String first() { return "fah" + this.second(); } public String third() { return "few" + this.first(); } } public class Yee extends Gee { public String third() { return "from" + this.second(); } }
Assume that you have the following variable declarations, all of which are valid:
Gee g = new Yee(); Yee y1 = new Yee(); Yee y2 = new Tee(); Tee t = new Tee(); Zee z = new Zee();
Consider the following statements. If a given statement would compile, state the output that it would produce when it is executed. If a given statement would not compile, explain why.
System.out.println(g.first() + " " + g.second() + " " + g.third());System.out.println(y1.first() + " " + y1.second() + " " + y1.third());System.out.println(y2.first() + " " + y2.second() + " " + y2.third());System.out.println(t.first() + " " + t.second() + " " + t.third());System.out.println(z.first() + " " + z.second() + " " + z.third());Submit your ps5_partI.pdf file by taking the following steps:
If you still need to create a PDF file, open your file on Google Drive, choose File->Download->PDF document, and save the PDF file on your machine.
Click on the name of the assignment in the list of assignments on Gradescope. You should see a pop-up window labeled Submit Assignment. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)
Choose the Submit PDF option, and then click the Select PDF button and find the PDF file that you created. Then click the Upload PDF button.
You should see a question outline along with thumbnails of the pages from your uploaded PDF. For each question in the outline:
As you do so, click on the magnifying glass icon for each page and doublecheck that the pages that you see contain the work that you want us to grade.
Once you have assigned pages to all of the problems in the question outline, click the Submit button in the lower-right corner of the window. You should see a box saying that your submission was successful.
Important
It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.
If you are unable to access Gradescope and there is enough
time to do so, wait an hour or two and then try again. If you
are unable to submit and it is close to the deadline, email
your homework before the deadline to
cscis111-staff@lists.fas.harvard.edu
50 points total
There are no grad-credit problems for this assignment.
In this part of the assignment, you will create blueprint classes for the card game of Blackjack.
Card objects20 points; pair-optional
Important
On this and all of the remaining Part IIs, make sure to employ
good programming style. Use appropriate indentation, select
descriptive variable names, insert blank lines between logical
parts of your program, and use comments at the top of each file
and before each method other than main(). See the coding
conventions for more detail.
In addition, the classes that you implement should not have any additional public methods besides the ones that are outlined in the problem set. If you choose to add a helper method, please make sure that it is private, not public.
(0 points) Download Card.java into your ps5 folder
and open it in VSCodium.
This file includes some starter code for the class you will write, and you should review it before continuing — including all of the comments that we have provided. In particular, make sure that you understand the following class constants:
integer constants for the ranks of non-numeric cards (ACE, JACK, QUEEN, and KING)
arrays of strings representing the names and abbreviations of
the ranks. These arrays are defined so that the rank number can
be used as the index into the array: the numeric rank r has
the name RANK_NAMES[r] and the abbreviation RANK_ABBREVS[r].
For example, an Ace has a rank of 1, and thus RANK_NAMES[1] is
the string “Ace” and RANK_ABBREVS[1] is the string “A”.
integer constants for the four suits (DIAMONDS, HEARTS, CLUBS, and SPADES)
arrays of strings representing the names and abbreviations of
the suits. These arrays are defined so that the suit number can
be used as the index into the array: the numeric suit s has
the name SUIT_NAMES[s] and the abbreviation SUIT_ABBREVS[s].
For example, the suit number for DIAMONDS is 1, and thus
SUIT_NAMES[1] is the string “Diamonds” and SUIT_ABBREVS[1]
is the string “D”.
Implement the getSuitNum method (2 points)
Complete the getSuitNum method provided in Card.java. This
method takes the name of a suit as a parameter, and it should return
the index of the specified suit in the SUIT_NAMES array, or -1 if
the string passed as a parameter does not appear in that array. For
example:
getSuitNum("Hearts") should return 2, because “Hearts” has an
index of 2 in the SUIT_NAMES array, and
getSuitNum("Spades") should return 3, because “Spades” has an
index of 3 in the SUIT_NAMES array.
getSuitNum("foo") should return -1, because “foo” does not
appear in the SUIT_NAMES array.
Notes:
Use the equalsIgnoreCase method when testing to see if the
parameter matches a given element of the SUIT_NAMES array, so
that the method will work for variants of the suit names in
which the cases of the letters are different than the cases of
the names in the array. For example, getSuitNum("spades") and
getSuitNum("SPADES") should also return 3.
Use a for loop to process the elements of the SUIT_NAMES
array, looking for a match. If you can’t figure out how to use
a loop, it’s worth noting that the approach you will need to
take is similar to the approach taken by the schoolNumber
method from problem 2 in Problem Set 4.
This method is a private helper method, and it will be used by one or more of the other methods that you write.
This method (unlike the others you will write) is static, because it does not need to access the fields in the object. Rather, we pass it all of the information that it needs as a parameter.
Define the fields (2 points)
Each Card object should encapsulate two pieces of state:
the card’s rank (an integer). For numeric cards, the rank is simply the number itself (e.g., 5 cards have a rank of 5). Aces have a rank of 1, Jacks a rank of 11, Queens a rank of 12, and Kings a rank of 13. Ranks less than 1 or greater than 13 will not be allowed.
the card’s suit number (an integer). This is the value that
would be returned by the getSuitNum method for the card’s
suit. The only allowable suit numbers are 0, 1, 2, and 3.
For example, here is what a Card object representing an Ace of
Hearts would look like in memory:
+----------------+ | +-----+ | | rank | 1 | | | +-----+ | | +-----+ | |suitNum | 2 | | | +-----+ | +----------------+
Note that it has two fields, both of which are integers.
For now, you only need to define the fields. Make sure to:
use the field names shown above
protect them from direct access by client code.
In subsequent sections, you will write constructors that assign values to the fields, and that ensure that only valid values are allowed.
Implement the constructors (3 points)
Next, add two constructors:
a constructor that takes two integer parameters specifying the card’s rank and suit number (in that order). It should ensure that only valid values are assigned to the object’s fields, as specified in part 3.
a constructor that takes an integer parameter specifying the
card’s rank and a String parameter specifying the card’s suit
(in that order). Note that this constructor will need to
determine the suit number for the specified suit string, and it
should use another method that you have already written for this
purpose.
In theory, you could have this constructor invoke the other
constructor using the keyword this. However, it can be tricky
to do that in this case, because the call to the other
constructor must be the first line of code in the new
constructor. If you can’t figure out how to make this work, then
you should just have this constructor do everything itself –
including the necessary error-checking.
For example, here is some code that uses the constructors:
Card c1 = new Card(1, 2); // Ace of Hearts Card c2 = new Card(5, 1); // 5 of Diamonds Card c3 = new Card(12, "hearts"); // Queen of Hearts
Implement the basic accessor methods (7 points)
Next, define the following initial set of instance methods. (Note
that all of these methods are accessor methods. We will not
implement any mutator methods, because we assume that a given Card
object’s rank and suit number remain fixed once the object is
created. The constructor will take care of assigning the initial
values of those fields, and those values will not change.)
getRank, which returns the integer representing the Card
object’s rank. For example, if c1 is the card shown in the
diagram above, c1.getRank() should return 1.
getRankName, which returns a String representation of the
Card object’s rank. For example, if c1 is the card shown in
the diagram above, c1.getRankName() should return the string
"Ace". This method should make use of the array of rank names
that we have given you.
getSuitNum, which returns the Card object’s suit number. For
example, if c1 is the card shown in the diagram above,
c1.getSuitNum() should return 2. (Note that this method is
different from the method that you wrote for part 2. That method
is a private static helper method; because it is static, it
doesn’t have a called object. The method that you are writing
here is non-static, and it should return the suit number of the
called object.)
getSuitName, which returns a String representation of the
Card object’s suit. For example, if c1 is the card shown in
the diagram above, c1.getSuitName() should return the string
"Hearts". This method should make use of the array of suit
names that we have given you.
getName, which returns a String representing the full name
of the Card. The returned String should have the form
“rank_name of suit_name”. For example, if a Card object
represents a 10 of Diamonds, this method should return
"10 of Diamonds". If a Card object represents a Queen of
Spades, this method should return "Queen of Spades". This
method can either make use of the RANK_NAMES and SUIT_NAMES
arrays that we have given you, or it can use other accessor
methods that you have already written.
isAce, which returns true if the Card is an Ace and and
false if it is not.
isFaceCard, which returns true if the Card is a face card
(Jack, Queen, or King) and and false if it is not.
getValue, which returns the Card object’s value. If the card
is a face card, then it should return a value of 10. Otherwise,
it should return the card’s rank. Hint: Use the isFaceCard()
method to check if it is a face card!
Make sure that your methods are non-static, because they need access to the fields in the called object. In addition, none of these methods should take an explicit parameter, because all of the information that they need is inside the called object.
Once you have completed your methods for parts 4 and 5, you can test them using the first client program that we’ve given you. See below for more detail.
Define the toString method (2 points)
Write a toString method that returns a String representation of
the Card object that can be used when printing it or concatenating
it to a String. We discuss this type of method in the lecture
notes, and we provide an example in our Rectangle
class.
The returned String should consist of the card’s rank abbreviation
followed immediately by its suit abbreviation. For example, if a
Card object represents a 10 of Diamonds, this method should return
"10D". If a Card object represents a Queen of Spades, this
method should return "QS". This method should make use of the
RANK_ABBREVS and SUIT_ABBREVS arrays that we have given you.
Define methods for comparing Card objects (3 points)
Finally, define the following two instance methods for comparing
Card objects:
sameSuitAs, which takes a Card object as a parameter and
determines if it is has the same suit as the called object,
returning true if they have the same suit and false if they
do not have the same suit. If a value of null is passed in for
the parameter, the method should return false.
equals, which takes a Card object as a parameter and
determines if it is equivalent to the called object, returning
true if it is equivalent and false if it is not equivalent.
Two Card objects should be considered equivalent if their rank
and suit are the same; the values should not be considered.
If a value of null is passed in for the parameter, the method
should return false.
Client programs and testing your code
To help you in testing your Card class, we have created two sample
client programs:
Make sure to put these client programs in your ps5 folder, and
don’t open them until the necessary parts have been completed.
In addition to using the client programs, we recommend that you
perform additional testing on your own. You can do so by adding code
to one of the clients, or by adding a main method to the Card
class.
Note: The static getSuitNum() method from part 2 is not directly
tested by the clients. However, it should be tested indirectly by
Client 1, because it should be called by one or more of the other
methods that you write. If you wanted to test it
directly, you could either add a main method to your Card class and
put some test code for it in that method, or you could temporarily
change it from private to public so that you can test it from a client.
If you are unable to get a given method to compile, make sure to comment out the body of the method (keeping the method header and possibly a dummy return value) so that we’ll still be able to test your other methods.
30 points; individual-only
In this problem, you will complete an implementation of the popular card game, Blackjack. The version of the game that you will complete allows a single human player (the user) to compete against the dealer. To simplify the logic, we will not allow betting.
In Blackjack, the goal is to assemble the hand with the highest value without going over a value of 21. Cards numbered 2-10 are worth their stated value (i.e., their value is equal to their rank). Face cards (Jacks, Queens, and Kings) have a value of 10. Aces have a value of 11, unless doing so would make the hand’s value exceed 21, in which case they have a value of 1. The best outcome is a combination of an ace with either a 10 or a face card; this gives a total value of 21 from only two cards, which is known as Blackjack.
The dealer starts by dealing two cards to the user of the game and two cards to herself. The dealer’s first card is dealt face down, and the other cards are revealed.
The user then begins his turn. He repeatedly decides whethers to request another card (which is known as a hit) or to hold his current hand. The user’s turn continues until he chooses to hold, or until the value of his hand is 21 or more.
Once the user’s turn is completed, the dealer begins her turn. She first reveals her hidden card. Then, provided that the user has not gone over 21, the dealer gives herself hits as needed in an attempt to win the game. In our version of Blackjack, the dealer will employ the following rules:
Note: If the user goes over 21, the dealer won’t even be asked to decide whether to take a hit.
Here are some sample runs of the game:
Notes about the sample runs:
The code for your Blackjack program will be divided into a number of
different classes. In particular, you will use the Card class that you
wrote for the previous problem.
In addition, we are giving you complete or nearly complete implementations of the following classes:
Deck.java
This class is a blueprint for objects
that represent a deck of 52 playing cards. These objects have
several methods, the most useful of which are the shuffle and
dealCard methods. It uses a random-number generator when shuffling
the cards to get a different ordering of the deck each time. When
testing your code, it’s possible to control the numbers generated by
the random-number generator so that you can get repeatable hands of
cards. See the section entitled Testing your code for more
details. You should not modify the code in this class.
Blackjack.java
This class contains the
main method of the program; you will run this class to start the
program. The class also includes several static methods, two of
which you will need to complete or modify. Note that this class is
not a blueprint class. It has no fields, and all of its methods
are static because they do not need a called object. You should
not make any modifications to this class except for the changes
specified in Tasks 3 and 4. In addition, this class will not
compile until you complete Task 2 below.
Download these files, making sure to store them in your ps5 folder
– the same folder in which you stored your Card.java file.
Begin by reading over the code that we have given you. In particular,
you should look at how the Blackjack class will make use of the types
of objects that you will create below. You do not need to fully
understand how the Deck class works, but we encourage you to look it
over.
Write a class named Player that serves as a blueprint for objects
that represent a single Blackjack player. Save it in the same folder as
the classes that you downloaded above. Import the java.util package at
the start of the file.
Each Player object should have the following components:
three fields:
name to keep track of the player’s name (a single
string)hand for an array to hold the cards
in the player’s handnumCards to keep track of how many cards are
currently in the player’s hand
Make sure that your field definitions
prevent direct access by code from outside the class.a constructor that takes a single parameter for the name of the
player. It should initialize all of the fields. Among other things,
it should create the array that will store the cards. Make the
collection big enough to store the maximum number of cards in a
given hand (11). Use the class constant
Blackjack.MAX_CARDS_PER_PLAYER to specify this value, rather than
hard-coding the integer 11.
an accessor named getName that returns the player’s name.
an accessor named getNumCards that returns the current number of
cards in the player’s hand.
a mutator named addCard that takes a Card object as a parameter
and adds the specified card to the player’s hand, filling the array
from left to right. It should throw an IllegalArgumentException if
the parameter is null, or if the player already has the maximum
number of cards.
an accessor named getCard that takes an integer index as a
parameter and returns the Card at the specified position in the
player’s hand, without actually removing the card from the hand.
For example, if p is a Player, p.getCard(0) should return the
card at position 0 in p‘s hand – i.e., the first/leftmost card.
If the specified index does not correspond to one of the cards in
the hand, the method should throw an IllegalArgumentException.
an accessor method named getHandValue that computes and returns
the total value of the player’s current hand – i.e., the sum of the
values of the individual cards. Use the getValue method from the
Card class to get each card’s value. One tricky aspect of this
method is handling any Aces that may be present in the hand. The
getValue method will return 1 for an Ace, but you may need to
change its value to 11 depending on the values of the rest of the
cards in the hand. Hint: If there is more than one Ace in the
hand, at most one of them can have a value of 11, and you should
only give it a value of 11 if doing so won’t cause the hand’s total
value to exceed 21.
an accessor method named printHand that prints the current
contents of the player’s hand, followed by the value of the player’s
hand. For example:
4H 7C QD (value = 21)
Notes:
There should be two spaces between the strings for the individual cards, and two spaces between the last card’s string and the left parenthesis at the start of the value.
This method should not print the player identifiers (“dealer: ” or “you: “) that come before the hands in the sample runs.
an accessor method named hasBlackjack that returns true if the
player has Blackjack (a two-card hand with a value of 21), and
false otherwise. This method will be relatively simple to write if
you take advantage of one or more of the other methods that you’ve
already written.
an accessor method called wantsHit that should return true if
the player wants another hit, and false if the player does not
want another hit. The method should take two parameters: a Scanner
object that can be used to read from the console, and a Player
object representing the player’s opponent (in that order). In this
version of the method:
nextLine method of the Scanner passed in as a
parameter. (Make sure that you do not use the Scanner‘s
next() method.) The method should return true if the user
enters “y” or “Y”, and it should return false if the user
enters any other input (even if it’s something other than “n” or
“N”).Player object for
the opponent). The version of this method that you will write in
Task 3 will use this second parameter, which is why we include
it here as well.a mutator method called discardCards that should get rid of all of
the cards in the player’s hand, to prepare for a new round of the
game. There are different ways to accomplish this. The key thing is
to ensure that immediately after this method is called, all other
methods that depend on the number of cards in the player’s hand
should behave as if the player has no cards.
After completing all of Task 2, you should be able to open and compile
the Blackjack class, and run it to play the game. At this point, the
computer will be represented by a Player object, which means that you
will be able to see all of its hand, and that its decisions about hits
will be determined using the wantsHit method that you implemented
above. In other words, you will need to decide on hits for both the user
(i.e., you) and the dealer.
If the Blackjack class doesn’t compile, that probably means that there
are problems in the headers of one or more of your Player methods.
Change your Player class as needed until the Blackjack class
compiles. Remember that you are not allowed to change the Card or
Deck classes in any way. In addition, you should not change the
Blackjack class at this point in the process.
The Player class that you wrote for Task 2 serves as a blueprint for
the human player in the game (the user). The dealer is also a player in
the game, but the dealer’s behavior is different in several respects
than the behavior of the user.
In this task, you will write a class named Dealer that serves as a
blueprint for an object that represents the dealer in the game. Save it
in the same folder as your other classes for this program. Import the
java.util package at the start of the file.
Much of the state and behavior needed for a Dealer object is already
present in the Player class. Thus, you should make Dealer a subclass
of Player, so that it will inherit the fields and methods of the
Player class.
In addition to the inherited fields and methods, this class will need:
a field of type boolean that indicates whether or not the dealer’s
first card should be revealed when the hand is printed. Make sure
that the field is properly encapsulated.
its own constructor, which takes no parameters. It should call
the constructor of the superclass to do the work of initializing the
inherited fields, passing it the string “dealer” as the name of the
player. In addition, it should initialize the boolean field to
reflect the fact that the dealer’s first card should not be
revealed at the start of a given round of the game.
a mutator method called revealFirstCard that takes no parameters
and changes the value of the called object’s boolean field to
indicate that the dealer’s first card should now be revealed. Note
that this method will not actually print any cards on its own.
Rather, by changing the value of the boolean field, it will cause
subsequent calls to the printHand method to reveal the first card.
a printHand method that overrides the inherited version of that
method. This version of the method should consult the called
object’s boolean field to determine what to do:
boolean field indicates that the first card should
not be revealed, then it should display the String “XX” in
place of the first card’s usual string. In addition, it should
not print the value of the hand. For example, here is one
possible output of this method when the first card is hidden:
XX 8Cboolean field indicates that the first card should be
displayed, then this method should produce the same output as
the superclass version of the method.This method – like all subclass methods – does not have direct access to the fields inherited from the superclass. For example, it cannot directly access the array of cards. Instead, it should make use of the appropriate accessor methods as needed (e.g., to get the cards that it needs to print).
a wantsHit method that overrides the inherited version of that
method. This version of the method should determine if the dealer
should give herself another hit, and return true or false
accordingly. See the section above entitled “Rules of the game” to
see when the dealer should take another hit and when she should
hold. Note that this method will ignore the first parameter of the
method (the Scanner object), but it will use the second parameter
of the method to obtain the necessary information about the
opponent’s hand.
a discardCards method that overrides the inherited version of that
method. This version of the method should have the same effect as
the inherited version of the method. In addition, it should reset
the called object’s boolean field to its original value, so that
the first card in the dealer’s next hand will not be revealed when
the hand is first printed.
Notes:
super. Even in cases in which it is
not essential to call the superclass method, you should do so if it
would allow you to simplify your code.Once you have defined your Dealer class, you should make the following
changes to the Blackjack class:
Modify the line in the main method that creates an object for the
dealer (assigning it to the variable dealer). Instead of assigning
a Player object to that variable, you should assign an instance of
your new subclass. The modified line should look like this:
Player dealer = new Dealer();
Note that you should not change the declared type of the
variable, because doing so would cause some of the other Blackjack
code to break. Polymorphism allows us to assign an object of type
Dealer to a variable of type Player, because Dealer is a
subclass of Player.
Uncomment the line in the playRound method that calls the
revealFirstCard method.
You should not make any other changes to the Blackjack class except
the change described below in Task 4.
If you have implemented everything correctly, the dealer’s first card and value should be hidden during the user’s turn, and the dealer should decide on its own hits, rather than asking you to make its decisions for it.
printResult methodIn Blackjack.java, implement the printResult method so that it
prints an appropriate message summarizing the results of a given hand.
Here are some special points to keep in mind when writing this method:
See the sample runs above for what the result messages should look like. Note that the user’s name is included in several of the messages.
Once all of these tasks are completed, you should have a working Blackjack game!
To get repeatable hands for testing purposes, you can specify a seed
for the random-number generator used by the Deck class when it
shuffles the deck. Here is one way to do so:
As needed, open the folder containing your code by using the File->Open Folder or File->Open menu option in VSCodium.
If you don’t already have a Terminal pane at the bottom of the VSCodium window, use the Terminal->New Terminal menu option to open one.
Enter the following command from the Terminal to compile your code:
javac Blackjack.java
If executing this command produces error messages describing bugs in your code, fix them, save the file(s) in VSCodium, and try again. Repeat this process until your code compiles without any error messages.
Enter the following command from the Terminal to run your code with a random seed:
java Blackjack seed
where you replace seed with an integer.
Other testing notes
If you make any changes to your code, make sure to:
Save the changed file(s) in VSCodium.
Recompile your code by executing
javac Blackjack.java
before you attempt to rerun the program.
To make sure that the wantsHit method in your Dealer class is
working correctly, you may want to temporarily comment out the
printHand method in that class. Doing so will cause all of the
dealer’s cards to be displayed, which will allow you to see if
wantsHit is making the correct decision. Make sure to uncomment
printHand before submitting the file.
Important
If you chose to work on Problem 7 with a partner, both you and your partner should submit your own copy of your joint work, along with your individual work on Problem 8.
You should submit only the following files:
Card.javaBlackjack.javaPlayer.javaDealer.java Here are the steps:
Click on the name of the assignment in the list of assignments. You should see a pop-up window with a box labeled DRAG & DROP. (If you don’t see it, click the Submit or Resubmit button at the bottom of the page.)
Add your files to the box labeled DRAG & DROP. You can either drag and drop the files from their folder into the box, or you can click on the box itself and browse for the files.
Click the Upload button.
You should see a box saying that your submission was successful.
Click the (x) button to close that box.
The Autograder will perform some tests on your file. Once it is done, check the results to ensure that the tests were passed. If one or more of the tests did not pass, the name of that test will be in red, and there should be a message describing the failure. Based on those messages, make any necessary changes. Feel free to ask a staff member for help.
Note: You will not see a complete Autograder score when you submit. That is because additional tests will be run later, after the final deadline for the submission has passed. For such problems, it is important to realize that passing all of the initial tests does not necessarily mean that you will ultimately get full credit on the problem. You should always run your own tests to convince yourself that the logic of your solutions is correct.
If needed, use the Resubmit button at the bottom of the page to resubmit your work. Important: Every time that you make a submission, you should submit all of the files for that Gradescope assignment, even if some of them have not changed since your last submission.
Near the top of the page, click on the box labeled Code. Then click on the name of each file to view its contents. Check to make sure that you see the code that you want us to grade.
Important
It is your responsibility to ensure that the correct version of every file is on Gradescope before the final deadline. We will not accept any file after the submission window for a given assignment has closed, so please check your submissions carefully using the steps outlined above.
If you are unable to access Gradescope and there is enough
time to do so, wait an hour or two and then try again. If you
are unable to submit and it is close to the deadline, email
your homework before the deadline to
cscis111-staff@lists.fas.harvard.edu
Last updated on July 14, 2026.