CS 211, 004/006
Project 4
due Tuesday, November 13th at 11:59pm


The objective of this project is to apply interfaces to design several classes which are similar in outward behavior but very different in nature. This project will involve implementing several different types of location (a location on a map, or in a room of a house, or abstractly inside a list).

Overview:

  1. Create the three primary interfaces used in this project, Named, Entity and Location. an entity can be moved around to different locations, while locations can be moved to and away from.
  2. Create an enumeration, Direction, which provides the four major compass directions.
  3. Create the class MovingEntity, which is an entity which can move around to different locations and prints messages describing its progress.
  4. Create the location class MapLocation, which tracks an x, y coordinate pair as the entity moves around a map.
  5. Create an EnterableArray class, which is a glorified ArrayList which can be treated as a location.
  6. Create a Room class, which represents a room in a house. A number of entities can move around the house at the same time.
  7. Document all public methods, classes, interfaces and enumerations using JavaDoc style comments.
We often run into situations where we can think of a lot of different things which behave in a very similar way at some level, but which are in fact very different in nature. Consider a location - something which you can go to or leave. The idea is a simple one, but it can apply to many different types of things. From where you are inside your home, to coordinates on a GPS map, to a spot on a game board. For these situations, it may make sense to use interfaces. Interfaces allow us to preserve some level of compatibility between different objects, without constraining them to be too similar. We may even want to derive from different existing classes, which would preclude us from using most other approaches besides interfaces.

In this project, we create two related interfaces, representing entities and locations, and use them to produce several different types of location-based classes.

Rules

  1. This project is an individual effort; the Honor Code applies
  2. You may import any standard Java library if you see the need.
  3. The main method will not be tested; you may use it any way you want.
  4. All fields must be declared private or protected. This will be verified manually.
  5. You may write your own helper methods, but any methods which are specifically asked for must match exactly (i.e. capitalization of the method name; number and order of the parameters).
  6. Any class, interface, and enumeration, as well as any public method, must be documented using JavaDoc style of comments.
Named: (5p)
public interface Named

The Named interface consists of objects which have been given a name. It is comprised of one single method,

Entity: (5p)
public interface Entity extends Named

An Entity is something which can move around from place to place. It has a name which it has inherited from Named. In normal usage, setting a location would first involve calling setLocation with null (in order to leave the previous location), and then immediately set location again with the new location.

Notice how Entity has a couple of methods which have Location as a parameter or return type? It's ok for two interfaces to depend on one another.

Location: (5p)
public interface Location extends Named

A location has a name, but it can also be entered or left by an Entity. Furthermore, it can have a set of neighbors, which can be returned as a list.

Direction: (10p)
public enum Direction

This is an enumeration which represents the four compass directions, north, south, east, and west. The actual members of the enumeration will be N, S, E, and W (in that order), but they will each have an overridden toString() method which holds the string values "north", "south", "east", and "west".

MovingEntity: (15p)
public class MovingEntity implements Entity

Now we actually implement our entity, an actor which moves around to different locations. This entity has a name and a location (the location may be null if it isn't anywhere at the moment). The entity also has the capability to move from one place to another, see what its neighbors are. It is also a talkative entity, so whenever it moves to another place, it will announce the fact, by printing to system output.

A MovingEntity relies on the setLocation() method to update its knowledge about its current location. The method spec warns that doing this incorrectly can result in an infinite loop. How is an infinite loop possible? When we enter(e) or leave(e) a new location, it is responsible for notifying the entity (using a call to setLocation(loc)) of its new location information. Meanwhile, when an entity's location is updated using setLocation(loc)it may be required to leave(e) an old location during the call. The fact that leave may call setLocation and setLocation may call leave creates a potential for a loop. However, when leave calls setLocation, the location passed is null. You can use this fact to help avoid calling back and forth forever.

MapLocation: (15p)
public class MapLocation implements Location

This is a location on a map, expressed as a 2D pair of integer coordinates, x and y. If you begin at position (0, 0) in the map, then moving north would take you to (0, 1), east would take you to (1, 0), etc. Each set of coordinates is its own location, and there can be any number of coordinates, so don't rely on pre-allocating all possible coordinates.

EnterableArray: (15p)
public class EnterableArray extends ArrayList<Entity> implements Location

Here we start to see why it makes sense for Location to be an interface. An EnterableArray is just an ArrayList of Entity elements, but a list is a place where an element can go, so it's possible to treat it as a location. This class just extends the ArrayList class by adding the necessary methods which will make it behave like a Location. Since we've already chosen a base class, we wouldn't be able to do this without using an interface.

Room: (15p)
public class Room implements Location

A Room is a room in a house or a building. It has a name, and it has a list of people who occupy it (hint: would inheriting from an EnterableArray be useful here?). Furthermore, it has a list of links to all of the other rooms which it is connected to (hint: another ArrayList?). Moving from one room to another would typically involve picking from the neightboring rooms. The entity which leaves a room is no longer part of the list of people in that room, and is now part of the list of people in the new room.

JavaDoc: (15p)
All of your public methods, classes, interfaces, and enumerations must be documented using JavaDoc-style comments. This includes declaring method parameters and return types.

Testing:

Download and use the following to test your code (in addition to the tester jar which you already have):

Example runs:

Move using MapLocation directions.

> MovingEntity ent = new MovingEntity("nobody");
> ent.getNeighbors()
{ }
> MapLocation map = new MapLocation(0, 0)
> map.enter(ent);
nobody moves to (0, 0)
> ent.getNeighbors()
{ (0, 1), (0, -1), (1, 0), (-1, 0) }
> ent.move(Direction.N);
nobody goes north
nobody moves to (0, 1)
> ent.move(Direction.N);
nobody goes north
nobody moves to (0, 2)
> ent.move(Direction.E);
nobody goes east
nobody moves to (1, 2)
> ent.move(Direction.S);
nobody goes south
nobody moves to (1, 1)
> ent.move(Direction.W);
nobody goes west
nobody moves to (0, 1)
> ent.move(Direction.W);
nobody goes west
nobody moves to (-1, 1)

Example of using an EnterableList:

> MovingEntity a1 = new MovingEntity("actor 1");
> MovingEntity a2 = new MovingEntity("actor 2");
> MovingEntity a3 = new MovingEntity("actor 3");
> EnterableArray elist = new EnterableArray();
> elist.enter(a1);
actor 1 moves to EnterableArray
> elist.enter(a2);
actor 2 moves to EnterableArray
> elist.enter(a3);
actor 3 moves to EnterableArray

Example of moving using Room lists:

> MovingEntity a1 = new MovingEntity("actor 1");
> MovingEntity a2 = new MovingEntity("actor 2");
> MovingEntity a3 = new MovingEntity("actor 3");
> Room r1 = new Room("Room 1");
> Room r2 = new Room("Room 2");
> Room r3 = new Room("Room 3");
> Room.link(r1,r2);
> Room.link(r2,r3);
> Room.link(r3,r1);
> r1.enter(a1);
actor 1 moves to Room 1
Room 1 now contains [actor 1]
> r2.enter(a2);
actor 2 moves to Room 2
Room 2 now contains [actor 2]
> r3.enter(a3);
actor 3 moves to Room 3
Room 3 now contains [actor 3]
> a1.getNeighbors() // note that Room.toString() prints its entity list rather than its name; because of this, it looks like it's printing actors when it is really printing rooms.
{ [actor 2], [actor 3] }
> a1.move(0);
actor 1 moves to Room 2
Room 2 now contains [actor 2, actor 1]
> a2.move(1);
actor 2 moves to Room 3
Room 3 now contains [actor 3, actor 2]
> a1.move(1);
actor 1 moves to Room 3
Room 3 now contains [actor 3, actor 2, actor 1]
> a3.move(0);
actor 3 moves to Room 2
Room 2 now contains [actor 3]

Grading:

The implementation of each class carries the weight mentioned in each part above. Partial credit is possible, but hard-coding to avoid test cases will receive an automatic zero on the manual inspection points. Programs which do not compile without modification will receive a zero in most cases.

Submission:

Submission instructions are as follows.

  1. Let xxx be your lab section number (one of 213-220), and let yyyyyyyy be your GMU userid. Your userid is your patriot pass login name, not your G number. Create the directory xxx_yyyyyyyy_P4/
  2. Place the eight files corresponding to the 8 classes/interfaces you've written in the directory you've just created.
  3. Create the file ID.txt in the format shown below, containing your name, userid, G#, lecture section and lab section, and add it to the directory. Your directory should contain nine files total.

    Full Name: Donald Knuth
    userID: dknuth
    G#: 00123456
    Lecture section: 004
    Lab section: 213

  4. compress the folder and its contents into a .zip file, and upload the file to Blackboard.