113 lines
3.5 KiB
Java
113 lines
3.5 KiB
Java
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import javax.swing.*;
|
|
|
|
public class AbelianSandpile {
|
|
public static void main(String[] args) {
|
|
SwingUtilities.invokeLater(new Runnable() {
|
|
public void run() {
|
|
Frame frame = new Frame();
|
|
frame.setVisible(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
private static class Frame extends JFrame {
|
|
private Frame() {
|
|
super("Abelian Sandpile Model");
|
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
|
Container contentPane = getContentPane();
|
|
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
|
JButton start = new JButton("Restart Simulation");
|
|
start.addActionListener(e -> restartSimulation());
|
|
JButton stop = new JButton("Stop Simulation");
|
|
stop.addActionListener(e -> stopSimulation());
|
|
controlPanel.add(start);
|
|
controlPanel.add(stop);
|
|
contentPane.add(controlPanel, BorderLayout.NORTH);
|
|
contentPane.add(canvas = new Canvas(), BorderLayout.CENTER);
|
|
timer = new Timer(100, e -> canvas.runAndDraw());
|
|
timer.start();
|
|
pack();
|
|
}
|
|
|
|
private void restartSimulation() {
|
|
timer.stop();
|
|
canvas.initGrid();
|
|
timer.start();
|
|
}
|
|
|
|
private void stopSimulation() {
|
|
timer.stop();
|
|
}
|
|
|
|
private Timer timer;
|
|
private Canvas canvas;
|
|
}
|
|
|
|
private static class Canvas extends JComponent {
|
|
private Canvas() {
|
|
setBorder(BorderFactory.createEtchedBorder());
|
|
setPreferredSize(new Dimension(600, 600));
|
|
}
|
|
|
|
public void paintComponent(Graphics g) {
|
|
int width = getWidth();
|
|
int height = getHeight();
|
|
g.setColor(Color.WHITE);
|
|
g.fillRect(0, 0, width, height);
|
|
int cellWidth = width/GRID_LENGTH;
|
|
int cellHeight = height/GRID_LENGTH;
|
|
for (int i = 0; i < GRID_LENGTH; ++i) {
|
|
for (int j = 0; j < GRID_LENGTH; ++j) {
|
|
if (grid[i][j] > 0) {
|
|
g.setColor(COLORS[grid[i][j]]);
|
|
g.fillRect(i * cellWidth, j * cellHeight, cellWidth, cellHeight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void initGrid() {
|
|
for (int i = 0; i < GRID_LENGTH; ++i) {
|
|
for (int j = 0; j < GRID_LENGTH; ++j) {
|
|
grid[i][j] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void runAndDraw() {
|
|
for (int i = 0; i < 100; ++i)
|
|
addSand(GRID_LENGTH/2, GRID_LENGTH/2);
|
|
repaint();
|
|
}
|
|
|
|
private void addSand(int i, int j) {
|
|
int grains = grid[i][j];
|
|
if (grains < 3) {
|
|
grid[i][j]++;
|
|
}
|
|
else {
|
|
grid[i][j] = grains - 3;
|
|
if (i > 0)
|
|
addSand(i - 1, j);
|
|
if (i < GRID_LENGTH - 1)
|
|
addSand(i + 1, j);
|
|
if (j > 0)
|
|
addSand(i, j - 1);
|
|
if (j < GRID_LENGTH - 1)
|
|
addSand(i, j + 1);
|
|
}
|
|
}
|
|
|
|
private int[][] grid = new int[GRID_LENGTH][GRID_LENGTH];
|
|
}
|
|
|
|
private static final Color[] COLORS = {
|
|
Color.WHITE,
|
|
new Color(0x00, 0xbf, 0xff),
|
|
new Color(0xff, 0xd7, 0x00),
|
|
new Color(0xb0, 0x30, 0x60)
|
|
};
|
|
private static final int GRID_LENGTH = 300;
|
|
}
|