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 Members (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
thisboat, 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
trueif all seats ofthisboat 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
min an empty seat ofthisboat. This method may either:return
trueand modifythisboat by placingmin the first available seat. This may only happen if there is an empty seat on thethisboat, and a member equal tomis not already sitting on the boat. Or,return
falsewithout modifyingthisboat. This can only happen if:the boat is already full, or
there is already a member equal to
mthat 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 aprivatefield 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
staticmethods 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
Xdepicts the player position.The character
#depicts a wall: the player cannot move there.The character
(space) depicts an empty cell: the player can move there.
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
rowsand columns (cols). The maze must be empty, i.e. each cell must contain the character(space).public 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
mazecontains 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
charin 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 expressionewith 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.
Fig. 32 UML class diagram for 03 - Arithmetic Expressions, Version 3.#
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:
Monsterwill 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, andDemogorgonshould 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
Monstermust provide the constructor:public Monster(String species, String name, int maxHealth, double hitDamageFactor, double burnDamageFactor)
This constructor initialises a new object of the class
Monsterwith the givenspecies,name, maximum health (maxHealth), andhitDamageFactorandburnDamageFactor, which modify the damage the monster takes when hit or burnt, respectively (for example: ifburnDamageFactoris 0.5, then the monster takes half the damage when burnt; instead, ifburnDamageFactoris 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
Monstermust 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
monsterdefined 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.javadeveloped 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, andDemogorgonto 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 theMonstersuperclass usingsuper(as shown in Example 56 and Example 60).Similarly, your implementation of the class
Thingthat 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
hitDamageFactororburnDamageFactor(which have typedouble). To this end, you might need convert the result of an expression of typedoubleto 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
xhas typeintand has the result ofexpression_of_type_doublewith 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:
Nfor north;NEfor north-east;Efor east;SEfor south-east;Sfor south;SWfor south-west;Wfor west;NWfor 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
Particlemust have thepublicconstructor:public Particle(int row, int column, int gridRows, int gridColumns, String direction)
which constructs a
Particleobject located in a grid at the positionrow,column; the grid has a total number of rows and columns given by the argumentsgridRowsandgridColumns, respectively; moreover, the particle moves in the givendirection.You can assume that
rowandcolumnare non-negative and smaller thangridRowsandgridColumns, respectively; moreover, you can assume that the argumentdirectionis one of the directions listed above.Objects of the class
Particlemust provide the methods:public int getRow()
public int getColumn()
public String getDirection()
which return the current row, column, and direction of
thisparticle, respectively.Objects of the class
Particlemust provide the method:public void move()
This method must change the current row and/or column of
thisparticle 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
pis a particle located at row 2 and column 3 of a 10x10 grid, andpis moving in the directionSW, then the method callp.move()must change the position ofpto 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
pis a particle located at row 5 and column 3 of a 6x4 grid, andpmoving in the directionSW, then the method callp.move()must change the position ofpto row 4 and column 2, and the direction ofpmust change toNW— i.e.,pcannot 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
Particlemust provide the method:public String display()
This method must return a string that, when printed, visualises
thisparticle as an asterisk*inside a rectangle having the number of rows and columns specified by the argumentsgridRowsandgridColumnsof the constructor above. Moreover, the returned string must include the particle position and direction.For instance, if
pis a particle located at row 2 and column 3 in a 5x5 grid, andpis 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.