| It's time to pretty things up and add some frills to the
final version.
I've added one button to clear the array, and another to randomly set some cells. The logic for these buttons is simple. However, when I added the buttons to the NORTH part of my BorderLayout, I discovered that each button took up the whole area and covered the previous button. As a result, I had to make a Panel (with a default FlowLayout manager), add the buttons to the panel, and add the panel to the NORTH of the BorderLayout. I also added two TextField elements, one to control the size of the board and one to control the speed (time between steps), and also one Label element for each TextField, to say what it's for. One cosmetic flaw remains: when the size of the board is changed, the spaces between ovals aren't cleaned up properly. (It looks fine if you clear the board before changing the size.) Fixing this would be a simple matter of drawing a gray rectangle filling the canvas before redrawing it at the new size. |
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*; // needed for ActionListener
import java.util.*; // needed for Random
public class Life extends Applet
{
static int boardSize = 10;
Cell [][] board;
Cell [][] nextBoard;
TextField sizeField;
TextField speedField;
MyCanvas canvas;
SeparateSubTask subtask;
boolean running = false;
static Random rand = new Random ();
int speed = 5;
/**
* Creates an empty (all cells dead) playing board of the given boardSize.
*/
static Cell[][] emptyBoard (int boardSize)
{
Cell[][] result = new Cell[boardSize][boardSize];
for (int i = 0; i 50)
{
sizeField.setText ("" + boardSize);
return;
}
if (running) subtask.suspend ();
boardSize = newSize;
board = emptyBoard (boardSize);
canvas.board = board;
canvas.boardSize = boardSize;
canvas.paint (canvas.getGraphics ());
repaint ();
if (running) subtask.resume ();
}
}
class SpeedField implements ActionListener
{
public void actionPerformed (ActionEvent evt)
{
int newSpeed;
try { newSpeed = Integer.parseInt (evt.getActionCommand ()); }
catch (Exception e) { speedField.setText ("" + speed); return; }
if (newSpeed <1 || newSpeed> 100)
{
speedField.setText ("" + speed);
return;
}
speed = newSpeed;
}
}
class SeparateSubTask extends Thread
{
public void run ()
{
int numberOfNeighbors;
while (true)
{
nextBoard = emptyBoard (boardSize);
for (int i = 0; i limit) continue;
if (jj <0 || jj> limit) continue;
if (board[ii][jj].getAlive ()) count++;
}
return count;
}
}