Write program in Java language for Bomberman game

Interactive Grid-Bomb Sandbox (With Enemies)

Click to plant a bomb! Blow up the moving enemies (👾).

Complete Java Source Code

Copy the source code below to run it inside your local desktop Java IDE environment:

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

public class Bomberman extends JFrame implements ActionListener {
    private final JButton[][] grid;
    private final int[][] bombs;
    private final Timer timer;
    private final int ROWS = 10;
    private final int COLS = 10;
    private final ArrayList<Point> enemies;
    private final Random rand = new Random();

    public Bomberman() {
        super("Bomberman Desktop Engine (Enemies Embedded)");
        setLayout(new GridLayout(ROWS, COLS));
        grid = new JButton[ROWS][COLS];
        bombs = new int[ROWS][COLS];
        enemies = new ArrayList<>();

        // Spawn initial 4 enemies
        enemies.add(new Point(2, 2));
        enemies.add(new Point(2, 7));
        enemies.add(new Point(7, 2));
        enemies.add(new Point(7, 7));

        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                grid[row][col] = new JButton();
                grid[row][col].setBackground(Color.LIGHT_GRAY); 
                add(grid[row][col]);
                grid[row][col].addActionListener(this);
            }
        }

        updateGridRendering();

        int delay = 1000; 
        timer = new Timer(delay, this);
        timer.start();

        setSize(500, 500);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(Bomberman::new);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == timer) {
            handleTimerTick();
        } else {
            handleButtonClick((JButton) e.getSource());
        }
    }

    private void handleButtonClick(JButton clickedButton) {
        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                if (clickedButton == grid[row][col]) {
                    if (bombs[row][col] == 0) {
                        grid[row][col].setText("💣");
                        grid[row][col].setBackground(Color.RED);
                        bombs[row][col] = 4; 
                    }
                    return; 
                }
            }
        }
    }

    private void handleTimerTick() {
        boolean[][] toExplode = new boolean[ROWS][COLS];

        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                if (bombs[row][col] > 0) {
                    bombs[row][col]--;
                    if (bombs[row][col] == 0) {
                        toExplode[row][col] = true;
                    } else {
                        grid[row][col].setText("💣 (" + bombs[row][col] + ")");
                    }
                }
            }
        }

        for (int row = 0; row < ROWS; row++) {
            for (int col = 0; col < COLS; col++) {
                if (toExplode[row][col]) {
                    triggerExplosion(row, col);
                }
            }
        }

        moveEnemies();
        updateGridRendering();
    }

    private void moveEnemies() {
        int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
        for (Point enemy : enemies) {
            ArrayList<Point> validMoves = new ArrayList<>();
            for (int[] dir : directions) {
                int nr = enemy.x + dir[0];
                int nc = enemy.y + dir[1];
                if (nr >= 0 && nr < ROWS && nc >= 0 && nc < COLS && bombs[nr][nc] == 0) {
                    validMoves.add(new Point(nr, nc));
                }
            }
            if (!validMoves.isEmpty()) {
                Point choice = validMoves.get(rand.nextInt(validMoves.size()));
                enemy.setLocation(choice.x, choice.y);
}
}
}
private void updateGridRendering() {
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
if (bombs[row][col] > 0) continue;
boolean hasEnemy = false;
for (Point enemy : enemies) {
if (enemy.x == row && enemy.y == col) {
hasEnemy = true;
break;
}
}
if (hasEnemy) {
grid[row][col].setText("👾");
} else if (grid[row][col].getText().equals("👾") || grid[row][col].getText().equals("")) {
grid[row][col].setText("");
}
}
}
}
private void triggerExplosion(int r, int c) {
int[][] directions = {{0, 0}, {-1, 0}, {1, 0}, {0, -1}, {0, 1}};
for (int[] dir : directions) {
int newRow = r + dir[0];
int newCol = c + dir[1];
if (newRow >= 0 && newRow < ROWS && newCol >= 0 && newCol < COLS) {
grid[newRow][newCol].setText("💥");
grid[newRow][newCol].setBackground(Color.ORANGE);
// Blast kills enemy
for (int i = enemies.size() - 1; i >= 0; i--) {
Point p = enemies.get(i);
if (p.x == newRow && p.y == newCol) {
enemies.remove(i);
}
}
int finalRow = newRow;
int finalCol = newCol;
Timer clearTimer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
grid[finalRow][finalCol].setText("");
grid[finalRow][finalCol].setBackground(Color.LIGHT_GRAY);
updateGridRendering();
}
});
clearTimer.setRepeats(false);
clearTimer.start();
}
}
}
}