Module 11, Part 1: Lab Day#
This first part of Module 11 does not introduce new contents: instead, it provides a series of assessments to improve your Java programming skills. All the following assignments can be solved with the Java programming notions introduced in Modules 2–10.
Important
For each assessment, you can download the corresponding handout and submit your solution on DTU Autolab: https://autolab.compute.dtu.dk/courses/02312-E24.
For details on how to use Autolab and the assessment handouts, and how to submit your solutions, please read these instructions.
If you have troubles, you can get help from the teacher and TAs.
01 - Rowing Club, Revisited#
This assessment is a revised version of
02 - Rowing Club: your task is to help writing a
program for the management of the boats of a rowing club, where a club member is
represented as an object of the class Member
.
The key difference with 02 - Rowing Club is that a boat must be
now represented an object of the class Boat
, that offers the constructor
and methods discussed below. Overall, the idea is that the class Boat
must
provide methods to manage which Member
s (if any) are sitting in a boat object.
Your task is to edit the file Boat.java
provided in the handout, and implement
a class called Boat
with the following constructor and methods. Besides, your
definition of the class Boat
can include all the fields you like, but they
must be all private
.
public Boat(int seats)
This constructor initialises a new boat with the given number of empty seats.
public void print()
This method prints the content of each seat of
this
boat, one seat per line.When a seat is occupied by a member
m
, then this method must print the result ofm.description()
;Otherwise, when a seat is empty, this method must print:
<Empty seat>
public boolean isFull()
This method returns
true
if all seats ofthis
boat are occupied. Otherwise (i.e. if there is at least one empty seat) this method returnsfalse
.public boolean assignMember(Member m)
This method tries to place the given member
m
in an empty seat ofthis
boat. This method may either:return
true
and modifythis
boat by placingm
in the first available seat. This may only happen if there is an empty seat on thethis
boat, and a member equal tom
is not already sitting on the boat. Or,return
false
without modifyingthis
boat. This can only happen if:the boat is already full, or
there is already a member equal to
m
that is sitting on the boat.
The handout for this assessment contains the following files:
Member.java
: definition of the classMember
(do not modify!)Boat.java
: the class representing a boatTest01.java
,Test02.java
, …: test programs (do not modify!)BoatTestUtils.java
: utility methods used by some tests (do not modify!)
When you are done, submit the modified file Boat.java
on DTU Autolab.
Tip
When implementing the class
Boat
, you might consider defining aprivate
field of typeMember[]
to keep track of who is sitting in each boat position, and which seats are available (if any).You can approach this problem by taking the solution of 02 - Rowing Club (either your own solution, or the one provided by the teacher) and converting its
static
methods into (non-static) object methods (as shown in Example 40). (Note: you will also need to slightly change the name of some methods, according to the requirements above.)
02 - Maze#
You are helping develop a text-based video game where the player moves in a maze. The maze has a rectangular shape and is represented as a bidimensional array of characters, where each character depicts the content of a cell of the maze:
The character
X
depicts the player position.The character
#
depicts a wall: the player cannot move there.The character
Your task is to edit the file Maze.java
provided in the handout, and implement
the following static
methods:
public static char[][] createMaze(int rows, int cols)
This static method creates a maze with the given number of
rows
and columns (cols
). The maze must be empty, i.e. each cell must contain the characterpublic static boolean moveUp(char[][] maze) public static boolean moveDown(char[][] maze) public static boolean moveLeft(char[][] maze) public static boolean moveRight(char[][] maze)
Each one of these static methods tries to move the player by one cell in the requested direction in the given
maze
. If the move is possible (i.e., if the destination cell is within the limits of the givenmaze
, and the cell is empty), then the static method must update themaze
(by moving the player as requested) and returntrue
; otherwise, the static method must not modify themaze
, and must just returnfalse
.Note
When writing these methods, you can assume that the given
maze
contains exactly one cell with the player.
When you are done, submit the modified file Maze.java
on DTU Autolab.
Warning
The automatic grading on DTU Autolab includes some additional secret checks that test your submission with more mazes. After you submit, double-check your grading result on DTU Autolab: if the secret checks fail, then your solution is not correct, and you should fix it and resubmit.
Hint
Remember that a value of type
char
in Java is represented between single quotes'
— for instance,'A'
,'b'
,' '
(space), …The static methods
moveUp(...)
,moveDown(...)
,moveLeft(...)
, andmoveRight(...)
must determine the position of the player in the given maze, before moving it. To do that, you could inspect each position in the maze, until you find the one that containsX
.When implementing
moveUp(...)
,moveDown(...)
,moveLeft(...)
, andmoveRight(...)
, you might be able to reduce the amount of code duplication by writing an auxiliary (andprivate
) static method that can move the player in any direction…
03 - Arithmetic Expressions, Version 3#
This is a follow-up to the assessment 04 - Arithmetic Expressions, Version 2,
and the starting point is its solution, i.e. the file Expression.java
(you can use either your own file, or the one provided by the teacher as a
solution to 04 - Arithmetic Expressions, Version 2).
Your task is to improve the solution to 04 - Arithmetic Expressions, Version 2 by adding support for some unary operations, i.e. operations that take only one argument. The goal is to introduce 3 new classes with the following constructors:
Minus(e)
, whose result is the result of the given expressione
with its sign flipped (from positive to negative, or vice versa). For instance, if we havevar m = new Minus(Constant(42.0))
, then:m.result()
must return the value -42.0;m.format()
must return the string"-(42.0)"
.
AbsoluteValue(e)
, whose result is the absolute value of the result of the given expressione
. For instance, if we havevar a = new AbsoluteValue(Constant(-42.0))
, then:a.result()
must return the value 42.0;a.format()
must return the string"abs(42.0)"
.
Hint
The Java API method Math.abs(…) can be useful.
SquareRoot(e)
, whose result is the square root of the result of the given expressione
. For instance, if we havevar s = new SquareRoot(Constant(9.0))
, then:s.result()
must return the value 3.0;s.format()
must return the string"sqrt(9.0)"
.
All the new classes Minus
, AbsoluteValue
, and SquareRoot
must extend an
abstract class called UnaryOperation
which implements the interface
Expression
.
Your task is to edit the file Expression.java
and implement the classes
described above, matching the UML diagram in
Fig. 32 below — where the difference
with 04 - Arithmetic Expressions, Version 2 are the abstract class
UnaryOperation
and its subclasses.
When you are done, submit the modified file Expression.java
on DTU Autolab.
The handout includes some Java files called Test01.java
, Test02.java
, etc.:
they are test programs that use the code you should write in Expression.java
,
and they might not compile or work correctly until you complete your work. You
should read those test programs, try to run them, and also run ./grade
to see
their expected outputs — but you must not modify those files.
Note
This assessment has several potential solutions. In fact, the UML diagram in
Fig. 32 omits various details in the
classes BinaryOperation
and UnaryOperation
— e.g. what is its constructor
(if any), what methods it implements, and whether it has non-private
fields:
you are free to choose those details as you like, trying to minimise code
duplication as much as possible. After the submission deadline expires, please
compare your solution with the one provided by the teacher.
Warning
The automatic grading on DTU Autolab includes some additional secret checks that test your submission with more expressions. After you submit, double-check your grading result on DTU Autolab: if the secret checks fail, then your solution is not correct, and you should fix it and resubmit.
04 - Video Game Monsters, Part 5#
Important
For this assessment you must submit two files: Monster.java
and
GameUtils.java
. For the submission instructions, see the
note at the end of this assessment.
This is a follow-up to the assessment
06 - Video Game Monsters, Part 4, and the starting point is its
solution, i.e. the files Monster.java
and GameUtils.java
(you can use either
your own files, or the ones provided by the teacher as a solution to
06 - Video Game Monsters, Part 4).
The development of the video game has two new requirements:
there is a new species of monster called the “thing”;
sometimes, the game may need to create some monsters that do not fit one of the 4 main species (wumpus, owlbear, demogorgon, thing).
Therefore, the development team decides to revise the structure of the Java code of the game:
Monster
will become a class (instead of an interface) allowing the creation of various kinds of monsters having different species, names, maximum health points, and damage from being hit or burnt;Wumpus
,Owlbear
, andDemogorgon
should become sub-classes of the classMonster
, each one with with its predetermined characteristics (listed in 06 - Video Game Monsters, Part 2).
You will need to edit the file Monster.java
to turn the interface Monster
into a class Monster
in the file Monster.java
. The class Monster
must
implement all the methods that were specified for the Monster
interface (as
described in 06 - Video Game Monsters, Part 2), plus the one listed below.
Besides, feel free to define all the fields you need — but they must be all
private
.
The class
Monster
must provide the constructor:public Monster(String species, String name, int maxHealth, double hitDamageFactor, double burnDamageFactor)
This constructor initialises a new object of the class
Monster
with the givenspecies
,name
, maximum health (maxHealth
), andhitDamageFactor
andburnDamageFactor
, which modify the damage the monster takes when hit or burnt, respectively (for example: ifburnDamageFactor
is 0.5, then the monster takes half the damage when burnt; instead, ifburnDamageFactor
is 2.0, the monster takes twice the damage when burnt). When created, the health points of the monster object correspond to its maximum health points.For example, the constructor can be used as follows:
var monster = new Monster("skeleton", "Toothless", 42, 2.0, 1.0);
This creates a new monster of the species “skeleton” that is called Toothless, has 42 maximum health points, takes twice the damage when hit, and normal damage when burnt.
The class
Monster
must provide the following method:public char getSymbol()
This method returns a character representing the monster, used to show the monster on the playground. The character must be the first letter of the monster species, uppercase. For example, for the variable
monster
defined above,monster.getSymbol()
must return the characterS
(i.e. the first letter of"skeleton"
, uppercase).
After you implement the class Monster
, you will need to revise the classes
Wumpus
, Owlbear
, and Demogorgon
to make them extend the class Monster
.
Finally, you will need to implement the new class Thing
for the new
species of monster, which has a maximum of 30 health points, and takes double
damage when burned.
Note
For this assessment you need to prepare and submit a ZIP file containing your
modified versions of Monster.java
and GameUtils.java
. To prepare that ZIP
file, you can simply execute from the terminal (inside the handout directory):
./grade -z
This command will grade your work and prepare a ZIP file that you can then submit on DTU Autolab.
Hint
When solving this assessment, you should not need to change the file
GameUtils.java
developed for 06 - Video Game Monsters, Part 4 (i.e. you should be able to just copy&paste it, and submit it as it is).As you revise the classes
Wumpus
,Owlbear
, andDemogorgon
to make them extend the classMonster
, you should be able to remove almost all their code, and reuse the methods already provided byMonster
. You should just need to call the constructor of theMonster
superclass usingsuper
(as shown in Example 56 and Example 60).Similarly, your implementation of the class
Thing
that derives fromMonster
, you should be able to reuse all the methods provided byMonster
.When updating a monster’s health after the monster is hit or burnt, you will need to multiply the damage by the
hitDamageFactor
orburnDamageFactor
(which have typedouble
). To this end, you might need convert the result of an expression of typedouble
to typeint
: to achieve this you can use a narrowing primitive cast by writing(int)
before the expression of typedouble
, e.g.var x = (int)expression_of_type_double;
This way, the variable
x
has typeint
and has the result ofexpression_of_type_double
with its decimal digits truncated.
05 - Particle#
Your task is to edit the file Particle.java
provided in the handout, and
implement a class named Particle
that simulates a particle moving through a
rectangular grid. The particle has a position represented by non-negative row
and column numbers. The position corresponding to row 0 and column 0 is located
in the top-left corner of the grid. The particle moves in one of the following
directions:
N
for north;NE
for north-east;E
for east;SE
for south-east;S
for south;SW
for south-west;W
for west;NW
for north-west.
The definition of the class Particle
must satisfy the following requirements;
besides, feel free to define all the fields you need — but they must be all
private
.
The class
Particle
must have thepublic
constructor:public Particle(int row, int column, int gridRows, int gridColumns, String direction)
which constructs a
Particle
object located in a grid at the positionrow
,column
; the grid has a total number of rows and columns given by the argumentsgridRows
andgridColumns
, respectively; moreover, the particle moves in the givendirection
.You can assume that
row
andcolumn
are non-negative and smaller thangridRows
andgridColumns
, respectively; moreover, you can assume that the argumentdirection
is one of the directions listed above.Objects of the class
Particle
must provide the methods:public int getRow()
public int getColumn()
public String getDirection()
which return the current row, column, and direction of
this
particle, respectively.Objects of the class
Particle
must provide the method:public void move()
This method must change the current row and/or column of
this
particle by moving it by one cell along its current direction, in a grid having the number of rows and columns specified in the constructor above.For instance, if
p
is a particle located at row 2 and column 3 of a 10x10 grid, andp
is moving in the directionSW
, then the method callp.move()
must change the position ofp
to row 3 and column 2.Importantly, the particle must bounce and change direction if it tries to move beyond the limits of the grid.
For instance, if
p
is a particle located at row 5 and column 3 of a 6x4 grid, andp
moving in the directionSW
, then the method callp.move()
must change the position ofp
to row 4 and column 2, and the direction ofp
must change toNW
— i.e.,p
cannot keep moving south-west after row 5 (because it is the last row of the 6x4 grid), so it bounces and starts moving north-west. (See the animation at the end of this assessment for a visual representation of a bouncing particle.)Tip
Remember that the grid position at row 0 and column 0 is located in the top-left corner of the grid. Therefore, a particle moving south will increase its row number (unless it has already reached the last row of the grid), and a particle moving east will decrease its column number (unless it has already reached column 0).
Objects of the class
Particle
must provide the method:public String display()
This method must return a string that, when printed, visualises
this
particle as an asterisk*
inside a rectangle having the number of rows and columns specified by the argumentsgridRows
andgridColumns
of the constructor above. Moreover, the returned string must include the particle position and direction.For instance, if
p
is a particle located at row 2 and column 3 in a 5x5 grid, andp
is moving in the directionSW
, then the method callp.display()
must return the following string: (remember that the coordinate with row 0 and column 0 is in the top-left corner of the grid)+-----+ | | | | | * | | | | | +-----+ Position: (2,3); direction: SW
Tip
To create the string returned by the method
display(...)
, you will need to useSystem.lineSeparator()
, as explained in the hints of 06 - Square 2. Notice that the returned string must include a line separator at the end of the last line.
When you are done, submit the modified file Particle.java
on DTU Autolab.
The handout includes some Java files called Test01.java
, Test02.java
, etc.:
they are test programs that use the code you should write in Particle.java
,
and they might not compile or work correctly until you complete your work. You
should read those test programs, try to run them, and also run ./grade
to see
their expected outputs — but you must not modify those files.
Tip
The test Test13.java
can show an animation based on your implementation of the
class Particle
. To see the animation, you will need to open a terminal in the
directory of the handout and compile all Java files:
javac *.java
Then you can execute Test13
by providing the command-line argument
animate
, e.g.:
java Test13 animate
The animation should look as follows:
Note
For Windows users: if the animation is not displayed correctly, make sure that the console program you are using is Git Bash (as recommended) or Powershell.
Warning
The automatic grading on DTU Autolab includes some additional secret checks. After you submit, double-check your grading result on DTU Autolab: if the secret checks fail, then your solution is not correct, and you should fix it and resubmit.