Subway simulation

This program simulates a Subway car traveling from station to station. At each stop, the doors open and close. Click on a button to make the car stop there or wait for random stops to occur.

This program is both an Applet and an Application.

Java Web Start: Launch the Subway simulation by clicking here.

JWS Applet: Click here to view the Subway simulation as an Applet via Java Web Start.

Applet: Click here to view the Subway simulation as an Applet.

Download: Click here to download the jar file.

Verify: Check the certificate fingerprints.

MD5:  03:B0:20:7F:F5:F4:5A:84:6F:F9:C6:8F:32:5C:47:71

SHA1: 8F:1B:00:0C:6C:57:C1:88:D9:2E:66:24:F4:55:AD:37:F7:B8:DC:F1

See also these related Java Web Start documentation links.

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.*;

/** @author John B. Matthews; distribution per GNU Public License */
public class Subway extends JApplet {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                JFrame frame = new JFrame();
                frame.setTitle("Subway Simulation");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                initContainer(frame);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    // Common initialization for either JApplet or JFrame
    private static void initContainer(Container container) {
        ButtonPanel control = new ButtonPanel();
        SubwayPanel subway = new SubwayPanel(control);
        container.add(Box.createVerticalStrut(8), BorderLayout.NORTH);
        container.add(subway, BorderLayout.CENTER);
        container.add(control, BorderLayout.SOUTH);
        subway.beginOperation();
    }

    @Override
    public void init() {
        System.out.println("Initializing...");
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                initContainer(Subway.this);
            }
        });

    }

    @Override
    public void destroy() {
        System.out.println("That's all, folks...");
    }
}

class SubwayPanel extends JPanel implements ActionListener {

    public static final int MAX = 8; // Max stops
    private static final int DX = 4; // Initial velocity
    private static final int DOOR = 100; // Preferred width
    private int dx = DX;
    private int xx = 0;
    private int yy = 0;
    private Timer timer = new Timer(40, this); // ~25 Hz
    private ButtonPanel control;
    private boolean loading;

    public SubwayPanel(ButtonPanel control) {
        super(true);
        this.control = control;
        setPreferredSize(
            new Dimension(MAX * DOOR, DOOR * 162 / 100 + 16));
    }

    public void beginOperation() {
        timer.setInitialDelay(200);
        timer.start();
        timer.setInitialDelay(1000);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.clearRect(0, 0, getWidth(), getHeight());
        int width = getWidth() / MAX;
        int height = getHeight();
        int w2 = width / 2;
        g.setColor(Color.gray);
        g.fillRect(xx, yy, width, height);
        g.setColor(Color.black);
        g.drawRect(xx, yy, width - 1, height - 1);
        if (loading) {
            g.fillRect(xx + w2 / 2, yy, w2, height);
        } else {
            g.drawLine(xx + w2, yy, xx + w2, yy + height);
        }
    }

    // Handle Timer events
    public void actionPerformed(ActionEvent e) {
        int width = getWidth() / MAX;
        int height = getHeight();
        int curStop = Math.min(xx / width, MAX - 1);
        boolean selected = control.getButton(curStop);
        if (Math.abs(xx % width) < DX && selected) {
            timer.restart();
            control.clearButton(curStop);
            loading = true;
        } else {
            xx += dx;
            if (xx < 0) {
                dx = -dx;
                xx = 0;
            }
            if (xx > (MAX - 1) * width) {
                dx = -dx;
                xx = (MAX - 1) * width;
            }
            loading = false;
        }
        control.randomButton();
        this.repaint();
    }
}

class ButtonPanel extends JPanel implements ActionListener {

    private static final int MAX = SubwayPanel.MAX;
    private static final Random rnd = new Random();
    private ArrayList<JToggleButton> stops =
        new ArrayList<JToggleButton>();

    public ButtonPanel() {
        this.setLayout(new GridLayout(1, MAX));
        for (int i = 0; i < MAX; i++) {
            JToggleButton tb = new JToggleButton("Stop " + (i + 1));
            tb.addActionListener(this);
            if ((i > 0)) {
                tb.setSelected(rnd.nextBoolean());
            }
            stops.add(tb);
            this.add(tb);
        }
    }

    public boolean getButton(int i) {
        return stops.get(i).isSelected();
    }

    public void clearButton(int i) {
        stops.get(i).setSelected(false);
    }

    public void randomButton() {
        if (rnd.nextGaussian() > 2.0537) // ~2%
        {
            stops.get(rnd.nextInt(MAX)).setSelected(true);
        }
    }

    public void actionPerformed(ActionEvent e) {
        JToggleButton button = (JToggleButton) e.getSource();
        button.setSelected(true);
    }
}

Copyright © 2008 John B. Matthews. Distributed under the terms of the GPL
Č
ċ
Subway.jar
(8k)
John Matthews,
Dec 13, 2013, 10:57 PM
ċ
Subway.jnlp
(1k)
John Matthews,
Dec 13, 2013, 10:57 PM
ċ
SubwayApplet.jnlp
(1k)
John Matthews,
Dec 13, 2013, 10:57 PM
Comments