Originally posted 11 October 2012, due at 11:59 p.m. EDT on
Wednesday 24 October 2012,
by placing .java files in a subdirectory of your cs187 directory on
your edlab account, called
For more information on accessing the edlab, see
here or ask in discussion
Some updates in purple on 12 October 2012.
Some more updates in brown on 12 October 2012.
The class you construct should be named
Continent, because that name is just too
Some more changes on 19 October 2012. Note that the q and a page now has something on it. (Link fixed 21 October)
MAJOR change on 21 October: I am redefining
#3, still due on Wednesday, to include only the first task
continentMap method. The other tasks will form
part of Project #4, to be due on Monday 5 November. Also, a
grading driver is now available.
Goals of this project:
Questions and answers about this project are collected here.
In Section 4.4, DJW present code for a class called
Grid object has a two-dimensional array of booleans. You
can download their code from their course website by following the
instructions on page 28.
define a blob as a set of grid cells such that from any cell in the
blob, you may travel to any other cell in the blob but to no cell not
in the blob. Here "travel" means to take a sequence of moves each directly
north, south, east, or west, and use only cells in which the grid's boolean
true. Note that diagonal moves are not allowed.
Because I am a fan of the Civilization family of computer games, I
prefer to call the
true cells land cells, the
false cells water cells, and the "blobs" continents.
So in my terminology, their method
countBlobs determines how
many continents are on the map, and their method
all the cells on the continent of the cell given by its parameters.
All of your code will be in a class called
will extend the class
Grid. So all the DJW code for
Grid should be in your edlab directory or somewhere else where it
can be found from your edlab directory.
As explained in Lecture 15, we want you
to write a new constructor for
which will mimic their
Grid except for one thing -- it will have an additional
int parameter called
seed, and will create its
object with that seed instead of without a parameter. This will allow us to
test your program on maps that are randomly generated using seeds of our choice,
making grading easier. (It is too bad that we have to repeat the code instead
of just calling it, but their code is insufficiently flexible for that.)
Your first and easier task is to alter their code so that instead of just
counting the continents, it names them and is able to return a string that
denotes the map with the continents' names. For consistency, we will insist
that the first continent be named
'A', the second
'Z', the 27th
'[', the 33rd
'a', and so on. If the name
char and we have an array indexed by the continents, then
the name of continent
i is given by the Java expression
'A' + i. (Don't use
or it will interpret the
addition as concatenation.)
You should write a method
continentMap( ) that returns a
String that has a line for each row of the map, a hyphen for each
water square, and a letter denoting the continent name for each land square,
A-A--B--C-- AAA--B----- --AA-B----- -----BB---- ----D---EEE
Note that you should number the continents in the order that you encounter them, going row by row and going left to right in each row.
This first task will make use of
There will be partial credit for carrying out
this first task -- you are probably best off doing it and testing it
first before starting on the second task.
markBlob, or something like it, to identify all the cells
in a continent when you first encounter the continent. Unfortunately
markBlob private rather than protected. You may
fix this in
Grid (as we will grade your work using the
Grid that is in your directory), or you may
write a new version of
markBlob to go in
There will be partial credit for carrying out this first task -- you are probably best off doing it and testing it first before starting on the second task.
Your second task is where you will use queues. The distance between two land squares (if it exists) is the length of the shortest path from one to the other, using only north-east-south-west moves on land squares. We want to find the best cell for a capital of each continent. A cell makes a better capital the more centrally located it is -- we define the centrality of a cell to be the largest distance from that cell to any other on its continent, and we want the capital to be a cell with minumum centrality.
In our example above, continent
A has two
cells that are within three steps of any other cell on the continent --
the second and third cell in the second row. No cell has every other
cell within two steps, so these are the two candidate capitals. We
want you to choose the first candidate with the best centrality.
That is, you test the longest distance for every cell, and move the capital
only when you find a candidate with strictly smaller longest distance.
In our example, the
A capital would be the second cell in
the second row. The
B capital would be the
in the third row. The
C capital is of course the only
c cell, and likewise the
D capital. Finally the
E capital is the middle of that continent's three cells.
You should have a method
capitalMap that returns a
I don't mind that the distinction between continents
D is obscured on the map -- small continents
have to live with that sort of thing.
You should also write a method
continentTable( ) that
returns a String that is
a table like the following:
Continent Capital Centrality A 1,1 3 B 2,5 2 C 0,8 0 D 4,4 0 E 4,9 1
Of course to make these output methods work you are going to want to give each grid a field that keeps track of the continents, probably in the same format as the continent table.
How do we compute the centrality of a cell? The easiest way to do this is
somewhat similar to the
markBlob method, in that we "mark" all the
cells on the continent. But instead of the stack implicit in the recursion
markBlob, we'll use a queue. As we'll see in Chapter
5 of DJW and starting in Lecture 17, a queue
is a data structure that holds objects, can accept new objects that are
enqueued, and can dequeue the object they have been holding the
We will make a queue of
Move objects from
Project #2. When we start our search from cell (i,j),
we will visit all the cells on (i,j)'s continent and enqueue a
Move for each cell as we visit it. This
row for the row number of
the cell we are visiting,
col for the column number of the cell
we are visiting, and
dist for this cell's distance from (i,j).
markBlob, we will mark each cell as
when we encounter it. The key fact is this: if we are looking at a cell with
distance d, and we see an unseen land neighbor of this cell, then it has
distance d+1. We begin by putting (i,j) on the queue with distance 0.
We then dequeue the oldest element in the queue, which is (i,j) because it's
the only element. We look for all the unseen land neighbors of (i,j) and
enqueue each of them with distance 1. Then we dequeue one of them (it doesn't
really matter which) and enqueue its unseen land neighbors with distance
2. We continue in this way until the queue is empty -- when it is, the
centrality of (i,j) is the distance of the last
Move that we
You should put your classes in your EdLab space, in a directory called "cs187/proj3", and test the behavior with a main method or a driver class. (We will test the code with our own driver class.)
If you create your code within Eclipse (which we encourage but don't require), you will want to ignore the warning message that says "The use of the default package is discouraged". Bear in mind that if you make the mistake of declaring your class in a package, our driver class will not see it (since it will not be in a package) and we won't be able to test your code.
Last modified 21 October 2012