Description
COMP 1020 ASSIGNMENT 1: Introduction to Object-Oriented Programming
Assignment overview
In this assignment, you will implement a set of related classes of objects:
Student: A university student
StudentList: A list of students
Course: A course with a title, short title, class list, etc.
CourseList: A class list
Keep all of your methods short and simple. In a properly-written object-oriented program, the work is distributed among
many small methods, which call each other. There are no methods in this entire assignment that should require more
than 12 lines of code, not counting comments, blank lines, or {} lines (and many of them need no more than 3-4).
Unless specified otherwise, all instance variables must be private, and all methods should be public. Also, unless
specified otherwise, there should be no println statements in your classes. Objects usually do not print anything, they
only return String values from toString methods. The only exceptions in this assignment are register in Course
(Phase 2) and withdraw in Course (Phase 3).
Testing Your Coding
We have provided sample test files for each phase to help you see if your code is working according to the assignment
specifications. These files are starting points for testing your code. Part of developing your skills as a programmer is to
think through additional important test cases and to write your own code to test these cases. For marking, we will use
longer and more comprehensive tests.
Phase 1: Student and StudentList
First, implement two simple classes: a Student class and a StudentList class
The Student class should have:
Three instance variables: the student’s first name (a String), last name (a String) and student number (an
int)
A constructor that has three parameters, in the above order, which are used to initialize the three instance
variables.
A standard toString method, which returns a String containing the student’s last and first names separated
by a comma, and student number in between parentheses (as shown in the output below).
ASSIGNMENT 1: Introduction to Object-Oriented Programming
COMP 1020
Page 2 of 7
An equals method that checks if two Students are equal. Two students are equal if they have the same first
name, last name and student number.
The StudentList class should have:
Three instance variables: an array of Students, the maximum size of the array (an int) and the current number
of students in the array (an int)
A constructor that takes one parameter: the maximum size of the array. The other instance variables must be
initialized in the constructor (assume that the StudentList will be empty when constructed).
A method contains(Student) that checks if the student is already in the list and returns a boolean (true if in the
list or false otherwise).
A method addStudent that has a parameter of type Student, adds the Student to the list only if there is enough
space. This method returns a boolean (true if the student was added and false otherwise).
A toString method which returns a String containing all the Students in the list, one Student per line (as
shown below).
You can test your classes using the supplied test program TestPhase1.java. You should get the output shown below.
Frost, Miranda (123001)
The list already contains: Frost, Miranda (123001)
Frost, Miranda (123001)
Bullion, Mister (123002)
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Cannot add student: Grishenko, Boris (123004)
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Phase 2: Course and CourseList
Next, implement the Course class, and a CourseList.
The Course class should have:
A class constant: the maximum size of the wait list (you can set it to 100).
Five instance variables: the title of the course (a String), the short title of the course (a String – e.g.
COMP1020), the maximum class size (an int), a class list (a StudentList) and a wait list (a StudentList).
A constructor that accepts three parameters, the title, short title and maximum class size. The two StudentLists
should also be instantiated by the constructors.
A method register(Student) that registers the Student to the appropriate list, if possible, using the rules
described here:
o if the student is already in the class list, nothing is to be done, and the method should print “The
student [student description] is already registered to [course short title]!”
o if the student is not in the class list, and space is available, the method adds the student to the class
list and prints: “The student [student description] has been registered successfully to [course short
title].” This method also adds the course to the course list of the student (see Changes to Student
class below).
o if the class list is full, then the method tries to add the student to the wait list
o if the student is already on the wait list, nothing is to be done and the method should print “The
student [student description] is already on the wait list for [course short title]!”
o if the student is not on the wait list and space is available, the method adds the student to the wait
list and prints: “The student [student description] has been placed on the wait list for [course short
title].”
ASSIGNMENT 1: Introduction to Object-Oriented Programming
COMP 1020
Page 3 of 7
o if the wait list is full, nothing is to be done and the method prints “The wait list is full for [course short
title]!”
A getTitles method, that returns a String containing the course short title followed by a dash and the
course title.
A toString method that returns a String containing the course short title followed by a dash and the course
title on the first line. On the following lines, the class list and wait list are printed (see example below).
Then, implement a CourseList class. This class should have:
A class constant: the maximum number of courses a student can take (set it to 100).
Two instance variables: an array of Courses, and the current number of courses in the list (an int)
A constructor that has no parameters, which initializes the instance variables (the CourseList should be empty
when created).
A method contains(Course) that returns true if the course is already in the list, false otherwise.
An addCourse(Course) method (void) that adds the Course to the list.
a getAllTitles method that calls the getTitles method for each Course of the list, and builds a String
representation of all the courses on the list, one Course per line.
A toString method that returns a String containing the full String representation (titles, class list and wait
list) of all Courses in the list (as shown in the example below).
Changes to Student class:
Add an additional instance variable: a CourseList, containing the list of all courses the student is registered to
(fully registered, not on the wait list).
The constructor should instantiate the above instance variable (empty CourseList).
A method addCourse(Course), that adds the Course to the CourseList. You may assume that it will never
get full.
A method getCourseListString, that returns a String containing “Student [student description] is
registered to:” followed on the next lines by the list of course titles, using the getAllTitles method of the
CourseList class.
You can test your class with TestPhase2.java. You should get the output shown below.
The student Frost, Miranda (123001) has been registered successfully to COMP1010.
The student Bullion, Mister (123002) has been registered successfully to COMP1010.
The student Simonova, Natalya (123003) has been registered successfully to COMP1010.
The student Grishenko, Boris (123004) has been registered successfully to COMP1010.
The student Davidov, Sacha (123005) has been registered successfully to COMP1010.
The student Carver, Paris (123006) has been registered successfully to COMP1010.
The student Gupta, Henry (123007) has been placed on the wait list for COMP1010.
COMP1010 – Introductory Computer Science 1
Class list:
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Wait list:
Gupta, Henry (123007)
The student Simonova, Natalya (123003) has been registered successfully to COMP1020.
The student Onatopp, Xenia (123008) has been registered successfully to COMP1020.
The student Drax, Hugo (123009) has been registered successfully to COMP1020.
The student Zukovsky, Valentin (123010) has been registered successfully to COMP1020.
ASSIGNMENT 1: Introduction to Object-Oriented Programming
The student Ourumov, Arkady Grigorovich (123011) has been registered successfully to
COMP1020.
The student Mishkin, Dmitri (123012) has been placed on the wait list for COMP1020.
The student Lynd, Vesper (123013) has been placed on the wait list for COMP1020.
The student Trevelyan, Alec (123014) has been placed on the wait list for COMP1020.
The student Scaramanga, Francisco (123015) has been placed on the wait list for
COMP1020.
The student Jones, Christmas (123016) has been placed on the wait list for COMP1020.
The student Lin, Wai (123017) has been placed on the wait list for COMP1020.
The student King, Elektra (123018) has been placed on the wait list for COMP1020.
COMP1020 – Introductory Computer Science 2
Class list:
Simonova, Natalya (123003)
Onatopp, Xenia (123008)
Drax, Hugo (123009)
Zukovsky, Valentin (123010)
Ourumov, Arkady Grigorovich (123011)
Wait list:
Mishkin, Dmitri (123012)
Lynd, Vesper (123013)
Trevelyan, Alec (123014)
Scaramanga, Francisco (123015)
Jones, Christmas (123016)
Lin, Wai (123017)
King, Elektra (123018)
The student Gupta, Henry (123007) is already on the wait list for COMP1010!
COMP1010 – Introductory Computer Science 1
Class list:
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Wait list:
Gupta, Henry (123007)
The student Drax, Hugo (123009) is already registered to COMP1020!
COMP1020 – Introductory Computer Science 2
Class list:
Simonova, Natalya (123003)
Onatopp, Xenia (123008)
Drax, Hugo (123009)
Zukovsky, Valentin (123010)
Ourumov, Arkady Grigorovich (123011)
Wait list:
Mishkin, Dmitri (123012)
Lynd, Vesper (123013)
Trevelyan, Alec (123014)
Scaramanga, Francisco (123015)
Jones, Christmas (123016)
Lin, Wai (123017)
King, Elektra (123018)
ASSIGNMENT 1: Introduction to Object-Oriented Programming
The student Simonova, Natalya (123003) has been registered successfully to COMP2140.
The student Simonova, Natalya (123003) has been registered successfully to COMP2150.
The student Simonova, Natalya (123003) has been registered successfully to COMP3350.
Student Simonova, Natalya (123003) is registered to:
COMP1010 – Introductory Computer Science 1
COMP1020 – Introductory Computer Science 2
COMP2140 – Data Structures and Algorithms
COMP2150 – Object Orientation
COMP3350 – Software Engineering 1
Phase 3: Withdrawing from a Course
Next implement a withdraw(Student) method in the Course class, which will withdraw the Student from the class list,
if the Student is on the class list, or withdraw the Student from the wait list, if the Student is on the wait list, or do
nothing if the Student is not in any of the lists.
The method must print:
o “The student [student description] has been withdrawn from [course short title].” if the student
was on the class list.
o “The student [student description] has been withdrawn from the wait list of [course short title].”
if the student was on the wait list.
o “The student [student description] is not on any list of [course short title].” otherwise.
If the Student was on the class list, the method must also remove the Course from the Student’s CourseList.
If the Student was on the class list, and there is at least one Student on the wait list, the first Student on the
wait list must be registered to the class list (and removed from the wait list).
When removing a Student from a class/wait list, or removing a course from a CourseList, you must fill in the
gap by shifting up all the following Students/Courses. Also, don’t forget to update the counter of the current
number of students or current number of courses.
Important: to fully complete Phase 3, following the instructions above, you will need to add other methods
to other classes(while maintaining encapsulation – every object is responsible for modifying its own instance
variables).
You can test your class with TestPhase3.java. You should get the output shown below:
The student Frost, Miranda (123001) has been registered successfully to COMP1010.
The student Frost, Miranda (123001) has been registered successfully to COMP2150.
The student Bullion, Mister (123002) has been registered successfully to COMP1010.
The student Simonova, Natalya (123003) has been registered successfully to COMP1010.
The student Grishenko, Boris (123004) has been registered successfully to COMP1010.
The student Davidov, Sacha (123005) has been registered successfully to COMP1010.
The student Carver, Paris (123006) has been registered successfully to COMP1010.
The student Gupta, Henry (123007) has been placed on the wait list for COMP1010.
The student Onatopp, Xenia (123008) has been placed on the wait list for COMP1010.
COMP1010 – Introductory Computer Science 1
Class list:
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Wait list:
Gupta, Henry (123007)
Onatopp, Xenia (123008)
ASSIGNMENT 1: Introduction to Object-Oriented Programming
COMP 1020
Page 6 of 7
Student Frost, Miranda (123001) is registered to:
COMP1010 – Introductory Computer Science 1
COMP2150 – Object Orientation
The student Zukovsky, Valentin (123010) is not on any list of COMP1010.
COMP1010 – Introductory Computer Science 1
Class list:
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Wait list:
Gupta, Henry (123007)
Onatopp, Xenia (123008)
The student Gupta, Henry (123007) has been withdrawn from the wait list of COMP1010.
COMP1010 – Introductory Computer Science 1
Class list:
Frost, Miranda (123001)
Bullion, Mister (123002)
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Wait list:
Onatopp, Xenia (123008)
The student Frost, Miranda (123001) has been withdrawn from COMP1010.
The student Onatopp, Xenia (123008) has been registered successfully to COMP1010.
COMP1010 – Introductory Computer Science 1
Class list:
Bullion, Mister (123002)
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Onatopp, Xenia (123008)
Wait list:
The student Bullion, Mister (123002) has been withdrawn from COMP1010.
COMP1010 – Introductory Computer Science 1
Class list:
Simonova, Natalya (123003)
Grishenko, Boris (123004)
Davidov, Sacha (123005)
Carver, Paris (123006)
Onatopp, Xenia (123008)
Wait list:
Student Frost, Miranda (123001) is registered to:
COMP2150 – Object Orientation
ASSIGNMENT 1: Introduction to Object-Oriented Programming
COMP 1020
Page 7 of 7
Hand in
Submit your four Java files (Student.java, StudentList.java, Course.java, CourseList.java). Do not
submit .class or .java~ files! You do not need to submit the TestPhaseN.java files that were given to you. If you did
not complete all phases of the assignment, use the Comments field when you hand in the assignment to tell the
marker which phases were completed, so that only the appropriate tests can be run. For example, if you say that you
completed Phases 1-2, then the marker will compile your files, and compile and run the tests for phases 1 and 2. If it
fails to compile and run, you will lose all of the marks for the test runs. The marker will not try to run anything else,
and will not edit your files in any way. Make sure none of your files specify a package at the top!
COMP 1020 ASSIGNMENT 2: Input/output, Exceptions, and Multi-dimensional arrays
Assignment overview
In this assignment, you will build a version of the game Bejewelled. Bejewelled is a ‘match 3’ game, where you must
match 3 or more of the same gem by moving the gems on the board. The gems can only move 1 cell up or down, left or
right, and swap with neighbouring gem when moving. Upon matching, the gems that match disappear, leaving a gap,
and the gems above the gap fall, filling the gap. If you are unfamiliar with the game, you can plan an online version here.
Keep all of your methods short and simple. In a properly-written object-oriented program, the work is distributed among
many small methods, which call each other. There are few methods in this entire assignment that should require more
than 15 lines of code, not counting comments, blank lines, or {} lines.
Unless specified otherwise, all instance variables must be private, and all methods should be public.
Your assignment should be DRY – don’t repeat yourself. If you notice you have code that does the same function in two
places, consider making a private method that can be called to do the work. If you see 3 or more lines of code that do
the same thing in two different methods, consider making a private method that does that task. This is often called a
‘helper’ method.
Testing Your Coding
We have provided sample test files for each phase to help you see if your code is working according to the assignment
specifications. These files are starting points for testing your code. Part of developing your skills as a programmer is to
think through additional important test cases and to write your own code to test these cases.
Phase 1: The Grid
First, create the game board, named class Grid.
The Grid class should have:
• An instance variable to hold the board, which is a 2D array of char.
• A method fillBoard(), which fills the board with random gems, overwriting whatever is in the board.
• A constructor Grid(int height, int width), which creates a new game board filled with random gems.
• A standard toString method, which returns a text representation of the board.
To choose random gems, you can add this to your Grid class:
public static char[] gems = {‘r’, ‘g’, ‘b’,’y’};
ASSIGNMENT 2: Input/output, Exceptions, and Multi-dimensional arrays
COMP 1020
Page 2 of 4
public static char getRandomGem() {
int choice = (int)(Math.random() * gems.length);
return gems[choice];
}
Phase 2: Grids from files
We want to be able to save our progress. To do this, we will save our progress to a file, and be able to read these files.
The save files have a special format. The top line is the dimensions of the saved board: number of rows, then number
of columns. The rest of the file is the contents of the board. Example:
2 3
yrb
bry
Is a valid file.
To do this, implement these methods in the Grid class:
• A new constructor, Grid(char[][] someGrid), which creates a grid with the given data. You do not need
to check if the gems are valid (in the set of letters provided).
• A factory method called Grid createGrid(String filename), which reads the data the text file specified
by ‘filename’, and returns a Grid object with that data. This method throws IOException if the data is not
valid. Special exception messages include:
o Bad dimensions for the saved file
o Not enough rows of data to read
o Not enough columns of data to read
Your error messages should have as much detail as possible. See the sample output for what is expected. This
method is quite long, due to the error handling, and will exceed the usual “15 lines of code” rule-of-thumb.
• A save(String filename)method, that writes the current board to the specified file, in the save file format
used. If there is an exception, it should print out the error message, and return null.
Sample output:
yr
by
bb
rr
java.io.IOException: No dimensions to read
java.io.IOException: The size values were not numeric!
java.io.IOException: There was not enough rows! Saw 5 need 10
java.io.IOException: There was not enough colums. Saw 2 need 12
yr
by
These should be the same:
rryryb
yybgbg
yrrbrb
yyryrr
brgbgr
rryryb
yybgbg
yrrbrb
yyryrr
ASSIGNMENT 2: Input/output, Exceptions, and Multi-dimensional arrays
brgbgr
Phase 3: Extracting data
Add the following methods to extract data from your Grid class. You will use these later in the program.
• Method char[] extractRow(int rowNum) that extracts the row specified by the passed integer. 0 will
fetch the first row, 1 the second (index-by-zero rules).
• Method char[] extractColumn(int colNum), which extracts a single column, much like extract row.
Phase 4: Checking for gems in a row
Write a method named static char[] replaceSets(char[] input) in Grid that is passed a 1D array of gems,
and checks if there are set of 3 or more gems in a row. Return a new array that has the gems that are in a row replaced
with ‘x’ characters.
Phase 5: Merge
We have methods to find if there are sets of gems. Now, write the method replaceAll() in Grid. This method uses
the methods created in phase 4 to mark any sets of 3 with x’s.
There are some subtleties to this method. Consider:
bbb
bgg
bgg
There is a set of 3 in both the first row, and first column. If you set the first row to all x’s, then check the column, then
column 0 would be xbb, and the program would not set column 0 to all x’s. A solution to this is to create a new 2D array
with the sets replaced by x’s, while looking at the original to see if there are sets to be replaced.
Phase 6: Drop
Create method boolean drop() in class Grid. This method ‘drops’ the gems that are above cells that have an x in
them. In Bejewelled, as gems disappear, the gems above them drop down. This method does the dropping step.
The drop method returns true if any gems have moved.
In any spots that are now empty, place random gems. This will be the gems that are ‘falling from the top’.
Phase 7: Swap
Create 4 public static final variables in class Grid: UP, DOWN, LEFT, and RIGHT. You can set these to any numbers
you like but they all must be different numbers.
Create the method void swap(int row, int col, int direction). This will swap the gem specified by row
and column (indexed at 0) in the direction specified. Throw appropriate exceptions for out-of-bounds gem selection,
and movement. Throw IndexOutOfBoundsException for any strange things that may happen.
ASSIGNMENT 2: Input/output, Exceptions, and Multi-dimensional arrays
Phase 8: Bonuses: Is that swap allowed? Ending the game?
+10%: In Bejewelled, moves are only allowed if it causes a match. Update the game to enforce that rule.
+20%: The game is over when there are no more moves. Update the game, and TestPhase7b.java to enforce this. Visit
every gem, and see if it can move up/down/left/right. Continue the game if there is at least 1 valid move left.
If you accomplish these bonus items, write that you did so in the comment section of the hand-in.
Hand in
Submit your one Java file (Grid.java). Do not submit .class or .java~ files! You do not need to submit the
TestPhaseN.java files that were given to you unless you attempted the bonus. If you did not complete all phases of
the assignment, use the Comments field when you hand in the assignment to tell the marker which phases were
completed, so that only the appropriate tests can be run. For example, if you say that you completed Phases 1-2, then
the marker will compile your files with appropriate test cases. If it fails to compile and run, you will lose all of the
marks for the test runs. The marker will not try to run anything else, and will not edit your files in any way. Make sure
none of your files specify a package at the top!
COMP 1020 ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
Assignment overview
In this assignment, you will implement a text-based game that is heavily inspired by the game NetHack. NetNack is a
classic open-source console-based game, and has been ported to most operating systems. See their homepage here, or
play online here. NetHack is a very deep game, and we are only borrowing basic elements from it.
The key parts we are keeping are:
• There is a board of size m by n.
• Each element of the board may be a wall or an empty space.
• Each empty space can be occupied by one character or item: either the player, an enemy, a health potion or a
trap.
• Commands are given by typing “up”, “down”, “left” or “right” (or just ‘u’, ‘d’, ‘l’, or ‘r’). The player will only
move in that direction if the space is unoccupied, and not a wall.
• If the space is occupied by a different character, the player attacks that character.
Keep all of your methods short and simple. In a properly-written object-oriented program, the work is distributed among
many small methods, which call each other.
There are many files to hand in with this assignment, most of which are only 1 or 2 lines long. Only a few will need 20
lines of code or more. Writing good code that uses inheritance means writing the logic once, and using that logic in the
subclasses.
Phase 1: The board
First, implement the abstract class Tile. This class represents the elements of the two-dimensional array that is the
board (a Tile[][] array). The tiles will hold the game pieces or a wall. We will add more to this class later. To start, a
Tile should have:
• Two instance variables: a String which is the symbol that should be displayed by this tile, and a boolean
which will indicate if this tile is a tile that the player can move onto (is “passable”).
• A constructor that has two parameters – the String and the boolean, in that order.
• Method String getSymbol()which fetches the symbol that should be displayed.
• Method boolean isPassable() which indicates if the tile is passable.
Now implement two subclasses of the Tile class: Wall, and OpenSpace.
• Class Wall is not passable, and the symbol is a hash: #
• Class OpenSpace is an empty space which is passable, and the symbol is a period: .
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
COMP 1020
Page 2 of 9
These subclasses will only contain constructors. All the other logic in them is inherited from class Tile.
You can test your classes using the supplied test program TestPhase1.java. You should get the output shown below.
####
#..#
#..#
####
Phase 2: Content
Next, implement the abstract Content class, which represents items that are sitting on the Tiles.
The Content class should have:
• One instance variable: a String that represents the symbol that will be drawn on the map. This can be a
protected variable.
• A constructor that accepts only one parameter (the String).
• A String getSymbol()method that returns the symbol for this item.
Implement an abstract subclass of Contents named Item. Subclasses of Item will be objects in the game that the
player can touch to interact with. Item should have:
• A constructor with only a String parameter specifying the symbol.
• An int getEffect() method that returns how much of the player’s health (“hit points”) are added, or
removed by touching this item. The default value to return is 0.
Now write three subclasses of Item:
• Amulet: which is marked by the character “Y” on the map. This is the “Amulet of Yendor”. Picking up this item
will result in winning the game. This item has no effect on hit points. This will be implemented later. In addition
to returning a 0, the getEffect() method should also write “You picked up the Amulet of Yendor!” to the
console.
• HealthPotion: Represented by an “h” on the map, a health potion has the effect of adding 5 hit points
(health) to the player. In addition to returning a 5, the getEffect() method should also write “You picked
up a health potion!” to the console.
• Trap: Represented by a “^” on the map, the player will lose 5 hit points when touching this item. In addition
to returning a -5, the getEffect() method should also write “You set off a trap!” to the console.
These three classes only contain a no-parameters constructor, and a getEffect() method.
Now make the following modifications to class Tile and its subclasses:
• Add an instance variable of type Content to Tile. When there is no content to a tile, this variable should be
null.
• Add methods removeContent(), which will set your Content instance variable to null, and a
getContent() method which will return the contents of this tile, and a setContent(Content) method
which will set the content of this tile.
• Change the getSymbol() method to return the symbol of the content, if there is a content in the tile.
Otherwise, return the symbol of the tile itself.
• Add a second constructor to the Tile and OpenSpace classes, that accepts an additional parameter of type
Content. The signature should be: public Tile(String, boolean, Content). The Wall class should
not have a constructor of this kind, since a wall cannot have any content.
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
You can test your class with TestPhase2.java. You should get the output shown below.
####
#^Y#
#^h#
####
Phase 3: Combatants
Combatants are the characters on the board. There is always exactly one player, and zero or more enemies. Both have
“hit points” (the amount of health the combatant has). When the hit points become zero or lower, the combatant is
removed from the board. Health potions can increase the player’s hit points, while traps lower the player’s hit points.
Combatants have attacks which vary in strength. There are minimum and maximum attack values. Each time an attack
is made, a new random attack value between the minimum and maximum is returned. This amount of health is removed
from the combatant that is being attacked.
Define an abstract Combatant class that is a subclass of Content. It should have:
• Three instance variables: int values for the health, and minimum and maximum attack values.
• A constructor which accepts parameters of type (String, int, int, int) which are the symbol, health,
minimum, and maximum attack points, in that order.
• Three methods:
o int getHP() – returns the current number of hit points (health)
o int doAttack() – return a random number between the minimum and maximum attack values,
inclusive. Investigate Math.random() to do this.
o void changeHP(int amount) – add this amount to the combatant’s hit points. The number could
be negative.
Define three subclasses of Combatant:
• Player: represented by an “@” on the board, this is the playing piece the user will be able to move. The player
should start with 100 hit points, and have a minimum attack value of 5, and a maximum of 10.
• Troll: represented by a “t” on the board. Trolls should start with 15 hit points, and have a minimum attack
value of 1, and a maximum of 10.
• GreaterTroll, which is a subclass of Troll: Greater Trolls have double the hit points of Trolls, attack twice
not once, and are represented by a “T” on the board. The constructor of GreaterTroll should call the
constructor of Troll, then modify the hit points. The doAttack() method of GreaterTroll should call the
doAttack() method in Troll twice, and return the total damage.
• These three subclasses should have only a no-parameters constructor.
Combatant
Player Troll
Greater Troll
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
Add toString() methods to the Combatant class, and all of its subclasses, that simply returns the class name.
You can test your class with TestPhase3.java. You should get the output shown below.
######
#^Y.t#
#^h@.#
######
Player hp is:100
Troll hp is:15
Phase 4: Your own Enemies
Create a new enemy class, of your choosing and design. This is very open ended. The only requirements are that there
is a unique letter attributed with the name on the map, and that it has a unique name in the game when it is in a fight.
Then, create a subclass of that enemy, that is a more specialized version of that enemy (much like Troll, GreaterTroll).
In your subclass, override the changeHP method to double any values that are applied. If a 2 is passed, add 4. If a -4 is
passed, use -8.
Phase 5: Gameboard
Create a Gameboard class that will hold and manage a 2D array of tiles that will represent the game state. To initialize
the game board, data will be read in from a text file. The text file has the following format. The first row contains two
integers that specify how many rows and columns are in the rectangular game board. The rest of the file gives the initial
state of the game board. It has the same format as the output that we have been generating to this point: “Y” is the
amulet, “@” is the player, and so on.
The Gameboard class, for this phase, only needs one instance variable of type Tile[][].
Write a constructor that accepts a file name as a parameter (a String). Open that file, read the contents, and initialize
your two dimensional array of tiles based on the file. It can be assumed that the file will be in the same folder as your
code.
Write a toString() method that returns the game board as a multi-line String. The first line should give the current
health of the player, and the remaining lines should show the board. See the examples below.
You can test your class with TestPhase5.java. You should get the output shown below. Make sure the supplied test
data files (phase5GameBoard1.txt and phase5GameBoard2.txt) are in the same folder as the rest of your files.
Health: 100
#######
#^Y.t.#
#^h@.T#
#.h..h#
#######
Health: 100
#############
#^Y.t…….#
#^h..T..^…#
#.h..h…..@#
#############
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
Phase 6: The Game
Extend the Gameboard class to play a simple game with the game board we have created. Add:
• Static variables to define the four possible directions. You can set these to whatever values you like:
o public static final int UP
o public static final int DOWN
o public static final int LEFT
o public static final int RIGHT
• Two boolean instance variables: one indicating whether or not the game is over, and one indicating whether
or not the player has won the game. Add accessor methods getWon() and getDone() for these instance
variables.
• void doRound(int): This method contains all the logic to control one move in the game. The parameter
specifies the direction of the move: up, down, left or right. This will be a fairly large method.
o If the player tries to move into a wall, the player should not move.
o If the player moves into an empty space, the player should move to that space.
o If the player moves onto a space where there is an Item, call getEffect() on the item, and change
the user’s hit points appropriately with changeHP(). If the item is the Amulet of Yendor (Y), the game
is won. Set the boolean variables appropriately.
o If the player attempts to move into a space occupied by a different combatant:
▪ The player attacks that combatant. Use doAttack() to generate how many hit points the
attack removes from the combatant. If the other combatant is reduced to 0 or fewer hit
points, that combatant is removed from the board, and the player moves into that square.
▪ If the combatant is not at 0 or fewer hit points, the player does not move, and the combatant
attacks back, reducing the health of the player. If the player is reduced to 0 or fewer hit
points, the player dies and the game is over.
▪ Print out to the console the number of hit points both combatants have after the attacks are
complete.
▪ Print out to the console “[enemy type] is vanquished!” when a combatant is reduced to 0 or
fewer hit points.
You can test your class with TestPhase6.java. Sample output is shown below, which shows fighting a combatant,
and setting off a trap.
Welcome to NetHack, 1020 edition.
Health: 100
#############
#^Y.t…….#
#^h..T..^.^t#
#.h..h…..@#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
u
Player attacks the Troll for 6
Troll attacks the player for 3
Player health:97 Troll health 9
Health: 97
#############
#^Y.t…….#
#^h..T..^.^t#
#.h..h…..@#
#############
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
Which way would you like to move?
Valid commands are up, down, left, right.
u
Player attacks the Troll for 8
Troll attacks the player for 4
Player health:93 Troll health 1
Health: 93
#############
#^Y.t…….#
#^h..T..^.^t#
#.h..h…..@#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
u
Player attacks the Troll for 5
Troll is vanquished!
Health: 93
#############
#^Y.t…….#
#^h..T..^.^@#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
You set off a trap!
Health: 88
#############
#^Y.t…….#
#^h..T..^.@.#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
u
Health: 88
#############
#^Y.t…..@.#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Health: 88
#############
#^Y.t….@..#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
Valid commands are up, down, left, right.
l
Health: 88
#############
#^Y.t…@…#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Health: 88
#############
#^Y.t..@….#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Health: 88
#############
#^Y.t.@…..#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Health: 88
#############
#^Y.t@……#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Player attacks the Troll for 6
Troll attacks the player for 5
Player health:83 Troll health 9
Health: 83
#############
#^Y.t@……#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Player attacks the Troll for 6
Troll attacks the player for 2
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
Player health:81 Troll health 3
Health: 81
#############
#^Y.t@……#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Player attacks the Troll for 7
Troll is vanquished!
Health: 81
#############
#^Y.@…….#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
Health: 81
#############
#^Y.@…….#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
Health: 81
#############
#^Y@……..#
#^h..T..^…#
#.h..h……#
#############
Which way would you like to move?
Valid commands are up, down, left, right.
l
You picked up a The Amulet of Yendor!
You win!
Hand in
Submit your fifteen Java files.
1. Amulet.java
2. Combatant.java
3. Content.java
4. Gameboard.java
5. GreaterTroll.java
6. HealthPotion.java
ASSIGNMENT 3: Object-Oriented Programming, Inheritance and Polymorphism
7. Item.java
8. OpenSpace.java
9. Player.java
10. Tile.java
11. Trap.java
12. Troll.java
13. Wall.java
14. The enemy you created
15. The subclass of the enemy you created
Do not submit .class or .java~ files! Do not submit a .zip file! You do not need to submit the TestPhaseN.java files
that were given to you. If you did not complete all five phases of the assignment, use the Comments field when you
hand in the assignment to tell the marker which phases were completed, so that only the appropriate tests can be
run. For example, if you say that you completed Phases 1-2, then the marker will compile your files, and compile and
run the tests for phases 1 and 2. If it fails to compile and run, you will lose all of the marks for the test runs. The
marker will not try to run anything else, and will not edit your files in any way. (Make sure none of your files specify a
package at the top!)
COMP 1020 ASSIGNMENT 4: Introduction to Object-Oriented Programming
Assignment overview
In this assignment, you will receive two template files, in which you will implement a set of methods. The two template
files, that you will modify are:
Node: A node of a LinkedList, containing some data (stored as an Object) and a reference to the next link (a
Node).
LinkedList: A class representing a LinkedList of Nodes. It has a reference to the first Node of the list (top).
Keep all of your methods short and simple. In a properly-written object-oriented program, the work is distributed among
many small methods, which call each other. Most methods in this entire assignment require no more than 10-12 lines
of code, not counting comments, blank lines, or {} lines. The swap method (Phase 5) is the only exception (this one might
require about 30 lines of code).
Unless specified otherwise, all instance variables must be private, and all interface methods should be public. Helper
methods (not supposed to be used by outside code) should normally be private. Since this assignment will be using a
lot of recursion, and since recursive methods often need extra parameters, we will often implement a public interface
method, which is meant to be used by outside code, and its only role will be to call the private recursive version of
the method with appropriate parameters.
Testing Your Coding
We have provided sample test files for each phase to help you see if your code is working according to the assignment
specifications. These files are starting points for testing your code. Part of developing your skills as a programmer is to
think through additional important test cases and to write your own code to test these cases. For marking, we will use
longer and more comprehensive tests.
Phase 1: add and toString
Implement these methods in the LinkedList class:
The add(Object data) method:
This method is the public interface to add a new piece of data at the end of the list.
This method will call the addRec method defined below, with appropriate parameters.
ASSIGNMENT 4: Introduction to Object-Oriented Programming
COMP 1020
Page 2 of 4
The addRec(Node start, Node newNode) method:
This method is the private recursive method used internally only.
It will use recursive calls (to itself) to move to the end of the list, and add the newNode at the end of the list.
The String toString() method:
This method is the public interface to return a String representation of the list.
This method will call the toStringRec method defined below, with appropriate parameters.
The String toStringRec([parameters of your choice]) method:
This method is the private recursive method used internally only.
It will use recursive calls (to itself) to move through the list, and build a String representation of the list.
The resulting String will have each data from each Node on a separate line (see example below for an example).
You can test your code using the supplied test program TestingPhase1.java. You should get the output shown
below.
Hello
World
1
2
3
Phase 2: Factory method to build a LinkedList from a file
Implement this method in the LinkedList class:
The LinkedList createLinkedList(String filename) method:
This is a public factory method that builds and returns a new LinkedList.
This is the only method of this assignment in which loops are allowed.
This method must open the file corresponding to the filename parameter, read it and build the corresponding
LinkedList.
You can assume that there is only one token (representing the data to be stored in a Node of the LinkedList)
on each line in the file.
Tokens that are convertible to Integers, must be stored in the list as Integers.
Tokens that are not convertible to Integers, must be stored in the list as Strings.
This method must handle the exceptions related to reading a file internally (do not add a throws statement at
the end of the signature of this method).
You can test your code with TestingPhase2.java. The output should be equivalent to the text in the three
supplied files: list1.txt, list2.txt and list3.txt.
Phase 3: Sum
Implement these methods in the LinkedList class:
The int getSum() method:
This method is the public interface to return an int representing the sum of all data in the list (see description
of the next method for details).
This method will call the getSumRec method defined below, with appropriate parameters.
The int getSumRec([parameters of your choice]) method:
This method is the private recursive method used internally only.
ASSIGNMENT 4: Introduction to Object-Oriented Programming
It will use recursive calls (to itself) to move through the list, and calculate the sum of the data of all Nodes of
the list.
For each Node, if the data is an Integer, it considers the value of the int and adds it to the sum.
If the data is a String, it counts the number of characters in the String and adds it to the sum.
If the data is any other kind of Object (not an Integer, not a String), it simply adds 0 to the current sum.
You can test your code with TestingPhase3.java. The output of this code tells you what values are expected.
Phase 4: compareTo and getSmallestNode
First, implement this method in the Node class:
The int compareTo(Node other) method:
This method is a traditional compareTo method, which will return an int that is either < 0, == 0 or > 0.
The data instance variable in each Node is going to be used to determine which Node is bigger than the other.
Since many different types of data can be contained in a Node, we will follow the following rules:
o Integer data is considered to be smaller than String data
o If the two Nodes being compared contain Integer data, the difference between them will be returned.
o If the two Nodes being compared contain String data, the alphabetical difference between them will
be returned (you can simply use compareTo of Strings).
o Any data that is not an Integer and not a String is considered to be bigger than Integers and Strings.
No difference needs to be calculated when dealing with those and no specific int value needs to be
returned as long as it is either a positive or negative number (you could use +1 or -1 for example). See
TestingPhase4.java for examples.
Second, implement this method in the LinkedList class:
The Node getSmallestNode(Node start, Node smallest)method:
This method is a public method that will also be recursive (no separate interface for this one).
It will use recursive calls (to itself) to move through the list, and find the smallest Node in the list, which will be
returned. The start Node represents where to start the search, and the smallest Node represents the
smallest Node found so far.
Using the compareTo method created previously in the Node class, this should be straightforward.
You can test your code with TestingPhase4.java. The output of this code tells you what values are expected.
Phase 5: getPreviousNode and swap
Implement these methods in the LinkedList class:
The Node getPreviousNode(Node toFind) method:
This method is the public interface to return a Node representing the node that comes right before the Node
toFind in the list (see description of the next method for details).
This method will call the getPreviousNodeRec method defined below, with appropriate parameters.
The Node getPreviousNodeRec([parameters of your choice]) method:
This method is the private recursive method used internally only.
It will use recursive calls (to itself) to move through the list, and find and return the Node that immediately
precedes the Node to find.
If the Node to find is the very first Node of the list, return null.
You can assume that the Node to find is always present, that no duplicates are in the list, and that we will never
call this method on an empty list.
ASSIGNMENT 4: Introduction to Object-Oriented Programming
The swap(Node n1, Node n2) method:
This method is a public method that swaps two given Nodes in the list. Nothing needs to be returned.
You have to swap the entire Nodes, not just the data (you are not allowed to add a mutator in the Node class
for the data).
You can assume that Nodes n1 and n2 are going to be different.
Using the getPreviousNode method might be useful.
This is the most complex method of the assignment (it could take up to about 30 lines of code). Make sure to
think about all the links that must be modified in order to have a successful swap that will preserve the integrity
of the list. Make sure to also think about all the special cases that could arise.
You can test your code with TestingPhase5.java. The output of this code should allow you to see if everything
worked correctly.
Phase 6: Bonus phase (+20% bonus)
If you are completing this bonus phase, you must mention it when submitting your assignment in the dropbox using the
comments field. This bonus phase will not be evaluated if you do not specify, in the UMLearn dropbox, that you
completed it.
Implement these methods in the LinkedList class (if recursion is not used as described below, you will not get the bonus
points):
The selectionSort() method:
This method is the public interface to sort the list using a selection sort algorithm, as seen in class.
This method will call the selectionSortRec() method defined below, with appropriate parameters.
The selectionSortRec([parameters of your choice]) method:
This method is the private recursive method used internally only.
It will use recursive calls (to itself) to move through the list, and sort it in place using a selection sort algorithm.
The same rules defined in Phase 4 are to be used to order the Nodes.
You can test your code with TestingPhase6.java. The output of this code should allow you to see if everything
worked correctly.
Hand in
Submit your four Java files (LinkedList.java and Node.java). Do not submit .class or .java~ files! You do not
need to submit the TestingPhaseN.java files that were given to you. If you did not complete all phases of the
assignment, use the Comments field when you hand in the assignment to tell the marker which phases were
completed, so that only the appropriate tests can be run. For example, if you say that you completed Phases 1-2, then
the marker will compile your files, and compile and run the tests for phases 1 and 2. If it fails to compile and run, you
will lose all of the marks for the test runs. The marker will not try to run anything else, and will not edit your files in
any way. Make sure none of your files specify a package at the top!


