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).
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. 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.