RosettaCodeData/Task/Abelian-sandpile-model/Java/abelian-sandpile-model.java
2023-07-01 13:44:08 -04:00

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;
}