Com S 227 Assignment 1 to 4 solutions

$110.00

Original Work ?
Category: Tags: , You will Instantly receive a download link for .ZIP solution file upon Payment

Description

5/5 - (1 vote)

Com S 227 Assignment 1

For this assignment you will create a hot air balloon simulator. Specifically, you are
implementing a single class called Balloon, that models the flight of a hot air balloon taking
multiple factors into account, for example: the mass of the balloon, outside air temperature,
available fuel, rate of fuel burn, etc.

A hot air balloon is a lighter-than-air aircraft
consisting of a bag, called an envelope, which
contains heated air. Suspended beneath is a
gondola or wicker basket (in some long-distance or
high-altitude balloons, a capsule), which carries
passengers and a source of heat, in most cases an
open flame caused by burning liquid propane. The
heated air inside the envelope makes it buoyant,
since it has a lower density than the colder air
outside the envelope.

https://en.wikipedia.org/wiki/Hot_air_balloon
The simulation models fuel being burned to heat the air inside of a balloon. The heated air inside
of the balloon has a lower density than the air outside of the balloon, generating a lifting force.
When the lifting force overcomes gravity, the balloon rises. The balloon can also drop when the
lifting force is not greater than gravity, but of course, the balloon can’t drop below ground level.

Also, the balloon is on a tether (rope attached to the ground) that prevents it from getting too
high. As time passes in the simulation, the altitude of the balloon is calculated as Aballoon, as long
as it is between ground level and the maximum extent of the tether, using the following
equations.

Inputs to the simulation
Air temperature outside the balloon in C.
Toutside
Rate of fuel burn per second in kBTU/s.
B
Balloon mass.
m
Provided simulation constants
Heat loss factor.
H = 0.1
The volume of air in the balloon in m3
V = 61234
Acceleration due to gravity in m/s2
.
Ag = 9.81
The gas constant in J/kgK.
R = 287.05
Standard pressure in hPa.
P = 1013.25
Kelvins at 0 degrees C.
Kc = 273.15

Simulation calculations

The rate of change in the balloon’s air temperature per second (assuming sufficient fuel).
ΔT = B + (Toutside – Tballoon) × HEAT_LOSS
The temperature of the air inside of the balloon after one second.
Tballoon at current time = Tballoon one second ago + ΔT
Density of the surrounding air (kg/m3
).
ρ! = �
R ( �”#$%&'( + �! )
Density of the balloon air (kg/m3
).
ρ# = �
R ( �)*++””, + �! )
Force of lift in N.
FL = V (ρc – ρu) Ag
Force of gravity in N.
Fg = m Ag
Net force in upward direction in N.
Fn = FL – Fg

Note: this gives wrong results when the balloon is on the ground or at the end of the tether, the
net force should be zero, but we will ignore this detail for the sake of simplicity.
Net acceleration in upward direction.
An = Fn / m
Velocity in upward direction (assuming 1 second of time) in m/s.
vat time n = vat time n-1 + An
The altitude of the balloon after one second.
Aballoon at time n = Aballoon at time n-1 + vat time n

Special Assignment Requirements

You are not allowed to use conditional statements in this homework. That means
specifically no “if” or “if-else” statements, no loops of any sort, and no ternary operators
(don’t worry if you don’t know what those are yet).
But why?

The purpose of this assignment is to give you practice using variables and mathematical
expressions. Wouldn’t it be just as easy to use conditionals to solve this particular assignment?
Perhaps, but that won’t always be the case. Professional programmers use mathematical
expression every day to simplify code, make it more readable, and make it more efficient. You’re
not ready yet to write code for the Linux kernel or the InnoDB database engine or the javac
compiler… So, we decided to give you an easier programming assignment and artificially tie
your hands (so to speak) by forcing you to implement the logic with only variables and
mathematically expressions. Some day when you are adding a patch to the Linux kernel you
might thank us for the practice.

Hints: To solve this assignment you will need to declare instance and local variables, that part of
the program design is up to you. There will be a couple of places where you need to choose the
larger or smaller of two numbers, which can be done with the methods Math.max()
or Math.min(). For example, the balloon has a minimum and maximum allowable altitude,
ground level (0) and the height of the tether respectively. These functions can be used to enforce
the altitude boundaries. For the wrapping (circular) behavior, you can use the mod (%) operator.
Yes, it is possible to solve this assignment very neatly with just what we have learned so far in
class, and the challenge of doing so will make you a better programmer! You will be penalized
slightly for using conditional statements, keep in mind that if you really can’t figure it out, it’s
better to turn in something working than nothing at all.

More about grading
This is a “regular” assignment so we are going to read your code. Your score will be based partly
(about 2/3) on the specchecker’s functional tests and partly on the TA’s assessment of the quality
of your code. This means you can get partial credit even if you have errors, but it also means that
even if you pass all the specchecker tests you can still lose points. Are you doing things in a
simple and direct way that makes sense? Are you defining redundant instance variables? Are you
using a conditional statement when you could just be using Math.min? Are you using a loop for
something that can be done with integer division? Some specific criteria that are important for
this assignment are:
• Use instance variables only for the “permanent” state of the object, use local variables for
temporary calculations within methods.
o You will lose points for having unnecessary instance variables
o All instance variables should be private.
• Accessor methods should not modify instance variables.
See the “Style and documentation” section below for additional guidelines.
Style and documentation
Roughly 15% of the points will be for documentation and code style. Here are some general
requirements and guidelines:
• The class and every method, constructor and instance variable, whether public or
private, must have a meaningful Javadoc style comment. The javadoc for the class
itself can be very brief, but must include the @author tag. The javadoc for methods must
include @param and @return tags as appropriate. The javadoc for instance variables can
be a very short description of the purpose of the variable.
• Try to briefly state what each method does in your own words. However, there is no rule
against copying the descriptions from the online documentation. However: do not
literally copy and paste from this pdf! This leads to all kinds of weird bugs due to the
potential for sophisticated document formats like Word and pdf to contain invisible
characters.
• Run the javadoc tool and see what your documentation looks like! (You do not have to
turn in the generated html, but at least it provides some satisfaction 🙂
o All variable names must be meaningful (i.e., named for the value they store).
o Your code should not be producing console output. You may add println
statements
o when debugging, but you need to remove them before submitting the code.
o Internal (//-style) comments are normally used inside of method bodies to explain
how something works, while the Javadoc comments explain what a method does.
(A good rule of thumb is: if you had to think for a few minutes to figure out how
something works, you should probably include an internal comment explaining
how it works.)
• Internal comments always precede the code they describe and are indented to the same
level. In a simple homework like this one, as long as your code is straightforward and you
use meaningful variable names, your code will probably not need any internal comments.
• Use a consistent style for indentation and formatting.
• Note that you can set up Eclipse with the formatting style you prefer and then use Ctrl-Shift-F to
format your code. To play with the formatting preferences, go to Window- >Preferences->Java-
>Code Style->Formatter and click the New button to create your own “profile” for formatting.

The SpecChecker
A significant portion (but not all) of the points for this assignment are based on the specchecker
score. It is not advised to wait until the last day to run the SpecChecker on your code.
You can find the SpecChecker on Canvas. Import and run the SpecChecker just as you practiced
in Lab 1. It will run a number of functional tests and then bring up a dialog offering to create a
zip file to submit. Remember that error messages will appear in the console output. There are
many test cases so there may be an overwhelming number of error messages. Always start
reading the errors at the top and make incremental corrections in the code to fix them. When
you are happy with your results, click “Yes” at the dialog to create the zip file. Submit the zip to
the Canvas assignment.

The UI
For your amusement, and as a reward for when everything is implemented, a UI has been
provided with this assignment. Be aware that UIs are generally not a good tool for testing and
debugging code. The UI might give you a hint when something is wrong, but it won’t catch
every error and it won’t tell you much about the cause of an error. The bottom line is that you
should test your code by writing simple tests and print out the values of calculations to help
understand the cause of bugs.
To use the UI, download hw1ui.jar. Follow the same instructions as the specchecker to setup
and run the UI. Running the jar as an application should start the UI.

Specification
The specification for this assignment includes this pdf along with any “official” clarifications
announced on Canvas. The specification is for a single class Balloon. You may (are encouraged
to) create a second class called SimpleTests (as described in the Suggestions for getting started
section) for your own testing purposes, but you will not be graded on that class.
There are 6 constant values defined in the table of formulas in the Overview section of this
document. Use best programming practices when incorporating these constant values in your
code.

There is one public constructor:
public Balloon(double airTemp, double windDirection)
Constructs a new balloon simulation. The simulation starts with the given airTemp (outside air
temperature in C) and windDirection (in degrees). It is assumed windDirection is between 0
(inclusive) and 360 (exclusive). The balloon temperature (air inside the balloon) is initialized to
the same temperature as the outside air. The simulation time is initialized to the default value 0.
The balloon’s altitude, remaining fuel, fuel burn rate, balloon mass, velocity, and tether length
are all initialized to 0.

There are the following public methods:
public double getFuelRemaining()
Gets the remaining fuel that can be used to heat the air in the balloon.
public void setFuelRemaning(double fuel)
Sets the remaining fuel that can be used to heat the air in the balloon.
public double getBalloonMass()
Gets the mass of the balloon (m in the formulas).
public void setBalloonMass(double mass)
Sets the mass of the balloon (m in the formulas).
public double getOutsideAirTemp()
Gets the outside air temperature (Toutside in the formulas).
public void setOutsideAirTemp(double temp)
Sets the outside air temperature (Toutside in the formulas).
public double getFuelBurnRate()
Gets the fuel burn rate (B in the formulas).
public void setFuelBurnRate(double rate)
Sets the fuel burn rate (B in the formulas).
public double getBalloonTemp()
Gets the balloon temperature (Tballoon in the formulas).
public void setBalloonTemp(double temp)
Sets the balloon temperature (Tballoon in the formulas).
public double getVelocity()
Gets the balloon velocity (v in the formulas).
public double getAltitude()
Gets the balloon altitude.
public double getTetherLength()
Gets the length of the tether.
public double getTetherRemaining()
Gets the length of the tether minus the current altitude of the balloon.
public void setTetherLength(double length)
Sets the length of the tether.
public double getWindDirection()
Gets the direction of the wind in degrees, a number between 0 (inclusive) and 360 (exclusive).
public void changeWindDirection(double deg)
Updates the wind direction by adding the giving value (which is assumed to be between -360 and
360 exclusive) on to the current wind direction. The wind direction must always be between 0
(inclusive) and 360 (exclusive).
Hint: If the direction goes below 0 or to 360 or higher you need to get it back to between 0 to
360. There is more than one way to do this. Do be careful that the modulus of a negative number
has an unexpected result in Java. For example, -1 % 2 is -1. One simple way to deal with this is
to add an extra 360 degrees to avoid any negative values in the first place.
public long getMinutes()
Gets the number of full minutes that have passed in the simulation. For example, if the
simulation time is 179, minutes = 2 and seconds = 59.
public long getSeconds()
Gets the number of seconds passed the number of full minutes. For example, if the simulation
time is 179, minutes = 2 and seconds = 59. The seconds should always be between 0 and 59
inclusive.
public void update()
Calling this method represents 1 second of simulated time passing. Specifically, the simulation
time is incremented by 1. The fuel remaining is consumed at the set fuel burn rate, but it can
never drop below 0. If the fuel burn rate is more than the available amount of fuel then consume
as much fuel as is available but no more. The temperature inside of the balloon is updated (see
formulas in the Overview section).
The velocity and position of the balloon is also updated based on the formulas. Note that the
calculations for velocity and position at time n depend on the velocity and position at time n-1
(one second ago). In other words, each calculation of velocity and position depends on the
previous calculation.
There are two exceptions to the calculation of the position of the balloon; the balloon can never
drop below ground level (an altitude of 0) and can never rise above the length of the tether. That
is to say, the ground level and the tether length are the minimum and maximum altitudes
respectively. The velocity and altitude can only be calculated after updating the balloon
temperature.
public void reset()
Calling this method resets the simulation to its initial state (the same state it had immediately
after the constructor was called). Pay attention that the outside air temperature and wind
direction are reset to the values that were provided to the constructor. (Hint: How will you do
that when those parameters are not in the scope of this method? You have learned all the tools
necessary; but it will take some planning to implement the solution.)
Where’s the main() method??
There isn’t one! Like most Java classes, this isn’t a complete program and you can’t “run” it by
itself. It’s just a single class, that is, the definition for a type of object that might be part of a
larger system. To try out your class, you can write a test class with a main method like the
examples below in the getting started section.
There is also a specchecker (see below) that will perform a lot of functional tests, but when you
are developing and debugging your code at first you’ll always want to have some simple test
cases of your own, as in the getting started section below.

Suggestions for getting started
Smart developers don’t try to write all the code and then try to find dozens of errors all at once;
they work incrementally and test every new feature as it’s written. Since this is our first
assignment, here is an example of some incremental steps you could take in writing this class.
0. Be sure you have done and understood Lab 2.
1. Create a new, empty project and then add a package called hw1. Be sure to choose “Don’t
Create” at the dialog that asks whether you want to create module-info.java.
2. Create the Balloon class in the hw1 package and put in stubs for all the required methods, the
constructor, and the constants. Remember that everything listed is declared public. For methods
that are required to return a value, for now, just put in a “dummy” return statement that returns
zero or false. There should be no compile errors. WARNING: be careful about COPY AND
PASTE from this pdf! This may lead to insidious bugs caused by invisible characters that are
sometimes generated by sophisticated document formats. It’s better to re-type it by hand.
3. Briefly javadoc the class, constructor, and methods. This is a required part of the assignment
anyway, and doing it now will help clarify for you what each method is supposed to do before
you begin the actual implementation. (Copying phrases from the method descriptions here or in
the Javadoc is acceptable, however, see waring above.)
4. Look at each method. Mentally classify it as either an accessor (returns some information
without modifying the object) or a mutator (modifies the object, usually returning void). The
accessors will give you a lot of hints about what instance variables you need.
5. You could start by deciding how to keep track of the balloon’s fuel. The presence of a method
getFuelRemaining suggests an instance variable might be useful to keep track how much fuel
remains in the tank. Keep in mind the specification states the fuel remaining starts empty. In a
separate class (and file), write a simple test to see if this much is working as it should:
public static void main(String args[]) {
Balloon b = new Balloon(20, 90);
System.out.println(“Test 1:”);
System.out.println(“Fuel remaining is ”
+ b.getFuelRemaining() + ” expected 0.”);
System.out.println(“Adding 1000 to fuel.”);
b.setFuelRemaning(1000);
System.out.println(“Fuel remaining is ”
+ b.getFuelRemaining() + ” expected 1000.”);
(Tip: you can find code for the simple test case above, along with the others discussed in this
section, in the class SimpleTests.java linked from the assignment page on Canvas.)
6. In addition to fuel remaining, there are 5 other values described in the specification for the
constructor that have simple getters and setters associated with them (we will skip time, wind
direction and velocity for now). Implements these getters and setters and update the constructor.
System.out.println(“Test 2:”);
System.out.println(“Air temp is ” + b.getOutsideAirTemp()
+ ” expected 20.”);
System.out.println(“Balloon temperature is ”
+ b.getBalloonTemp() + ” expected 20.”);
System.out.println(“Fuel burn rate is ” + b.getFuelBurnRate()
+ ” expected 0.”);
System.out.println(“Tether length is ” + b.getTetherLength()
+ ” expected 0.”);
System.out.println(“Balloon mass is ” + b.getBalloonMass()
+ ” expected 0.”);
b.setOutsideAirTemp(18);
b.setBalloonTemp(25);
b.setFuelBurnRate(5);
b.setTetherLength(100);
b.setBalloonMass(110);
System.out.println(“Air temp is ” + b.getOutsideAirTemp()
+ ” expected 18.”);
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 25.”);
System.out.println(“Fuel burn rate is ” + b.getFuelBurnRate()
+ ” expected 5.”);
System.out.println(“Tether length is ” + b.getTetherLength()
+ ” expected 100.”);
System.out.println(“Balloon mass is ” + b.getBalloonMass()
+ ” expected 110.”);
7. Now you can start working on two of the slightly less strait forward methods, the getMinutes
and getSeconds methods. These methods imply you need some way of keeping track of the
current time. Should it be two separate variables or a single variable that can be used to derive
minutes and seconds? That is up to you. The only way time can increment is when update is
called. You don’t need to implement all of update, but for now just add the code to increment
time by one second.
System.out.println(“Test 3:”);
System.out.println(“Minutes is ” + b.getMinutes() + ” expected 0.”);
System.out.println(“Seconds is ” + b.getSeconds() + ” expected 0.”);
b.update();
b.update();
b.update();
System.out.println(“Minutes is ” + b.getMinutes() + ” expected 0.”);
System.out.println(“Seconds is ” + b.getSeconds() + ” expected 3.”);
8. The next set of methods to implement are the getWindDirection and changeWindDirection
methods. You must ensure that the direction always remains between 0 (inclusive) and 360
(exclusive). See the specification of changeWindDirection for some helpful hints.
System.out.println(“Test 4:”);
System.out.println(“Wind direction is ” + b.getWindDirection()
+ ” expected 90.”);
b.changeWindDirection(180);
System.out.println(“Wind direction is ” + b.getWindDirection()
+ ” expected 270.”);
b.changeWindDirection(90);
System.out.println(“Wind direction is ” + b.getWindDirection()
+ ” expected 0.”);
b.changeWindDirection(-90);
System.out.println(“Wind direction is ” + b.getWindDirection()
+ ” expected 270.”);
9. Before continuing, it is time to implement the reset method. This method is mostly straight
forward, but you will need to devise a plan for how to set the air temperature and wind direction
back to the values that were passed to the constructor.
System.out.println(“Test 5:”);
b.reset();
System.out.println(“Air temp is ” + b.getOutsideAirTemp()
+ ” expected 20.”);
System.out.println(“Wind direction is ” + b.getWindDirection()
+ ” expected 90.”);
System.out.println(“Fuel remaining is ” + b.getFuelRemaining()
+ ” expected 0.”);
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 20.”);
System.out.println(“Fuel burn rate is ” + b.getFuelBurnRate()
+ ” expected 0.”);
System.out.println(“Tether length is ” + b.getTetherLength()
+ ” expected 0.”);
System.out.println(“Balloon mass is ” + b.getBalloonMass()
+ ” expected 0.”);
10. Finally, it is time to implement the update method. For this method you will need to
implement the formulas described in the Overview section of this document. Remember that you
can use local variables to break up longer calculations into smaller parts. Math functions such as
min and max may be helpful when implementing the upper and lower bounds on the altitude.
System.out.println(“Test 6:”);
b.setBalloonMass(100);
b.setBalloonTemp(70);
b.setFuelBurnRate(5);
b.setFuelRemaning(10);
b.setTetherLength(100);
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 70.”);
System.out.println(“Balloon velocity is ” + b.getVelocity()
+ ” expected 0.”);
System.out.println(“Altitude is ” + b.getAltitude()
+ ” expected 0.”);
b.update();
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 70.”);
System.out.println(“Balloon velocity is ” + b.getVelocity()
+ ” expected 0.72…”);
System.out.println(“Altitude is ” + b.getAltitude()
+ ” expected 0.72…”);
b.update();
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 70.”);
System.out.println(“Balloon velocity is ” + b.getVelocity()
+ ” expected 1.45…”);
System.out.println(“Altitude is ” + b.getAltitude()
+ ” expected 2.18…”);
// note: at time point fuel has run out
b.update();
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 65.”);
System.out.println(“Balloon velocity is ” + b.getVelocity()
+ ” expected 1.27…”);
System.out.println(“Altitude is ” + b.getAltitude()
+ ” expected 3.46…”);
b.update();
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 60.5.”);
System.out.println(“Balloon velocity is ” + b.getVelocity()
+ ” expected 0.24…”);
System.out.println(“Altitude is ” + b.getAltitude()
+ ” expected 3.70…”);
b.update();
System.out.println(“Balloon temperature is ” + b.getBalloonTemp()
+ ” expected 56.45.”);
System.out.println(“Balloon velocity is ” + b.getVelocity()
+ ” expected -1.56…”);
System.out.println(“Altitude is ” + b.getAltitude()
+ ” expected 2.14…”);
11. At some point, download the SpecChecker, import it into your project as you did in lab 1 and
run it. Always start reading error messages from the top. If you have a missing or extra public
method, if the method names or declarations are incorrect, or if something is really wrong like
the class having the incorrect name or package, any such errors will appear first in the output and
will usually say “Class does not conform to specification.” Always fix these first.
If you have questions
For questions, please see the Piazza Q & A pages and click on the folder hw1. If you don’t find
your question answered, then create a new post with your question. Try to state the question or
topic clearly in the title of your post, and attach the tag hw1. But remember, do not post any
source code for the classes that are to be turned in. It is fine to post source code for general Java
examples that are not being turned in. (In the Piazza editor, use the button labeled “pre” to have
Java code formatted the way you typed it.)
If you have a question that absolutely cannot be asked without showing part of your source code,
make the post “private” so that only the instructors and TAs can see it. Be sure you have stated a
specific question; vague requests of the form “read all my code and tell me what’s wrong with it”
will generally be ignored.
Of course, the instructors and TAs are always available to help you. See the Office Hours section
of the syllabus to find a time that is convenient for you. We do our best to answer every question
carefully, short of actually writing your code for you, but it would be unfair for the staff to fully
review your assignment in detail before it is turned in.
Any announcements from the instructors on Canvas that are labeled “Official Clarification” are
considered to be part of the spec, and you may lose points if you ignore them. Such posts will
always be placed in the Announcements section of Canvas. (We promise that no official
clarifications will be posted within 24 hours of the due date.)

What to turn in

Note: You will need to complete the “Academic Dishonesty policy questionnaire,” found on
the Assignments page on Canvas, before the submission link will be visible to you.
Please submit, on Canvas, the zip file that is created by the SpecChecker. The file will be named
SUBMIT_THIS_hw1.zip. and it will be located in whatever directory you selected when you ran
the SpecChecker. It should contain one directory, hw1, which in turn contains one file,
Balloon.java. Please LOOK at the file you upload and make sure it is the right one!
Submit the zip file to Canvas using the Assignment 1 submission link and VERIFY that your
submission was successful. If you are not sure how to do this, see the document “Assignment
Submission HOWTO”, linked on the Course Information page on Canvas.

We recommend that you submit the zip file as created by the specchecker. If necessary for some reason, you can
create a zip file yourself. The zip file must contain the directory hw1, which in turn should contain the files
Balloon.java. You can accomplish this by zipping up the src directory of your project. Do not zip up the entire
project. The file must be a zip file, so be sure you are using the Windows or Mac zip utility, and NOT a third-party
installation of WinRAR, 7-zip, or Winzip.

Document updates:
01/30 On page 16, the name of the file the SpecChecker puts into the zip is called
“Balloon.java”.
01/30 Fixed example test code in “Suggestions for getting started” section to match with
provided SimpleTests.java file.
02/02 Method name change to setFuelRemaning to match specchecker (see announcement).
Added comment “assuming sufficient fuel” to formula (see announcement).

Com S 227 Assignment 2

The purpose of this assignment is to give you lots of practice working with conditional logic and
managing the internal state of a class. You’ll create one class, called FuzzballGame, that is a
model of an obscure game played with a ball and a stick1. Although there is some resemblance to
the American game of baseball, it’s probably best if you forget everything you know about
baseball as you read these instructions.

Your job is to implement the rules of the game that is
specified in this document even if that conflicts with your understanding of any other baseball
game rules.

Here is how it works. There are two teams, which we will call “Team 0” and “Team 1” that take
turns as the batting team and the fielding team. At each step of the game, a player called the
pitcher from the fielding team, standing in a designated location, throws the ball towards a player
on the batting team called the batter, also standing in a designated location called home. The
batter, at his or her discretion, tries to hit the ball with a stick and make it go a very long
distance. Another player from the fielding team, called the catcher, crouches behind the batter
and catches the ball if the batter doesn’t hit it. Behind the catcher is an official called the umpire,
whose job is to decide whether the pitch was accurately thrown.

Some possible outcomes are:
• The batter swings the stick at the ball and misses. This is a strike, and the batter is
immediately out.
• The batter doesn’t swing at the ball, but the umpire declares that it was accurately thrown.
This is a called strike. The batter isn’t immediately out, but the called strike is added to a
count for that batter, and after a certain number of them, the batter is out.
• The batter doesn’t swing at the ball, but the umpire declares that it wasn’t accurately
thrown. This is called a ball, and is added to the batter’s count of balls. What this means
is discussed below.

• The batter hits the ball, but it goes less than 15 feet, or flies behind the batter. This is a
foul, and the batter is immediately out.
• The batter hits the ball, but someone on the fielding team catches it before it bounces.
This is a caught fly, and the batter is immediately out.
• The batter hits the ball and it goes 15 feet or more, in the right direction, and isn’t caught
by the fielding team. This is a hit. Depending on the distance the ball goes, it is called a
single, double, triple, or home run, the consequences of which are discussed below.
Outs
If a batter is out, one of two things happens: if the number of outs for the batting team has
reached a designated maximum (usually 3), the teams switch sides: the fielding team becomes
the batting team, and the batting team becomes the fielding team, and all the imaginary runners
(see below) are cleared off the bases. In any case, the counts of balls and strikes are reset to zero
for a new batter.

1 https://en.wikipedia.org/wiki/Fuzzball_(sport)

Hits
Close your eyes, breathe deeply, and imagine three locations. Everyone playing the game has in
his or her mind a picture of three locations, known as first base, second base, and third base. A
base may be occupied by an imaginary runner. When a batter hits a single, an imaginary runner
goes to first base. Any imaginary runners that were already on the imaginary bases automatically
advance to the next one: first base to second base, second base to third base, and third base to
“home”. Each time an imaginary runner advances to home, the team earns a point. This is
important, because it’s by accumulating points that you win the game!
When the batter hits a double, the same process essentially happens twice: an imaginary runner
goes to second base, leaving first base empty, and any runners already on the bases advance
twice. (Note that an imaginary runner reaching home always stops there, and does not keep going
around to first base again!) Likewise, in case of a triple, an imaginary runner goes to third base,
and any runners already on base advance three times. In case of a home run, the runners advance
four times, so the bases always end up empty, and the team always earns at least one point, and
possibly up to four points.

After any hit or out, the counts of balls and strikes is reset to zero for a new batter.

Singles, Doubles, Triples, Home Runs

If the batter hits the ball but it travels less than 15 feet in front of the batter, or goes a negative
distance (behind the batter), as noted above it’s considered a foul and the batter is out. Otherwise,
as long as it’s not a caught fly, it’s a hit, and the interpretation of the distance the ball travels is as
follows:
1. At least 15 feet but less than 150: the hit is a single
2. At least 150 feet but less than 200: the hit is a double
3. At least 200 feet but less than 250: the hit is a triple
4. 250 feet or more: the hit is a home run

Balls
If the batting player’s count of balls reaches a certain point (usually 5), the pitching stops and the
batter gets what is called a walk. What this means is that, as with a single, an imaginary runner is
placed on first base. However, the imaginary runners on other bases don’t automatically advance
one base as they do for a hit; they only do so if forced to by the advancement of another
imaginary runner. As an example: suppose there are runners on first and third base and the batter
gets a walk. The new imaginary runner is placed on first, the runner on first is forced to advance
to second, but the batter on third stays there. After a walk, the counts of balls and strikes are reset
to zero for a new batter.

Innings, “top” and “bottom”, and winning the game
The game is divided into rounds called innings. In each inning, each team gets a chance to be the
batting team, always starting with Team 0; when the designated number of outs is reached, Team
1 becomes the batting team. The maximum number of innings for a game is configurable via a
constructor parameter. Whichever team has the most points after the last inning is the winner. It
is possible to have a tie, in which case both teams are considered to “win” the game. As a matter
of terminology, the first part of the inning when Team 0 is batting is called the top, and the
second part when Team 1 is batting is called the bottom.
Specification
The specification for this assignment includes this pdf, the online Javadoc, and any “official”
clarifications announced on Canvas.

Where’s the main() method?
There isn’t one! Like most Java classes, this isn’t a complete program and you can’t “run” it by
itself. It’s just a single class, that is, the definition for a type of object that might be part of a
larger system. To try out your class, you can write a test class with a main method like the
examples below in the getting started section.
There is also a specchecker (see below) that will perform a lot of functional tests, but when you
are developing and debugging your code at first you’ll always want to have some simple test
cases of your own, as in the getting started section below.
Suggestions for getting started
Smart developers don’t try to write all the code and then try to find dozens of errors all at once;
they work incrementally and test every new feature as it’s written. Here is example of some
incremental steps you could take in writing this class.

1. Create a new, empty project and then add a package called hw2. Be sure to choose “Don’t
Create” at the dialog that asks whether you want to create module-info.java.
2. Create a package named hw2. Download the skeleton code version of FuzzballGame.java
and copy it into your project. The easiest way to do this is by drag-and-dropping the file into
src/hw2 in Eclipse.
3. At this point, the FuzzballGame class will not even compile. Getting the code to compile
should be your top priority. Add stubs for all the methods and the constructor which are
described in the Javadoc provided with the assignment. Document each one. For methods that
need to return a value, just return a “dummy” value (e.g., 0 or false) as a placeholder for now. At
this point there should be no compile errors in the project.
3. Try a very simple test like this:
public class SimpleTests {
public static void main(String[] args) {
FuzzballGame game = new FuzzballGame(3);
System.out.println(game);
}
}
You should see an output string like this, produced by the toString() method:
ooo Inning:0 [B] Score:0-0 Balls:0 Strikes:0 Outs:0
Note that in printing the variable game, the println method automatically invokes the method
game.toString(). The toString method just calls your other accessor methods to get the
values to put in the string.

4. The initial values seen in the output string above are not quite right. We should start out at the
top of inning 1. You might start with the methods whichInning() and isTopOfInning() ,
which implies defining an instance variable to count innings, and an instance variable to keep
track of whether it’s the top or bottom of the inning. Once you have these initialized correctly in
the constructor, the test above should give you the output:
ooo Inning:1 [T] Score:0-0 Balls:0 Strikes:0 Outs:0
5. Next you could think about counting the balls, strikes, and outs. You’ll need three instance
variables for these three values, and their values are returned by the corresponding accessor
methods getBallCount(), getCalledStrikes(), and getCurrentOuts(). Remember that
accessor methods never modify instance variables, they only observe them and return
information.
6. You will have noticed that there are several mutator methods that will cause the game to
change state by simulating what happens when the pitcher pitches the ball: ball(),
caughtFly(), hit(), and strike(). Think about what happens after a sequence of strikes.
Remember that we distinguish between strike(true) (a “swung” strike) and strike(false)
(a “called” strike). For the former, the batter is out immediately, but for the latter, the batter is out
after two called strikes, so we should be able to check:
game.strike(false);
System.out.println(game); // one strike
game.strike(false);
System.out.println(game); // 0 strikes, one out, since it’s a new batter
game.strike(false);
System.out.println(game); // one strike, one out
game.strike(false);
System.out.println(game); // 0 strikes, two outs, since it’s a new batter
Add logic to the strike method to start a new batter after two called strikes as above.

7. Now, suppose you continue the test case above where we have two outs in the top of the first
inning. When there is one more out, the teams switch, which we observe by seeing that
isTopOfInning now returns false, and team 1 starts with no outs:
game.strike(true); // batter is immediately out for swung strike
System.out.println(game.isTopOfInning()); // should be false now
System.out.println(game); // bottom of 1st inning, 0 outs
The final line of output above should be,
ooo Inning:1 [B] Score:0-0 Balls:0 Strikes:0 Outs:0
After that, if team 1 gets three outs, the game should transition to the top of inning 2. You should
be able to create a short example that transitions all the way to the end of the game. At the end of
a three-inning game, whichInning() would return 4, and gameEnded() would return true.
8. A batter could also be out because of a caught fly ball. Go ahead and implement
caughtFly(), which should have the same effect as strike(true).
9. What about hit() ? In the case that the distance is less than 15, it’s an automatic out for the
batter, which you already know how to handle as above. But if the distance is 15 or greater, we
have to start thinking about the imaginary runners. How will you keep track, for bases 1, 2, and
3, whether there is an imaginary runner there or not? Decide how to do that, and implement the
accessor method runnerOnBase().

10. Maybe a good place to start is with singles. What should happen here?
game = new FuzzballGame(3);
game.hit(15);
System.out.println(game.runnerOnBase(1)); // true
System.out.println(game.getBases()); // Xoo
(The getBases method, which is already implemented for you, returns a string representation of
the bases, where “Xoo” indicates that there is a runner on first, but not on second or third.) If we
get another single, there should be runners on first and second:
game.hit(15);
System.out.println(game.getBases()); // XXo
Continuing the example above, after another single, there should be runners on all three bases:
game.hit(15);

System.out.println(game.getBases()); // XXX
What is a good way to make that happen without going nuts considering all possible cases? For
example, if you had a runner just on second (“oXo”) and there was a single, you should end up
with runners on first and third (“XoX”). One idea is to implement a helper method, e.g.
shiftRunners(), that simply shifts all runners to the next base.
Tip: shiftRunners() is probably easiest to implement by updating third and working backward to first and
second.
11. Finally, continuing the example above, what if there is one more single:
game.hit(15);
System.out.println(game.getBases()); // XXX
System.out.println(game.getTeam0Score()); // 1
There will still be runners on all three bases, but the imaginary runner on third base will have run
to home, which counts as a point for team 0. Add instance variables to keep track of the score,
and add logic to your helper method to adjust the score when a runner gets back to home.
12. Next, you could add the logic to the hit() method to take different action depending on
whether the distance represents a double, triple, or home run. Your shiftRunners() method, if
you chose to implement one, will be very useful here, since for a double all you really have to do
is shift the runners twice (the first time, also adding a runner on first); for a triple you do it three
times, and so on. So, continuing the example above, you should be able to do this:
// try hitting a double now
game.hit(150); System.out.println(game.getBases()); // oXX
System.out.println(game.getTeam0Score()); // 3
13. The ball() method is interesting. Normally it just increases the count of balls, going back
to zero in case there is a hit or out.
game = new FuzzballGame(3);
game.ball();
System.out.println(game.getBallCount()); // 1
game.ball();
System.out.println(game.getBallCount()); // 2
game.ball();
System.out.println(game.getBallCount()); // 3
game.strike(true); // out!
System.out.println(game.getBallCount()); // 0, since it’s a new batter
But if the ball count reaches the maximum, the batter gets a walk and an imaginary runner is
placed on first base. But it is not quite like a single, where all the runner advance. On a walk,
runners only advance if they are forced to do so. For example, if the bases are oXo, after a walk
they would be XXo, not XoX, since the runner on second isn’t forced to move. If the bases were
XoX and there was a walk, it would become XXX. Thus, a walk only results in a point for the team
if all the bases were all occupied to start with. Try something like this:
game = new FuzzballGame(3);
game.hit(225); // a triple
System.out.println(game.getBases()); // ooX
game.ball();
game.ball();
game.ball();
game.ball();
System.out.println(game.getBallCount()); // 4
game.ball(); // a walk
System.out.println(game.getBases()); // XoX
A helper method, e.g. shiftRunnersForWalk, could be helpful here.
14. There are a number of places where helper methods could simplify the code. Think about
some of the tasks that occur repeatedly:
• switching to a new batter (resets balls and strikes)
• switching teams (switches top to bottom, or bottom to top plus next inning, and resets
outs)
• updating score for the appropriate team, depending on whether it top or bottom
• shifting runners to next base (as described above, possibly increasing score)
• shifting runners for a walk (as described above, possibly increasing score)
The requirements for the class are embodied in the public API, so it is not mandatory that you
use the ideas above. But they could be very helpful! And, of course, if you end up with a lot of
unnecessarily duplicated code the grader may take off some points for style.
The SpecChecker
You can find the SpecChecker on Canvas. Import and run the SpecChecker just as you practiced
in Lab 1. It will run a number of functional tests and then bring up a dialog offering to create a
zip file to submit. Remember that error messages will appear in the console output. There are
many test cases so there may be an overwhelming number of error messages. Always start
reading the errors at the top and make incremental corrections in the code to fix them. When
you are happy with your results, click “Yes” at the dialog to create the zip file. See the document
“SpecChecker HOWTO”, link on the “syllabus” tab in Canvas, if you are not sure what to do.

More about grading
This is a “regular” assignment so we are going to read your code. Your score will be based partly
(about a two thirds) on the specchecker’s functional tests and partly on the TA’s assessment of
the quality of your code. This means you can get partial credit even if you have errors, and it also
means that even if you pass all the specchecker tests you can still lose points. Are you doing
things in a simple and direct way that makes sense? Are you defining redundant instance
variables? Are you using a conditional statement when you could just be using %? Are you using
a loop for something that can be done with integer division? Some specific criteria that are
important for this assignment are:
• Use instance variables only for the “permanent” state of the object, use local variables for
temporary calculations within methods.
o You will lose points for having unnecessary instance variables
o All instance variables should be private.
• Accessor methods should not modify instance variables.
See the “Style and documentation” section below for additional guidelines.
Restrictions on Java Features For this Assignment
There are no restrictions on the Java features you can use to implement this assignment.
However, see above the above section about using good programming practices. You may not
use any outside libraries (i.e., external libraries such as Apache Commons; otherwise, we won’t
be able to compile your code when grading.
Style and documentation
Roughly 15% of the points will be for documentation and code style. Here are some general
requirements and guidelines:
• Each class, method, constructor and instance variable, whether public or private,
must have a meaningful javadoc comment. The javadoc for the class itself can be very
brief, but must include the @author tag. The javadoc for methods must include @param
and @return tags as appropriate.
o Try to briefly state what each method does in your own words. However, there is
no rule against copying the descriptions from the online documentation. However:
do not literally copy and paste from this pdf! This leads to all kinds of weird bugs
due to the potential for sophisticated document formats like Word and pdf to
contain invisible characters.
o Run the javadoc tool and see what your documentation looks like! (You do not
have to turn in the generated html, but at least it provides some satisfaction 🙂
• All variable names must be meaningful (i.e., named for the value they store).
• Your code should not be producing console output. You may add println statements
when debugging, but you need to remove them before submitting the code.
• Internal (//-style) comments are normally used inside of method bodies to explain how
something works, while the Javadoc comments explain what a method does. (A good rule
of thumb is: if you had to think for a few minutes to figure out how something works,
you should probably include an internal comment explaining how it works.)
o Internal comments always precede the code they describe and are indented to the
same level.
• Use a consistent style for indentation and formatting.
o Note that you can set up Eclipse with the formatting style you prefer and then use CtrlShift-F to format your code. To play with the formatting preferences, go to Window-
>Preferences->Java->Code Style->Formatter and click the New button to create your
own “profile” for formatting.
If you have questions
For questions, please see the Piazza Q&A pages and click on the folder hw2. If you don’t find
your question answered, then create a new post with your question. Try to state the question or
topic clearly in the title of your post, and attach the tag hw2. But remember, do not post any
source code for the classes that are to be turned in. It is fine to post source code for general Java
examples that are not being turned in. (In the Piazza editor, use the button labeled “pre” to have
Java code formatted the way you typed it.)
If you have a question that absolutely cannot be asked without showing part of your source code,
make the post “private” so that only the instructors and TAs can see it. Be sure you have stated a
specific question; vague requests of the form “read all my code and tell me what’s wrong with it”
will generally be ignored.
Of course, the instructors and TAs are always available to help you. See the Office Hours section
of the syllabus to find a time that is convenient for you. We do our best to answer every question
carefully, short of actually writing your code for you, but it would be unfair for the staff to fully
review your assignment in detail before it is turned in.
Any announcements from the instructors on Canvas are considered to be part of the official spec,
and you may lose points if you ignore them. Such posts will always be placed in the
Announcements section of Canvas. (We promise that no official clarifications will be posted
within 24 hours of the due date.)
What to turn in
Note: You will need to complete the “Academic Dishonesty policy questionnaire,” found on
the Assignments page on Canvas, before the submission link will be visible to you.
Please submit, on Canvas, the zip file that is created by the SpecChecker. The file will be named
SUBMIT_THIS_hw2.zip. and it will be located in whatever directory you selected when you ran
the SpecChecker. It should contain one directory, hw2, which in turn contains one file,
FuzzballGame.java. Please LOOK at the file you upload and make sure it is the right one!
Submit the zip file to Canvas using the Assignment 2 submission link and VERIFY that your
submission was successful. If you are not sure how to do this, see the document “Assignment
Submission HOWTO”, linked on the Course Information page on Canvas.
We recommend that you submit the zip file as created by the specchecker. If necessary for some reason, you can
create a zip file yourself. The zip file must contain the directory hw2, which in turn should contain the files
FuzzballGame.java. You can accomplish this by zipping up the src directory of your project. Do not zip up the
entire project. The file must be a zip file, so be sure you are using the Windows or Mac zip utility, and NOT a
third-party installation of WinRAR, 7-zip, or Winzip.

Com S 227 Assignment 3

The purpose of this assignment is to give you practice writing loops, using arrays and lists, and,
most importantly, to get some experience putting together a working application involving
several interacting Java classes.

There are three classes for you to implement: LizardGame, Lizard, and GameFileUtil. As
always, your primary responsibility is to implement these classes according to the specification
and test them carefully. The three classes can be used, along with some other components, to
create an implementation of a game we call Lizards, which is a mix between the classic snake
game1 and a sliding blocks puzzle game.

The game is played on a 2-dimensional grid of “cells”. Each cell may contain a wall, an exit, or
the body segment of a lizard. Cells are located by column and row.
Figure 1
The user presses down the left mouse button and drags lizards to move them around with the
goal of getting all the lizards to the exit. A lizard’s body is multi-segmented and the user can
press and drag any segment. The lizard moves in a snake-like fashion, that is, each segment must
follow in the path of the segments in front or behind of them when the lizard moves forward or
backward respectively. The only exception is when the user clicks and drags the head or tail
1 https://en.wikipedia.org/wiki/Snake_(video_game_genre)
segments, which can move in any direction. There are only four possible directions of
movement: up, down, right, left (never diagonally).

To illustrate the movement, Figure 2 shows four different scenarios: 1) the user selects the head
segment and drags it in some forward direction 2) the user selects the tail segment and drags it in
some backward direction 3) the user selects one of the inner segments and drags it in a forward
direction 4) the user selects an inner segment and drags it in a backward direction. It is also
possible, but not shown, that the user pushes the head segment in a backward direction or the tail
segment in a forward direction.
Figure 2

The lizard may not move off the grid and may not move onto a wall. When it moves onto an exit,
the lizard is removed from the grid. When all of the lizards have been removed, the player wins.
The three classes you implement will provide the “backend” or core logic for the game. In the
interest of having some fun with it, we will provide you with code for a GUI (graphical user
interface), based on the Java Swing libraries.
The sample code includes a documented skeleton for the classes you are to create in the package
hw3. The additional code is in the packages ui and api. The ui package is the code for the GUI.
The api package contains some classes for representing data in the game. There are some
simple tests for you to start with located in the default package.
Figure 3
You may not modify the code in the ui or api packages.
Specification
The complete specification for this assignment includes
• this pdf,
• the online Javadoc, and
• any “official” clarifications posted on Canvas and/or Piazza

Overview of the GameFileUtil class

The GameFileUtil class is a simple utility class with a single static method to load a game file.
public static void load(String filePath, LizardGame game);
Game files are in plain text and have a particular format. There are three main sections to the
file: the dimensions of the grid, a representation of the grid’s cells, and a description of the
lizards. The table below gives an example of these three segments.
8×8 Number of columns
by number of rows,
can be any integers
larger than 0. W WW .
WWW W.
.
WWWWWW .
E.
WWWWW W.
W W.
W W .
A representation of
the grid’s cells,
showing the location
of walls “W” and
exits “E”. Each row
ends with a dot.
L 5,1 6,1 6,2 5,2 4,2 3,2 2,2
L 1,2 0,2 0,3 0,4 1,4 2,4 3,4 4,4 5,4 6,4 6,5 6,6 5,6 4,6 Each line represents
a lizard. The pairs of
numbers represent
the location of
segments, starting
from the tail (left
most pair) of the
lizard and ending
with the head (right
most).

Coordinates are specified as (column, row) pairs. As shown in Figure 1, the columns are
numbered from left to right starting at zero and the rows are numbered from top to bottom
starting at zero. We use column before row consistently throughout this document and the API
because it matches with the convention of specifying coordinates as (x, y), however, it conflicts
with the convention of arrays being rows of columns. How you implement internal data
structures such as arrays does not need to match with the API, all that matters is that you are
consistent in your usage of the data structures.
Finally, note that load does not return anything. It is passed a LizardGame object and it is
expected that the method calls mutator methods on the object to update the state of the game.

Overview of the Lizard class

The Lizard class models a lizard as a collection of body segments (see the class
api.BodySegment). The class contains several accessor and mutator method that can be used by
other parts of the program, for example LizardGame. The segments are provided to the object
with a call to setSegments(ArrayList<BodySegment> segments), where the segments are
expected to be ordered from tail to head. In other words, you can assume the first element of the
list is always the tail.

Overview of the LizardGame class

The LizardGame class models the game and its methods are called by classes in the ui package
to create a complete game. For example, the UI calls move() every time the user presses and
drags the mouse over the graphical representation of the gird.
Also, LizardGame is responsible for keeping track of the grid of cells. Each cell is represented as
a Cell object. The grid is specified by (column, row), as shown in Figure 1 and described in
GameFileUtil above, however you can store the cells any way you want as long as the public
methods produce the correct results.

The GUI
There is also a graphical UI in the ui package. The GUI is built on the Java Swing libraries.
This code is complex and specialized, and is somewhat outside the scope of the course. You are
not expected to be able to read and understand it. However, you might be interested in exploring
how it works at some point. In particular, it is sometimes helpful to look at how the UI is calling
the methods of the classes you are writing.

The main method is in ui.GameMain. You can try running it, and you’ll see the initial window,
but until you start implementing the required classes you’ll just get errors. All that the main class
does is to initialize the components and start up the UI machinery. The classes GamePanel and
GridViz contain most of the UI code.

Importing the sample code
The sample code includes a complete skeleton of the three classes you are writing. It is
distributed as a complete Eclipse project that you can import. It should compile without errors
out of the box.
1. Download the zip file. You don’t need to unzip it.
2. In Eclipse, go to File -> Import -> General -> Existing Projects into Workspace, click
Next.
3. Click the radio button for “Select archive file”.
4. Browse to the zip file you downloaded and click Finish.
If you have an older version of Java or if for some reason you have problems with this process,
or if the project does not build correctly, you can construct the project manually as follows:
1. Extract the zip file containing the sample code (Note: on Windows, you have to right click
and select “Extract All” – it will not work to just double-click it)
2. In Windows Explorer or Finder, browse to the src directory of the zip file contents
3. Create a new empty project in Eclipse
4. In the Eclipse Package Explorer, navigate to the src folder of the new project.
5. Drag the hw3, ui, and api folders from Explorer/Finder into the src folder in Eclipse.
6. Copy the remaining top-level files (SimpleTest.java, etc) into the src folder.
Testing and the SpecChecker
As always, you should try to work incrementally and write tests for your code as you develop it.
Do not rely on the UI code for testing! Trying to test your code using a UI is very slow,
unreliable, and generally frustrating. The code for the UI itself is more complex than the code
you are implementing, and it is not guaranteed to be free of bugs. In particular, when we
grade your work we are NOT going to run the UI, we are going to test that each method
works according to its specification.

We will provide a SpecChecker, it will contain many tests to help you get started, but do not
expect that it will test for every possible mistake you might make. At this point in the course,
you are expected to be able to read the specifications, ask questions when things require
clarification, and write your own tests. The SpecChecker we use for grading may have more tests
added.
You can find the SpecChecker on Canvas. Import and run the SpecChecker just as you practiced
in Lab 1. It will run a number of functional tests and then bring up a dialog offering to create a
zip file to submit. Remember that error messages will appear in the console output. There are
many test cases so there may be an overwhelming number of error messages. Always start
reading the errors at the top and make incremental corrections in the code to fix them. When
you are happy with your results, click “Yes” at the dialog to create the zip file. See the document
“SpecChecker HOWTO”, if you are not sure what to do.

Getting started

At this point we expect that you know how to study the documentation for a class, write test
cases, and develop your code incrementally to meet the specification, so this getting started
section will not be quite as detailed as for the previous assignments.
You can find the example test cases below in the default package of the sample code. Don’t try
to copy/paste from the pdf.

Please remember that these are just examples to get you started and you will need to write
many, many more tests to be sure your code is working correctly. (You can expect that the
functional tests we run when grading your work will have something like 100 test cases, for
example.)

Don’t rely on the GUI for testing your code. Doing so is difficult and frustrating because
the GUI itself is so complex. Rely on simple, focused test cases that you can easily run in
the debugger.
A good starting point is the Lizard class. A lizard is modeled as a collection of body segments
(see the class api.BodySegment). A lizard can be constructed for test like this.
Lizard liz = new Lizard();
Cell cell0 = new Cell(1, 1);
Cell cell1 = new Cell(2, 1);
Cell cell2 = new Cell(2, 2);
ArrayList<BodySegment> segments = new ArrayList<BodySegment>();
segments.add(new BodySegment(liz, cell0));
segments.add(new BodySegment(liz, cell1));
segments.add(new BodySegment(liz, cell2));
There are several methods to implement in Lizard. Right now, these methods may not seem to
be that important. But when you implement LizardGame, you may find many uses for these
methods, so take note of what they do. Here are some simple tests for the methods in Lizard.
liz.setSegments(segments);
System.out.println(“The lizard has ” + liz.getSegments().size() + ”
segments, expected 3.”);
BodySegment headSegment = liz.getHeadSegment();
Cell headCell = headSegment.getCell();
System.out.println(“The head segment is at ” + headCell + “, expected
(2,2,Ground,Lizard).”);
BodySegment tailSegment = liz.getTailSegment();
Cell tailCell = tailSegment.getCell();
System.out.println(“The tail segment is at ” + tailCell + “, expected
(1,1,Ground,Lizard).”);
BodySegment middleSegment = liz.getSegmentAt(cell1);
Cell middleCell = middleSegment.getCell();
System.out.println(“The middle segment is at ” + middleCell + “,
expected (2,1,Ground,Lizard).”);
BodySegment aheadSegment = liz.getSegmentAhead(middleSegment);
Cell aheadCell = aheadSegment.getCell();
System.out.println(“The segment ahead of the middel is at ” + aheadCell
+ “, expected (2,2,Ground,Lizard).”);
BodySegment behindSegment = liz.getSegmentBehind(middleSegment);
Cell behindCell = behindSegment.getCell();
System.out.println(“The segment behind the middel is at ” + behindCell
+ “, expected (1,1,Ground,Lizard).”);
Direction aheadDir = liz.getDirectionToSegmentAhead(middleSegment);
System.out.println(“From the middle segment, ahead is ” + aheadDir + “,
expected DOWN.”);
Direction behindDir = liz.getDirectionToSegmentBehind(middleSegment);
System.out.println(“From the middle segment, behind is ” + behindDir +
“, expected LEFT.”);
Direction headDir = liz.getHeadDirection();
System.out.println(“The head is pointing ” + headDir + “, expected
DOWN.”);
Direction tailDir = liz.getTailDirection();
System.out.println(“The tail is pointing ” + tailDir + “, expected
LEFT.”);
The class GameFileUtil is used to load saved game files. You are provided with a couple of
sample files in the examples directory.
// Example tests for GameFileUtil class
// (requires some implementation of LizardGame)
LizardGame game = new LizardGame(0, 0);
GameConsole gc = new GameConsole();
game.setListeners(gc, gc);
System.out.println();
GameFileUtil.load(“examples/game1.txt”, game);
System.out.println(“Expected a message saying the number of lizards is
now 1.”);
System.out.println(“DO NOT print this message in GameFileUtil, the
ScoreListener needs to be called in LizardGame.”);
System.out.println();
System.out.println(“The grid with is ” + game.getWidth() + “, expected
8.”);
System.out.println(“The grid height is ” + game.getHeight() + “,
expected 4.”);
System.out.println(“The cell at (0,0) is empty (” + game.getCell(0,
0).isEmpty() + “), expected true.”);
System.out.println(“The cell at (1,1) has a wall (” + (game.getCell(1,
1).getWall() != null) + “), expected true.”);
System.out.println(“The cell at (7,2) has an exit (” + (game.getCell(7,
2).getExit() != null) + “), expected true.”);
System.out.println(“The cell at (2,2) has a lizard (” +
(game.getCell(2, 2).getLizard() != null) + “), expected true.”);
The LizardGame class models the game and its methods are typically called by the UI. Write
simple tests to take place of the UI. The main interaction with the user happens when the user
selects and drags the body segment of a lizard. These mouse events result in calls to the method
move().

Without a doubt, move() is the most complex of the methods you need to implement. Read the
javadocs, review Figures 1 and 2 of this document, review the many methods available to help
with the logic in Lizard and LizardGame and finally, break the problem into smaller parts and
possibly create helper methods of you own. Many of the other methods in LizardGame are
designed to help move() do its job, but you will also probably want to implement your own
helper methods, which is allowed as long as they are private. Here are some simple tests for
LizardGame.
// Example tests for LizardGame
// (assuming previous tests worked and the game is loaded)
segments = new ArrayList<BodySegment>();
segments.add(new BodySegment(liz, game.getCell(1, 0)));
segments.add(new BodySegment(liz, game.getCell(2, 0)));
segments.add(new BodySegment(liz, game.getCell(3, 0)));
liz = new Lizard();
liz.setSegments(segments);
System.out.println();
game.addLizard(liz);
System.out.println(“Expected a message saying the number of lizards is
now 2.”);
System.out.println();
game.removeLizard(liz);
System.out.println(“Expected a message saying the number of lizards is
now 1.”);
System.out.println();
liz = game.getLizards().get(0);
Cell adjCell = game.getAdjacentCell(1, 1, RIGHT);
System.out.println(“Right of cell (1,1) is ” + adjCell + “, expected
cell (2,1,Ground,Empty)”);
System.out.println(“Cell (5,2) is available (” + game.getCell(5, 2) +
“), expected true.”);
System.out.println(“Moving head of lizard one RIGHT.”);
game.move(4, 2, RIGHT);
System.out.println(“Cell (5,2) is available (” + game.isAvailable(5, 2)
+ “), expected false.”);
System.out.println(“The head of the lizard is in cell (5,2) (”
+ (liz.getHeadSegment().getCell() == game.getCell(5, 2)) + “),
expected true.”);
More about grading
This is a “regular” assignment so we are going to read your code. Your score will be based partly
(about a two thirds) on the specchecker’s functional tests and partly on the TA’s assessment of
the quality of your code. This means you can get partial credit even if you have errors, and it also
means that even if you pass all the specchecker tests you can still lose points. Are you doing
things in a simple and direct way that makes sense? Are you defining redundant instance
variables? Are you using a conditional statement when you could just be using %? Are you using
a loop for something that can be done with integer division?
Additionally, you should not take this to mean that your only job is it pass the specchecker’s test
by any means possible, such as hard-coding return values. The version of the specchecker we use
for grading may be modified to use different inputs and test the methods in different ways than
the speccecker you are given for testing. Bottom line, you job is to correctly implement
algorithms that meet the specifications.
Some specific criteria that are important for this assignment are:
• Use instance variables only for the “permanent” state of the object, use local variables for
temporary calculations within methods.
o You will lose points for having unnecessary instance variables
o All instance variables should be private.
• Accessor methods should not modify instance variables.
See the “Style and documentation” section below for additional guidelines.
Restrictions on Java Features For this Assignment
There are no restrictions on the Java features you can use to implement this assignment.
However, see above the above section about using good programming practices. You may not
use any outside libraries (i.e., external libraries such as Apache Commons; otherwise, we won’t
be able to compile your code when grading.
Style and documentation
Roughly 10% of the points will be for documentation and code style. The general guidelines are
the same as in homework 2. However, since the skeleton code has the public methods fully
documented, there is not quite as much to do. Remember the following:
• You must add an @author tag with your name to the javadoc at the top of each of the
classes you write (in this case the classes in the hw3 package).
• You must javadoc each instance variable and helper method that you add. Anything you
add must be private.
• Since the code includes some potentially tricky loops to write, you ARE expected to add
internal (//-style) comments, where appropriate, to explain what you are doing inside
the longer methods. A good rule of thumb is: if you had to think for a few minutes to
figure out how to do something, you should probably include a comment explaining how
it works. Internal comments always precede the code they describe and are indented to
the same level.
• Keep your formatting clean and consistent.
• Avoid redundant instance variables
• Accessor methods should not modify instance variables
If you have questions
For questions, please see the Piazza Q & A pages and click on the folder hw3. If you don’t find
your question answered, then create a new post with your question. Try to state the question or
topic clearly in the title of your post, and attach the tag hw3. But remember, do not post any
source code for the classes that are to be turned in. It is fine to post source code for general Java
examples that are not being turned in, and for this assignment you are welcome to post and
discuss test code. (In the Piazza editor, use the button labeled “code” to have the editor keep
your code formatting. You can also use “pre” for short code snippets.)
If you have a question that absolutely cannot be asked without showing part of your source code,
change the visibility of the post to “private” so that only the instructors and TAs can see it. Be
sure you have stated a specific question; vague requests of the form “read all my code and tell
me what’s wrong with it” will generally be ignored.
Of course, the instructors and TAs are always available to help you. See the Office Hours section
of the syllabus to find a time that is convenient for you. We do our best to answer every question
carefully, short of actually writing your code for you, but it would be unfair for the staff to fully
review your assignment in detail before it is turned in.
Any announcements labeled “Official Clarification” are considered to be part of the spec, and
you may lose points if you ignore them. Such posts will always be placed in the Announcements
section of the course page in addition to the Q&A page. (We promise that no official
clarifications will be posted within 24 hours of the due date.)

What to turn in

Note: You will need to complete the “Academic Dishonesty policy questionnaire,” found on
the Assignments page on Canvas, before the submission link will be visible to you.
Please submit, on Canvas, the zip file that is created by the SpecChecker. The file will be named
SUBMIT_THIS_hw3.zip. and it will be located in whatever directory you selected when you ran
the SpecChecker. It should contain one directory, hw3, which in turn contains four files,
LizardGame.java, GameFileUtil.java, and Lizard.java. Please LOOK at the file you
upload and make sure it is the right one!
Submit the zip file to Canvas using the Assignment 3 submission link and VERIFY that your
submission was successful.
We recommend that you submit the zip file as created by the specchecker. If necessary for some reason,
you can create a zip file yourself. The zip file must contain the directory hw3, which in turn should contain
the three required files. You can accomplish this by zipping up the src directory of your project. Do not zip
up the entire project. The file must be a zip file, so be sure you are using the Windows or Mac zip utility,
and NOT a third-party installation of WinRAR, 7-zip, or Winzip.

Com S 227 Assignment 4

The purpose of this assignment is to give you some experience:
• using interfaces and abstract classes
• reusing code through inheritance (“is-a”) relationship
• reusing code through association (“has-a”) relationship

A portion of your grade on this assignment (roughly 15% to 20%) will be determined by your
logical organization of classes in a class hierarchy and by how effectively you have been able
to use inheritance and composition to minimize duplicated code. Be sure you have done and
understood Lab 8 checkpoint 2!

In this project you will complete the implementation of a hierarchy of classes representing
various types of elements in a video game. Your task is to implement these eight concrete
classes:
SimpleElement
AttachedElement
FlyingElement
FollowerElement
LiftElement
MovingElement
PlatformElement
VanishingElement

All eight of these classes must directly or indirectly extend the given abstract class
api.AbstractElement. In implementing them, you may put them into a class hierarchy that
contains one or more additional abstract classes you create on your own to a) avoid duplicating
common code between the eight types, and b) avoid having redundant code or attributes in any
type.

All your code (the 8 required classes, and any extra classes you create) goes in the hw4 package.

Using inheritance

Part of your grade for this assignment (e.g. 15-20%) will be based on how effectively you are
able to implement the eight required concrete types with a minimum of code duplication. Here
are some specific restrictions; see page 13 for more details.
• You may not use public, protected or package-private variables. (You can provide
protected accessor methods or constructors when needed.)
• You may not modify the AbstractElement class itself (or anything else in the api
package).

Overview

A 2D video game may include elements such as players, enemies, projectiles, PlatformElements,
walls, and so on, each with slightly different behavior, but with many attributes in common as
well. For example, at any given time, a game element has a position (x, y) within a window,
where x and y are floating point values, (0, 0) is the upper left corner of the window, and the
positive y- direction is downwards. It also has a width and height, forming a bounding rectangle.
This rectangle is used for actually drawing the graphics on the screen, and also for detecting
collisions between elements.

The capabilities needed for doing the actual drawing are represented by the simple interface
api.Drawable, with these six methods:
void draw(Graphics g) – draws this object using the given graphics context
int getXInt() – returns the x-coordinate, rounded to the nearest integer
int getYInt() – returns the y-coordinate, rounded to the nearest integer|
int getWidth() – returns the width
int getHeight() – returns the height
Rectangle getRect() – returns the bounding rectangle (an instance of java.awt.Rectangle)
(These capabilities are isolated in this interface so that the graphical portion of applications need
not be concerned with any of the details of our specific type hierarchy for game elements.)

Your starting point will be the abstract class api.AbstractElement, which is declared to
implement the Drawable interface but leaves five of its methods abstract, and also declares
seven additional abstract methods. The important point is that the AbstractElement class
provides the implementation of the draw method, so that in your own code you do not ever need
to be concerned with the graphical aspects of the application. To allow for customizing the way
that a given game element is rendered on the screen, we define an interface api.Renderer, and a
AbstractElement always has an attribute of type Renderer.

The api package includes various
examples of renderers that are used in the demo applications, such as the BasicRenderer that
fills in an element’s bounding rectangle with a solid color, or the ImageRenderer that displays
an image in the bounding rectangle. Again, you will not need to be concerned with the graphical
aspects of the implementation, except to the extent that you want to experiment with the demo
applications and try things out.

The general design of the game framework is based on a timer that periodically triggers a
callback method, say, 25 times per second (the so-called frame rate). You would, in practice,
implement a game by setting up the game elements and then customizing the callback method to
update element positions, handle collisions, generate new enemies, keep score, etc.

The most
fundamental operation in the callback is to invoke the update() method on each element. In the
simplest case of something like SimpleElement that never actually moves or changes, the
update method does nothing except increment a counter. In a (slightly) more interesting
element type such as MovingElement, the update method might also change the element’s
position by adding a “velocity” (deltaX, deltaY) to the x and y coordinates of the position.

Here is a brief overview of the eight concrete types, in alphabetical order. Each one must directly
or indirectly extend AbstractElement. For detailed method specifications, see the Javadoc.
SimpleElement: Simplest concrete subclass of the AbstractElement type. The update method
just increments a frame counter.

AttachedElement: An element that is always associated to another “base” element such as a
PlatformElement or LiftElement. It only moves with the associated base object, remaining a
fixed distance above it. In addition to the methods specified in Drawable and AbstractElement, it
has a method setBase.

FlyingElement: An element whose position is updated each frame according to its vertical
velocity. Additionally, to simulate gravity, the vertical velocity is adjusted each frame by a
gravitational constant. In addition to the methods specified in Drawable and AbstractElement, it
has the methods setVelocity, setGravity, setGrounded, getDeltaX, and getDeltaY.

FollowerElement: An element that is always associated to another “base” element such as a
PlatformElement or LiftElement. Optionally, it can be configured with a nonzero horizontal
velocity and it will oscillate back and forth between the left and right edges of the base element it
is associated to, while remaining directly above it. In addition to the methods specified in
Drawable and AbstractElement, it has methods setVelocity, getDeltaX, getDeltaY,
setBounds, getMax, getMin, and setBase.

LiftElement: An element with two distinctive behaviors: First, it can be configured to move
vertically within a fixed set of boundaries. On reaching a boundary, the y-component of its
velocity is reversed. Second, it maintains a list of elements that are associated with it (see
AttachedElement and FollowerElement) whose basic motion all occurs relative to the
LiftElement. Invoking update on a LiftElement updates the LiftElement’s position, adjusts the
velocity as necessary, and then invokes update on each associated element. In addition to the
methods specified in Drawable and AbstractElement, it has the methods setVelocity,
getDeltaX, getDeltaY, setBounds, getMax, getMin, addAssociated,
deleteMarkedAssociated, and getAssociate.

MovingElement: An element in which the update method adjusts the position each frame with a
velocity vector (deltaX, deltaY). The units of velocity are “pixels per frame”. In addition to the
methods specified in Drawable and AbstractElement, it has the methods setVelocity,
getDeltaX, and getDeltaY.

PlatformElement: An element with two distinctive behaviors: First, it can be configured to
move horizontally within a fixed set of boundaries. On reaching a boundary, the x-component of
its velocity is reversed. Second, it maintains a list of elements that are associated with it (see
AttachedElement and FollowerElement) whose basic motion all occurs relative to the
PlatformElement. Invoking update on a PlatformElement updates the PlatformElement’s
position, adjusts the velocity as necessary, and then invokes update on each of its associated
elements. In addition to the methods specified in Drawable and AbstractElement, it has the
methods setVelocity, getDeltaX, getDeltaY, setBounds, getMax, getMin,
addAssociated, deleteMarkedAssociated, and getAssociated.

VanishingElement: An element that does not move, but it has an internal counter that is
decremented each frame. When the counter reaches zero, the element marks itself for deletion.

Note that the Javadoc was generated under the simple assumption that each concrete
class was a direct extension of AbstractElement, i.e., that no inheritance was being
used within these eight classes. So when you see in the Javadoc the line “extends
api.AbstractElement”, please do not take that literally as part of the spec! In a wellwritten implementation of the hierarchy, it is extremely unlikely, for example, that the
FlyingElement class would directly extend AbstractElement.

The Demo applications
There are some sample graphical applications to try out in the demo package. These are highly
experimental and almost certainly have bugs. As always, these are just for fun, do not rely on the
GUI to accurately test your code!
• PigsExample – requires only that you have implemented SimpleElement
• MazeExample – requires SimpleElement and MovingElement, use arrow keys to move
• JumpExample1 – requires SimpleElement and FlyingElement, use arrow keys, and ‘a’ key
to jump
• VanishingElementExample – requires VanishingElement
• WhenPigsFly – requires SimpleElement, MovingElement, FlyingElement, and
• PlatformExample – requires PlatformElement, LiftElement, AttachedElement, and
FollowerElement
• JumpExample2 – requires PlatformElement, LiftElement, AttachedElement,
• FollowerElement, and FlyingElement, use arrow keys and ‘a’ key to jump
• SuperPigsExample – requires everything! use arrow keys, and ‘a’ key to jump

Testing and the SpecChecker

As always, you should try to work incrementally and write tests for your code as you develop it.
Do not rely on the UI demo code for testing! Trying to test your code using a UI is very slow,
unreliable, and generally frustrating. The UI code is complex and not guaranteed to be free of
bugs. In particular, when we grade your work we are NOT going to run any of the demo
programs, we are going to test that each method works according to its specification.

We will provide a basic SpecChecker, but it will not perform any functional tests of your
code. At this point in the course, you are expected to be able to read the specifications, ask
questions when things require clarification, and write your own unit tests.

Since the test code is not a required part of this assignment and does not need to be turned in,
you are welcome to post your test code on Piazza for others to check, use and discuss.
The SpecChecker will verify the class names and packages, the public method names and return
types, and the types of the parameters. If your class structure conforms to the spec, you should
see a message similar to this in the console output:
x out of x tests pass.

This SpecChecker will also offer to create a zip file for you that will package up everything in
your hw4 package. Please check this carefully. In this assignment you may be including one
or more abstract classes of your own, in addition to the 8 required classes, so make sure
they have been included in the zip file.

Importing the sample code
The sample code is distributed as a complete Eclipse project that you can import. However, the
packages sample_tests and demo are posted separately, to keep you from getting a ton of
compile errors at first. The hw4 package includes a basic skeleton for each required class,
including only the class and constructor declarations.

1. Download the zip file sample_code.zip. You don’t need to unzip it.
2. In Eclipse, go to File -> Import -> General -> Existing Projects into Workspace, click Next.
3. Click the radio button for “Select archive file”.
4. Browse to the zip file you downloaded and click Finish.
5. When you want to try something from sample_tests or demo, create the package in your
project, download the respective zip file, extract it, and drag the file(s) you want into the
appropriate package. If you have an older version of Java or if for some reason you have
problems with the process above, or if the project does not build correctly, you can construct
the project manually as follows:

6. Extract the zip file containing the sample code (Note: on Windows, you have to right click
and select “Extract All” – it will not work to just double-click it)
7. In Windows Explorer or Finder, browse to the src directory of the zip file contents
8. Create a new empty project in Eclipse
9. In the Eclipse Package Explorer, navigate to the src folder of the new project.
10. Drag the hw4 and api folders from Explorer/Finder into the src folder in Eclipse.
Getting started
At this point we expect that you know how to study the documentation for a class, write test
cases, and develop your code incrementally to meet the specification, so this getting started
section will not be quite as detailed as for the previous assignments. You’ll find that the code is
not terribly difficult – other than the inheritance aspects, most of these classes could have been
given as a pretty easy homework 2.

Step 1: Most importantly – be sure you have done and understood the second checkpoint of
lab 8. Sometimes the best way to start on an inheritance hierarchy is to, initially, forget about
inheritance. That is, if you have two classes A and B that might be related, just implement both
of them completely from scratch. Then look at what they have in common. Does it make logical
sense for one to extend the other? Should the common code be factored into a common, abstract
superclass?

2. It looks like SimpleElement is just a direct implementation of all the abstract methods
specified in AbstractElement, so that would seem a likely place to start. As always begin by
writing a simple test case so you know what you are expecting to happen, for example (see
BasicTest.java in the sample_tests package):
SimpleElement e = new SimpleElement(2.3, 4.5, 10, 20);
System.out.println(e.getXReal()); // expected 2.3
System.out.println(e.getXInt()); // expected 2
System.out.println(e.getYReal()); // expected 4.5
System.out.println(e.getYInt()); // expected 5
System.out.println(e.getWidth()); // expected 10
System.out.println(e.getHeight());// expected 20
System.out.println(e.getRect());
// expected java.awt.Rectangle[x=2,y=5,width=10,height=20]
System.out.println(e.isMarked()); // expected false
Then try out some mutator methods too…
// setting position
e.setPosition(42, 137);
System.out.println(e.getXReal()); // expected 42
System.out.println(e.getYReal()); // expected 137
// update should increment the frame count
e.update();
e.update();
System.out.println(e.getFrameCount()); // expected 2
// mark
e.markForDeletion();
System.out.println(e.isMarked()); // expected true
// intersections
e = new SimpleElement(10, 0, 10, 10);
SimpleElement e2 = new SimpleElement(1, 5, 10, 10);
System.out.println(e.collides(e2)); // expected true e2.setPosition(0, 5);
System.out.println(e.collides(e2)); // expected false
(Tip: the java.awt.Rectangle class includes a method intersects that might be useful!)
3. You might next try MovingElement, FlyingElement, and VanishingElement, which appear
to be fairly similar to
SimpleElement. Write some simple tests as above for all the methods. For example, how does
gravity work? (See FlyingElementTest.java in the sample_tests package.)
FlyingElement p = new FlyingElement(0, 0, 0, 0);
p.setGrounded(false);
p.setVelocity(2, 3);
p.update();
System.out.println(p.getYReal()); // expected 3
System.out.println(p.getDeltaY());// expected 3
p.update();
System.out.println(p.getYReal()); // expected 6
System.out.println(p.getDeltaY());// expected 3
p.setGravity(5);
p.update();
System.out.println(p.getYReal()); // 6 + 3 = 9
System.out.println(p.getDeltaY()); // 3 + 5 = 8
p.setGrounded(true);
p.update();
System.out.println(p.getYReal()); // 9 + 8 = 17
System.out.println(p.getDeltaY()); // 8 (grounded)
p.update();
System.out.println(p.getYReal()); // 17 + 8 = 25
System.out.println(p.getDeltaY()); // 8 (grounded)
4. Maybe the next thing to tackle is PlatformElement. Sketch out a couple of examples by hand
to be sure you can see how to update the position and velocity when reaching the min or max
position. Try creating some test cases, for example (see PlatformElementTest.java):
// left side at x = 50, width 10, right side at 60
PlatformElement p = new PlatformElement(50, 200, 10, 10);
p.setBounds(40, 70);
p.setVelocity(6, 0);
p.update();
System.out.println(p.getXReal() + “, ” + (p.getXReal() + 10)); // [56, 66]
System.out.println(“Velocity ” + p.getDeltaX()); // 6.0
p.update();
System.out.println(p.getXReal() + “, ” + (p.getXReal() + 10)); // [60, 70]
System.out.println(“Velocity ” + p.getDeltaX()); // -6.0
p.update();
System.out.println(p.getXReal() + “, ” + (p.getXReal() + 10)); // [54, 64]
System.out.println(“Velocity ” + p.getDeltaX()); // -6.0
p.update();
System.out.println(p.getXReal() + “, ” + (p.getXReal() + 10)); // [48, 58]
System.out.println(“Velocity ” + p.getDeltaX()); // -6.0
p.update();
System.out.println(p.getXReal() + “, ” + (p.getXReal() + 10)); // [42, 52]
System.out.println(“Velocity ” + p.getDeltaX()); // -6.0
p.update();
System.out.println(p.getXReal() + “, ” + (p.getXReal() + 10)); // [40, 50]
System.out.println(“Velocity ” + p.getDeltaX()); // 6.0
5. You can’t complete the implementation of PlatformElement without checking its behavior
with associated elements. It looks like AttachedElement is quite a bit simpler than
FollowerElement, so we could start with that. See PlatformWithAttachedTest.java.
// left side at x = 50, width 10, right side at 60
PlatformElement p = new PlatformElement(50, 200, 10, 10);
p.setBounds(40, 70);
p.setVelocity(6, 0);
// size 5 x 5, offset 2 units from left of PlatformElement, 15 above
AttachedElement c = new AttachedElement(5, 5, 2, 15);
// this should automatically make p the base of c
p.addAssociated(c);
// x position should be the base position + 2 = 52
// y position should be base y – AttachedElement height – hover = 180
System.out.println(c.getXReal()); // expected 52
System.out.println(c.getYReal()); // expected 180
p.update();
System.out.println(c.getXReal()); // expected 58
System.out.println(c.getYReal()); // expected 180
p.update();
System.out.println(c.getXReal()); // expected 62
System.out.println(c.getYReal()); // expected 180
// calling update on p should update associated elements too
System.out.println(c.getFrameCount()); // expected 2
6. Time to think about FollowerElement, maybe? It has the same oscillating behavior as a
PlatformElement, but all motion is relative to the PlatformElement it’s on. First think about what
it should do when the PlatformElement isn’t moving, that should be the easiest case. See
PlatformWithFollowerTest.java.
// first try an example where the base doesn’t move
// left side at x = 50, width 10, right side at 60
PlatformElement p = new PlatformElement(50, 200, 10, 10);
p.setBounds(40, 70);
// size 5 x 5, initial offset 2 units from left of PlatformElement
FollowerElement e = new FollowerElement(5, 5, 2);
e.setVelocity(2, 0);
// this should automatically make p the base of e
// and the left and right sides of p the boundaries of e
p.addAssociated(e);
System.out.println(e.getMin()); // 50
System.out.println(e.getMax()); // 60
// x position should be the base position + 2 = 52
// y position should be base y – FollowerElement height = 195
System.out.println(e.getXReal()); // expected 52
System.out.println(e.getYReal()); // expected 195
// PlatformElement doesn’t move here, but FollowerElement does
p.update();
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5));//expected 54,59
System.out.println(e.getDeltaX()); // expected 2.0
p.update();
// this should hit the right boundary
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5));//expected 55,60
System.out.println(e.getDeltaX()); // expected -2.0
System.out.println();
7. How about if PlatformElement is moving, but the FollowerElement isn’t?
// next, what if PlatformElement is moving, but FollowerElement velocity 0?
// left side at x = 50, width 10, right side at 60
p = new PlatformElement(50, 200, 10, 10);
p.setBounds(40, 70);
p.setVelocity(3, 0);
// size 5 x 5, initial offset 2 units from left of PlatformElement
e = new FollowerElement(5, 5, 2);
p.addAssociated(e);
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5));//expected 52,57
// when p moves, the boundaries of e should shift
p.update();
System.out.println(“bounds ” + e.getMin() + “, ” + e.getMax());// 53, 63
// but e is still 2 units from left side
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5));//expected 55,60
System.out.println();
8. The trickiest bit is when both the PlatformElement and FollowerElement are both moving. For
example:
// next, what if PlatformElement is moving, and FollowerElement velocity is
nonzero?
// left side at x = 50, width 10, right side at 60
p = new PlatformElement(50, 200, 10, 10);
p.setBounds(40, 70);
p.setVelocity(3, 0);
// size 5 x 5, initial offset 2 units from left of PlatformElement
e = new FollowerElement(5, 5, 2);
e.setVelocity(2, 0);
p.addAssociate(e);
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5));//expected 52,57
p.update();
// e is now 4 units from left bound, since its velocity is 2
System.out.println(“bounds ” + e.getMin() + “, ” + e.getMax());// 53, 63
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5)); // 57, 62
p.update();
// p has moved to [56, 66], e attempts to move another 2 units
// relative to p, to [62, 67], but hits the right boundary at 66
// and reverses direction
System.out.println(“bounds ” + e.getMin() + “, ” + e.getMax());// 56, 66
System.out.println(e.getXReal() + “, ” + (e.getXReal() + 5)); // 61, 66
System.out.println(“velocity ” + e.getDeltaX()); // expected -2
You should be able to further develop the test cases above (for example, does your code work
when the FollowerElement hits the left boundary?)
9. Try working on similar tests for LiftElements with AttachedElements and
FollowerElements.
Requirements and guidelines regarding inheritance
A generous portion of your grade (maybe 20%) will be based on how well you have used
inheritance, and possibly abstract classes, to create a clean design with a minimum of duplicated
code. Please note that there is no one, absolute, correct answer – you have design choices to
make.
You will explain your design choices in the class Javadoc for BaseElement.

Specific requirements

You are not allowed to use non-private variables. Call the superclass constructor to initialize
its attributes, and use superclass accessor methods to access them. If your subclass needs some
kind of access that isn’t provided by public methods, you are allowed to define your own
protected methods or constructors.

Other general guidelines
You should not use instanceof or getClass() in your code, or do any other type of runtime
type-checking, to implement correct behavior. Rely on polymorphism.
• No class should contain extra attributes or methods it doesn’t need to satisfy its own
specification.
• Do not ever write a method like this (it is redundant):
public void foo()
{
super.foo()
}
There is almost never any reason to declare and implement a method that is already
implemented in the superclass unless you need to override it to change its behavior. That
is the whole point of inheritance!

Style and documentation
Special documentation requirement: you must add a comment to the top of the
SimpleElement class with a couple of sentences explaining how you decided to organize the
class hierarchy for the elements.
Roughly 10 to 15% of the points will be for documentation and code style. Some restrictions
and guidelines for using inheritance are described above.
When you are overriding a superclass or interface method, it is usually NOT necessary to rewrite the Javadoc, unless you are really, really changing its behavior. Just include the
@Override annotation. (The Javadoc tool automatically copies the superclass Javadoc where
needed.)
The other general guidelines are the same as in homework 3. Remember the following:
• You must add an @author tag with your name to the javadoc at the top of each of the
classes you write.
• You must javadoc each instance variable and helper method that you add. Anything you
add must be private or protected.
• Keep your formatting clean and consistent.
• Avoid redundant instance variables
• Accessor methods should not modify instance variables
If you have questions
It is extremely likely that the specification will not be 100% clear to you. Part of your job as a
developer is to determine what still needs to be clarified and to formulate appropriate questions.
In particular, since you are not required to turn in any test code for this assignment, your tests
and test cases can be freely shared and discussed on Piazza. It is your responsibility to make
sure that you correctly understand the specification and get clarifications when needed.

For questions, please see the Piazza Q & A pages and click on the folder hw4. If you don’t find
your question answered already, then create a new post with your question. Try to state the
question or topic clearly in the title of your post, and attach the tag hw4. But remember, do not
post any source code for the classes that are to be turned in. It is fine to post source code for
general Java examples that are not being turned in. (In the Piazza editor, use the buttons labeled
“code” or “tt” to have Java code formatted the way you typed it.)
If you have a question that absolutely cannot be asked without showing part of your source code,
make the post “private” so that only the instructors and TAs can see it. Be sure you have stated a
specific question; vague requests of the form “read all my code and tell me what’s wrong with it”
will generally be ignored.

Of course, the instructors and TAs are always available to help you. See the Office Hours
section of the syllabus to find a time that is convenient for you. We do our best to answer every
question carefully, short of actually writing your code for you, but it would be unfair for the staff
to fully review your assignment in detail before it is turned in.
Any posts from the instructors on Piazza that are labeled “Official Clarification” are
considered to be part of the spec, and you may lose points if you ignore them. Such posts
will always be placed in the Announcements section of the course page in addition to the Q&A
page. (We promise that no official clarifications will be posted within 24 hours of the due date.)
Acknowledgement
This project was inspired by the quirky and wonderful book, Program Arcade Games With Python and
Pygame, http://programarcadegames.com/ , written by Paul Craven, who teaches at Simpson College in
Indianola.

What to turn in

Note: You will need to complete the “Academic Dishonesty policy questionnaire,” found on
the Assignments page on Canvas, before the submission link will be visible to you.
Please submit, on Canvas, the zip file that is created by the SpecChecker. The file will be named
SUBMIT_THIS_hw4.zip and it will be located in whatever directory you selected when you ran
the SpecChecker. It should contain one directory, hw4, which in turn contains the eight required
classes along with any others you defined in the hw4 package. Please LOOK at the file you
upload and make sure it is the right one and contains everything needed!
Submit the zip file to Canvas using the Assignment 4 submission link and verify that your
submission was successful.

We recommend that you submit the zip file as created by the specchecker. If necessary for some reason, you can
create a zip file yourself. The zip file must contain the directory hw4, which in turn should contain everything in
your hw4 directory. You can accomplish this by zipping up the hw4 directory of your project. Do not zip up the
entire project. The file must be a zip file, so be sure you are using the Windows or Mac zip utility, and NOT a
third-party installation of WinRAR, 7-zip, or Winzip.