Conway's Game of Life V1.0 by Mihailo Despotovic, Feb 2011

The original Java applet and its page, 2 files
Life.html
<html>
<head>
    <title>Life by Mihailo Despotovic</title>
</head>
<body bgcolor=black>
<p align=center>
    <applet code=mihailo.life.LifeApplet.class width=1000 height=600></applet>
</p>
</body>
</html>
mihailo/life/LifeApplet.java
package mihailo.life;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;

/**
 * Created by mihailod, Feb 15, 2011, 7:24:14 PM
 */
public class LifeApplet extends Applet implements ActionListener {

    private static final boolean PROFILING = false;

    private static final double THRESHOLD = 0.925;

    private static final int W = 500; // map width
    private static final int H = 350; // map height
    private static final int M = 2; // pixel size multiplier

    private static Image buffer = null;
    private static Graphics bg = null;

    private static boolean running = false;

    private final Button seedButton = new Button("Seed");
    private final Button startButton = new Button("Start");
    private final Button nextButton = new Button("Next");
    private final Button stopButton = new Button("Stop");
    private static final Panel p = new Panel();

    private static byte a[][] = new byte[W][H]; // current generation

    // profiling 1500 x 1000 ~ 21ms
    private long average = 0;
    private long count = 0;
    private long time = 0;

    public void init() {
        final Frame f = new Frame("Conway's Game of Life V1.0 by Mihailo Despotovic");
        f.addWindowListener(new WindowListener() {
            public void windowOpened(WindowEvent windowEvent) { repaint(); }
            public void windowClosing(WindowEvent we) { buffer = null; f.dispose(); }
            public void windowClosed(WindowEvent windowEvent) { repaint(); }
            public void windowIconified(WindowEvent windowEvent) { repaint(); }
            public void windowDeiconified(WindowEvent windowEvent) { repaint(); }
            public void windowActivated(WindowEvent windowEvent) { repaint(); }
            public void windowDeactivated(WindowEvent windowEvent) { repaint(); }
        });
        f.addComponentListener(new ComponentListener() {
            public void componentResized(ComponentEvent componentEvent) { repaint(); }
            public void componentMoved(ComponentEvent componentEvent) { repaint(); }
            public void componentShown(ComponentEvent componentEvent) { repaint(); }
            public void componentHidden(ComponentEvent componentEvent) { repaint(); }
        });

        buffer = createImage(W * M, H * M);
        bg = buffer.getGraphics();

        final Panel buttonPanel = new Panel();
        buttonPanel.setLayout(new FlowLayout());
        buttonPanel.add(seedButton);
        buttonPanel.add(startButton);
        buttonPanel.add(nextButton);
        buttonPanel.add(stopButton);
        seedButton.addActionListener(this);
        startButton.addActionListener(this);
        nextButton.addActionListener(this);
        stopButton.addActionListener(this);
        f.setLayout(new BorderLayout());        
        f.add(buttonPanel, BorderLayout.SOUTH);
        f.add(p, BorderLayout.CENTER);
        
        seed();
        final Thread d = new Thread(new Drawer()); d.start();
        f.setBounds(50, 50, W * M, H * M + 60);
        f.setVisible(true);
        updateButtons();
    }

    public void actionPerformed(ActionEvent ae) {
        final String ac = ae.getActionCommand();
        if (ac.equals("Seed")) {
            seed();
        } else if (ac.equals("Start")) {
            running = true;
        } else if (ac.equals("Next")) {
            next();
        } else if (ac.equals("Stop")) {
            running = false;
            if (PROFILING) {
                System.out.println("Average: " + average);
            }
        }
        updateButtons();
    }

    private void updateButtons() {
        startButton.setEnabled(!running);
        nextButton.setEnabled(!running);
        stopButton.setEnabled(running);
        seedButton.setEnabled(!running);
        repaint();
    }

    private void next() {
        calculateNextGeneration();
    }

    public void update(Graphics g) {
        bg.setColor(Color.WHITE);
        bg.fillRect(0, 0, W*M, H*M);
        bg.setColor(Color.BLACK);
        for (int i=0; i<W; i++) {
            for (int j=0; j<H; j++) {
                if (a[i][j] == 1) {
                    bg.fillRect(i*M, j*M, M, M);
                }
            }
        }
        if (p.getGraphics() != null) {
            p.getGraphics().drawImage(buffer, 0, 0, null);
        }
    }

    private void seed() {
        a = new byte[W][H];
        for (int i=0; i<W; i++) {
            for (int j=0; j<H; j++) {
                a[i][j] = Math.random() > THRESHOLD ? (byte)1 : 0;
            }
        }
    }

    private void calculateNextGeneration() {
        final long start = System.currentTimeMillis();
        final byte b[][] = new byte[W][H];
        for (int i=0; i<W; i++) {
            for (int j = 0; j<H; j++) {
                int count = count(i, j);
                if (a[i][j] == 1) { // alive cell
                    if (count != 2 && count != 3) {
                        b[i][j] = 0; // dies (<2 = starving, >3 = overpopulation)
                    } else {
                        b[i][j] = 1; // otherwise, stays alive
                    }
                } else { // dead cell
                    if (count == 3) {
                        b[i][j] = 1; // becomes alive if 3 neighbours (reproduction)
                    } else {
                        b[i][j] = 0; // otherwise, stays dead
                    }
                }
            }
        }
        System.arraycopy(b, 0, a, 0, W);
        count++;
        time+= System.currentTimeMillis() - start;
        average = time / count;
    }

    private int count(final int x, final int y) {
        int px = x - 1; if (px < 0)     px = W - 1;
        int py = y - 1; if (py < 0)     py = H - 1;
        int nx = x + 1; if (nx > W - 1) nx = 0;
        int ny = y + 1; if (ny > H - 1) ny = 0;
        return a[px][py] + a[ x][py] + a[nx][py] +
               a[px][ y] +           + a[nx][ y] +
               a[px][ny] + a[ x][ny] + a[nx][ny];
    }

    private class Drawer extends Thread {
        public void run() {
            while (true) {
                if (running) {
                    calculateNextGeneration();
                    repaint();
                }
                yield();
            }
        }
    }

    public void paint(Graphics g) {
        update(g);
    }
}