The Java code implements a simple graphical application that visually represents and counts blobs within a grid by using recursion. A blob is a group of adjacent filled squares in the grid.
The application uses Java Swing for creating the graphical user interface (GUI) components. It includes buttons for generating a new set of blobs, counting the number of blobs, and a grid where users can click to get information about the blob size at that specific position. This Java code uses recursion in the getBlobSize
method to calculate the size of a blob.
The squares are arranged in a grid, and each position in the grid can be either empty or filled. A blob is defined to be a filled square and any square that can be reached from that square by moving horizontally or vertically to other filled squares. The application fills the grid randomly. If the user clicks on a filled square, all the squares in the blob that contains that square are colored red, and the number of squares in the blob is reported. The applet can also count and report the number of blobs. When the user clicks a “New Blobs” button, the grid is randomly re-filled.
Recursion is a natural fit for problems involving exploration of connected components, such as counting the size of blobs in this case. It simplifies the code and leverages the call stack to keep track of the positions to explore.
How this Code Works?
Class Structure:
- The main class is named
BlobsApp
, which extendsJFrame
and implementsActionListener
andMouseListener
interfaces. - The application is structured with an outer
JFrame
which represents the main window and an innerJPanel
namedContent
serving as the content pane.
Initialization:
- The
init
method is called during the initialization of the applet. It sets up the GUI components, initializes the grid, and creates buttons for generating new blobs and counting them.
Grid and Blob Generation:
- The grid is represented by a 2D array of boolean values (
filled
). Each cell in the grid represents a square, and the boolean value indicates whether the square is filled. - The
fillGrid
method generates a new grid of blobs based on a user-specified probability.
Blob Counting:
- The
countBlobs
method counts the number of blobs in the grid using a recursive algorithm (getBlobSize
). The algorithm marks visited squares to prevent counting the same blob multiple times. - The result is displayed in a message label on the GUI.
Blob Size Calculation:
- The
getBlobSize
method recursively calculates the size of a blob starting from a given position in the grid.
Mouse Interaction:
- Users can interact with the grid by clicking on squares. The
mousePressed
method retrieves blob information for the clicked position and displays it in the message label.
GUI Presentation:
- The GUI is presented with buttons for user actions, a grid of squares representing the blobs, and a message label for displaying information.
- The
Content
class extendsJPanel
and is responsible for painting the grid based on the state of the blobs and visited squares.
Java Blob Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BlobsApp extends JFrame implements ActionListener, MouseListener { private static final int SQUARE_SIZE = 8; private JLabel message; private JComboBox<String> percentFill; private int rows; private int columns; private boolean[][] filled; private boolean[][] visited; public BlobsApp() { setTitle("Blobs App"); setSize(600, 400); // Set your preferred initial width and height setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(true); Content content = new Content(); setContentPane(content); content.setLayout(null); content.setBackground(new Color(220, 220, 255)); content.addMouseListener(this); content.setBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, Color.blue)); int width = 600; // Set your preferred width int height = 400; // Set your preferred height rows = (height - 100) / SQUARE_SIZE; columns = (width - 20) / SQUARE_SIZE; filled = new boolean[rows][columns]; visited = new boolean[rows][columns]; for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) filled[r][c] = (Math.random() < 0.3); message = new JLabel("Click a square to get the blob size.", JLabel.CENTER); message.setForeground(Color.blue); message.setFont(new Font("Helvetica", Font.PLAIN, 14)); percentFill = new JComboBox<>(); for (int i = 1; i <= 9; i++) { percentFill.addItem(i * 10 + "% fill"); } percentFill.setBackground(Color.white); percentFill.setSelectedIndex(2); JButton newButton = new JButton("New Blobs"); newButton.addActionListener(this); newButton.setBackground(Color.lightGray); JButton countButton = new JButton("Count the Blobs"); countButton.addActionListener(this); countButton.setBackground(Color.lightGray); content.add(message); content.add(newButton); content.add(percentFill); content.add(countButton); message.setBounds(15, height - 75, width - 30, 18); countButton.setBounds(15, height - 50, width - 30, 18); newButton.setBounds(15, height - 25, (width - 40) / 2, 18); percentFill.setBounds(width / 2 + 5, height - 25, (width - 40) / 2, 18); pack(); setLocationRelativeTo(null); // Center the frame on the screen setVisible(true); } public void actionPerformed(ActionEvent evt) { String cmd = evt.getActionCommand(); if ("New Blobs".equals(cmd)) fillGrid(); else if ("Count the Blobs".equals(cmd)) countBlobs(); } void fillGrid() { double probability = (percentFill.getSelectedIndex() + 1) / 10.0; for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) { filled[r][c] = (Math.random() < probability); visited[r][c] = false; } message.setText("Click a square to get the blob size."); repaint(); } void countBlobs() { int count = 0; for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) visited[r][c] = false; for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) { if (getBlobSize(r, c) > 0) count++; } repaint(); message.setText("The number of blobs is " + count); } int getBlobSize(int r, int c) { if (r < 0 || r >= rows || c < 0 || c >= columns) { return 0; } if (!filled[r][c] || visited[r][c]) { return 0; } visited[r][c] = true; int size = 1; size += getBlobSize(r - 1, c); size += getBlobSize(r + 1, c); size += getBlobSize(r, c - 1); size += getBlobSize(r, c + 1); return size; } public void mousePressed(MouseEvent evt) { int row = (evt.getY() - 10) / SQUARE_SIZE; int col = (evt.getX() - 10) / SQUARE_SIZE; if (row < 0 || row >= rows || col < 0 || col >= columns) { message.setText("Please click on a square!"); return; } for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) visited[r][c] = false; int size = getBlobSize(row, col); if (size == 0) message.setText("There is no blob at (" + row + "," + col + ")."); else if (size == 1) message.setText("Blob at (" + row + "," + col + ") contains 1 square."); else message.setText("Blob at (" + row + "," + col + ") contains " + size + " squares."); repaint(); } public void mouseReleased(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} class Content extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); int width = getSize().width; int height = getSize().height; g.setColor(Color.white); g.fillRect(10, 10, columns * SQUARE_SIZE, rows * SQUARE_SIZE); g.setColor(Color.black); for (int i = 0; i <= rows; i++) g.drawLine(10, 10 + i * SQUARE_SIZE, columns * SQUARE_SIZE + 10, 10 + i * SQUARE_SIZE); for (int i = 0; i <= columns; i++) g.drawLine(10 + i * SQUARE_SIZE, 10, 10 + i * SQUARE_SIZE, rows * SQUARE_SIZE + 10); for (int r = 0; r < rows; r++) for (int c = 0; c < columns; c++) { if (visited[r][c]) { g.setColor(Color.red); g.fillRect(11 + c * SQUARE_SIZE, 11 + r * SQUARE_SIZE, SQUARE_SIZE - 1, SQUARE_SIZE - 1); } else if (filled[r][c]) { g.setColor(Color.gray); g.fillRect(11 + c * SQUARE_SIZE, 11 + r * SQUARE_SIZE, SQUARE_SIZE - 1, SQUARE_SIZE - 1); } } } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { new BlobsApp().setVisible(true); }); } } |
When you run the program you will see a similar window as showing below: