/** * * Applet Life * * */ import java.awt.*; import java.applet.Applet; public class Life extends Applet implements Runnable { static final int W = 45; static final int H = 30; static final int DX = 10; static final int DY = 10; static final int MARGIN = 5; static final int HSKIP = 5; static final int VSKIP = 5; static final int BUTTONH = 20; static final int BUTTONW = 80; static final long DT = 500; Color fg = Color.blue; Color bg = Color.lightGray; Button stepButton; Button startButton; Button stopButton; Button eraseButton; byte[][] a0 = new byte[W][H]; byte[][] a1 = new byte[W][H]; byte[][] a = a0; // Matrix on current step byte[][] n = a1; // Matrix on next step Thread lifeThread; boolean terminate = false; public void init() { requestFocus(); setBackground(bg); setFont(new Font("TimesRoman", Font.BOLD, 14)); setLayout(null); stepButton = new Button("Step"); add(stepButton); int y = MARGIN + DY * H + VSKIP; int x = MARGIN; stepButton.reshape(x, y, BUTTONW, BUTTONH); x += BUTTONW + HSKIP; startButton = new Button("Start"); add(startButton); startButton.reshape(x, y, BUTTONW, BUTTONH); x += BUTTONW + HSKIP; stopButton = new Button("Stop"); add(stopButton); stopButton.reshape(x, y, BUTTONW, BUTTONH); x += BUTTONW + HSKIP; eraseButton = new Button("Erase"); add(eraseButton); eraseButton.reshape(x, y, BUTTONW, BUTTONH); x += BUTTONW + HSKIP; for (int i = 0; i < W; i++) { for (int j = 0; j < H; j++) { a[i][j] = 0; } } // Planer // * // * // *** // a[6][5] = 1; // a[7][6] = 1; // a[5][7] = 1; // a[6][7] = 1; // a[7][7] = 1; // S-pentamino // ** // ** // * a[5][5] = 1; a[6][5] = 1; a[6][6] = 1; a[6][7] = 1; a[7][6] = 1; stepButton.enable(true); startButton.enable(true); stopButton.enable(false); eraseButton.enable(true); } public boolean mouseDown(Event evt, int x, int y) { if (lifeThread != null) return false; int i; int j; i = (x - MARGIN) / DX; j = (y - MARGIN) / DY; if (0 <= i && i < W && 0 <= j && j < H) { if ((evt.modifiers & Event.META_MASK) != 0) { // Right button a[i][j] = (byte)0; } else if ((evt.modifiers & Event.ALT_MASK) != 0) { // Middle button a[i][j] = (byte)(1 - a[i][j]); } else { // Left button a[i][j] = (byte)1; } repaintCell(i, j); return true; } return false; } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.setColor(Color.blue); g.drawRect(MARGIN, MARGIN, W * DX, H * DY); for (int x = 0; x < W; x++) { int left = MARGIN + DX * x + 1; for (int y = 0; y < H; y++) { int top = MARGIN + DY * y + 1; if (a[x][y] != 0) { g.setColor(fg); g.fillOval(left + 1, top + 1, DX - 3, DY - 3); } else { g.setColor(bg); g.fillRect(left, top, DX - 1, DY - 1); } } } } void repaintCell(int x, int y) { repaint(DT - 10, MARGIN + x * DX, MARGIN + y * DY, DX + 1, DY + 1); } synchronized void onStep() { // System.out.println("Step"); byte[][] n = new byte[W][H]; int sum = 0; for (int x = 0; x < W; x++) { for (int y = 0; y < H; y++) { int k = numNeibours(x, y); if (k <= 1) { n[x][y] = 0; } else if (k == 2) { n[x][y] = a[x][y]; } else if (k == 3) { n[x][y] = 1; } else { n[x][y] = 0; } // if (n[x][y] != a[x][y]) repaintCell(x, y); sum += k; } } // Swap two matrices byte[][] tmp = n; a = n; n = tmp; if (sum == 0) { terminate = true; } a = n; repaint(DT - 10); } int numNeibours(int x, int y) { int x0 = x - 1; if (x0 < 0) x0 = W - 1; int x1 = x + 1; if (x1 >= W) x1 = 0; int y0 = y - 1; if (y0 < 0) y0 = H - 1; int y1 = y + 1; if (y1 >= H) y1 = 0; int n = 0; if (a[x0][y0] == 1) n++; if (a[x0][y] == 1) n++; if (a[x0][y1] == 1) n++; if (a[x][y0] == 1) n++; if (a[x][y1] == 1) n++; if (a[x1][y0] == 1) n++; if (a[x1][y] == 1) n++; if (a[x1][y1] == 1) n++; return n; } void onStart() { // System.out.println("Start"); stepButton.enable(false); startButton.enable(false); stopButton.enable(true); eraseButton.enable(false); if (lifeThread != null) return; terminate = false; lifeThread = new Thread(this, "lifeThread"); lifeThread.start(); } void onStop() { terminate = true; } synchronized void onErase() { for (int x = 0; x < W; x++) { for (int y = 0; y < H; y++) { a[x][y] = 0; } } repaint(); } public void stop() { onStop(); } public boolean action(Event e, Object arg) { Object source = e.target; requestFocus(); if (source == startButton) { onStart(); } else if (source == stopButton) { onStop(); } else if (source == stepButton) { onStep(); } else if (source == eraseButton) { onErase(); } else { return true; } return false; } public void run() { while (!terminate) { onStep(); try { lifeThread.sleep(DT); } catch (InterruptedException e) { } } lifeThread = null; stepButton.enable(true); startButton.enable(true); stopButton.enable(false); eraseButton.enable(true); } public static void main(String[] args) { class MyFrame extends Frame { MyFrame(String headline) { super(headline); } public boolean action(Event e, Object arg) { if (e.target instanceof MenuItem) { // We have only one "Quit" menu item... System.exit(0); } return false; } public boolean handleEvent(Event e) { if (e.id == Event.WINDOW_DESTROY) { System.exit(0); } return super.handleEvent(e); } }; Frame f = new MyFrame("Python"); f.setFont(new Font("Helvetica", Font.PLAIN, 14)); MenuBar mb = new MenuBar(); f.setMenuBar(mb); Menu fileMenu = new Menu("File"); fileMenu.add(new MenuItem("Quit")); mb.add(fileMenu); f.resize( 2*MARGIN + W * DX + 16, // ??? 2*MARGIN + H * DY + VSKIP + BUTTONH + 24 // ??? + 36 // Menu bar width ); Life l = new Life(); f.add("Center", l); l.init(); l.start(); f.show(); } }