This assignment
will lead you into the world of so called “Cellular Automata”. It's a big word
for a small idea, which, however is extremely powerful. I will not give a
general introduction, but a specific example – wireworld.
Imagine a grid of
cells (or call it a 2 dimensional array, a matrix, a bunch of boxes arranged in
a rectangle). Each of the cells can be in a so called state (or call it “can
have a value from a set of values”, “can have a color from a set of colors”).
In the following picture, The states are represented by colors. There are only
4 possible states, which I call “background” (black), “head” (red), “tail”
(blue), “wire” (white). Wire World is a simulation of an electric board, so the
board in this image might remind you of an electric board with wires:

So, we have
single cells on a grid, each cell can have a state from a limited set of states
(here: 4 states). We are already close to the definition of cellular automata.
The only thing missing is a set of rules, that change the state of the cells.
In cellular automata, you create “generations of cell-grids”, the transition
from one generation to the next is based on certain rules. These rules always
include the local change of state of a single cell, depending on the states of
the neighboring cells.
Wire World has an
impressively simple set of rules:
·
if a cell is in state 0 (background), it will stay in state 0
(background)
·
if a cell is in state 1 (head), it will change to state 2 (tail)
·
if a cell is in state 2 (tail), it will change to state 3 (wire)
·
the interesting one: if a cell is in state 3 (wire), it will
change to head if there are 1 or 2 of the 8 neighbors in state “head”,
otherwise it will change stay in state wire.
So the cellular
automaton “Wire World” does the following:
Look at a
2-dimensional array. This is called the n-th
generation. Create a new 2D array, the (n+1) generation. For every cell in of
the n-th generation, apply the rules above, and store
the result in the corresponding cell in the (n+1) generation. After this,
display the new generation, and proceed from generation (n+1) to (n+2) and so
on. Here are some images from Wire Word that will give you an idea of what's
happening (left to right: generation 0, generation1, generation 2, generation
3).

If you look at
this figure, it seems that the read head and the blue tail are moving (and
splitting). This is an interesting illusion. What happened from generation 0 to
generation 1 is the following: The blue cell turned white (according to the
rule “tale becomes wire”), the red cell turned blue (according to the rule
“head becomes tail”), and the white cell right of the red one turned red
(according to the rule “wire with one or two heads as neighbors becomes head”).
In short, only single cells were switched, simulating a movement on the grid
along the wire.
To give you an
even better idea, here is an executable java file, that you can start and play
around with. Unfortunately, I will only give you the .jar --- since that's the
program you should write (at least parts of it) ! Please play around with this
program. You can get more information about Wire World in the internet, google it (that’s part of the assignment).
Click here to play with Wire World.
Here is your
task: Program Wire World. You will be given a graphical grid-input editor. You
have to program the actual logic of the game, and an output grid that shows the
iterated generations.
You only need to
program a simple GUI, which, once the logic has started to work, shows the
output. No return to the editor has to be provided (in contrast, the .jar file
above does provide such a return to the editor, which demands for a slightly
more difficult code).
Don't panic, you
will be given some support. This is a project, which might look big at first,
but if you split up the programming task into small pieces, you will see that
it's entirely doable.
To make this program appear as simple as it actually is, let’s
break it down into tasks. These tasks will also define a basic skeleton that
suggest classes, methods etc.
(A) For
this, create a new Netbeans Project, and create a CellArray class that first has to provide the basic data
structure: a 2D array (please call it currentGeneration).
Size it reasonably, e.g. 64x64
(B) Import
the editor jar-file. The TA will tell you how. After that is done, you can just
call a method which will (1) open the graphical editor, and (2) on exit, will
copy its edited 2D array into the output array that is provided by you.
(C) Write
the GUI:
a. Extend
your class from JPanel
b. Create
a frame
c. Add
yourself to the frame
d. Override
the paintComponent(…) method. The paintComponent
method has to paint the grid. In order to do so, traverse the 2D array, look
which state each cell has (0,1,2,3), define a color accordingly, and draw a
filled rectangle at the corresponding position. Example: let’s say your loop is
at a position row=13, column = 27, and your graphical squares have an
edge-length of SIZE pixels. Check what’s the state of myArray[13][27].
Set the drawing color accordingly (…if state=… the g.setColor(…)
…). The graphical coordinates of the box depend on the index of the cell you
are examining. The coordinates are: x = column*size, here 27*SIZE; y =
row*SIZE, here 13*size.
e. TEST
your code so far: call the input editor, edit some input grid, click “DONE”,
and draw your own board. The board should show exactly the edited array, of
course!
(D) You
are half way through already, would you believe that? Go and get a coffee.
(E) Now
implement the game logic. In order to do so, you have to traverse through the
grid, look at the states of the cells (you did the same for the graphics
already, you might want to copy some lines from there), and implement the rules
based on the state of each cell. You have to be careful, there’s one tricky
thing here: the new generation MUST be a new array, you can
not copy the changes into the original array. So: create a “nextGeneration” 2D array. Traverse through the currentGeneration array, apply the rules, store the result
in the newGeneration array. Then, when that’s done,
make the currentGeneration array the newGeneration array (currentGeneration
= newGeneration, i.e. re-reference. Do NOT copy. Too
slow!). Visualize, re-compute the next generation and YOU ARE DONE. Yes, it is
that simple. As usual, there are some little details, so let’s get down to
them:
a. The
newGeneration array has to be of the same size as the
currentGeneration array.
b. Since
in the wire-rule, you have to check for neighbors, you do not want to traverse
the entire currentArray, but leave a margin of one
cell to all sides. That prevents out of boundary errors. So your loop should be
from 1 to NUMBEROFCOLUMNS-2 for columns, and from 1 to NUMBEROFROWS for rows.
Please notice, it’s from 1, not from 0!
c. First
implement the simple rules, which are the background, the head and the tail
rule. There’s no neighborhood check. It’s a simple “if tail in currentGeneration Array, then make it wire in nextGeneration array.” Etc.
d. Test
your logic with this subset of rules. The next generation should look like the
previous one, yet with “dying” heads and tails. They won’t move, since the
“wire” rule is still missing.
e. Implement
the “wire” rule. For this one, you have to check the neighbors of your current
cell. Write a simple method “public int checkNeighbors(int column, int row), that takes as input the indices of the currently
examined cell, and check the neighbors, which are the cells with index:
[column-1][row-1] for top left neighbor, [column][row-1] for top neighbor etc.
You have to check 8 neighbors. Check if they are “head”. If so, increase a
counter (which at the beginning of your method is initialized to 0). When you
are done with 8 neighbors, return the counter value.
f. Test
your program again. Now that all is implemented, it should behave like the
example .jar file.
(F) Be
proud. You are done.
Here is the jar file for the editor: WireWorld.jar
How to use it: copy wireworld.jar to your project folder. In netbeans, right click on your projects, select
'properties', select 'libraries'. That opens a window to import libraries.
Press the button "add Jar file". Select the 'wireworld.jar' file.
After you did these steps, you have to add " import
wireworld.*; " in your code. The class wireworld.jar contains a class
"BoardInput", which is the input-editor.
Just instantiate an object of this class, passing your 2D array to its
constructor (BoardInput b = new BoardInput(board)).
That will show the editor. When the editor finishes, its result is stored in
the array "board" that you passed to it.
This is a one week assignment. It will keep you busy, so start
immediately. Please enjoy, and take this seriously: start immediately. I
suggest you start right NOW.