HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Board-tile game click event OOP pattern

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
clicktilepatterngameoopboardevent

Problem

This is actually an old 'problem' that I never really knew how to improve, but I'm wondering now if there is a better approach for this problem.

I'm creating MineSweeper with Java and struggling with an OOP aspect of the game. Basically I have a class Square.java, SquareBoms(extends Square) and Field.java. My approach on the Square is that it should only be aware of itself and should not communicate in any way or form with the Field.

However, the Field should check the surrounding SquaresBombs for bombs once a Square has been clicked. So the Square SHOULD message the Field that it has been clicked, but I don't think this is the right way of using OOP.

```
import java.awt.Color;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JButton;

public class Square extends JButton {
Field owner; //This is not OOP as the Square should only be aware of itself and what is in it.
int coords;
boolean isChecked = false;
boolean isMarked = false;
int bombsAround;

public Square(Field owner, int coords) {
this.owner = owner;
this.coords = coords;
this.setSize(400, 400);
this.setMargin(new Insets(0, 0, 0, 0));
this.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e){
if (e.getButton() == MouseEvent.BUTTON1) {
Clicked();
}
else if(e.getButton() == MouseEvent.BUTTON3) {
Mark();
}
}
});
}

public void Clicked() {
if(!isChecked) {
this.setBackground(new Color(238, 238, 238)); // Reset when it had been marked
isChecked = true;
this.setEnabled(false);

owner.checkSquare(this); //This is not OOP as the Square should only be aware of itself and what is in it.
}
}

public v

Solution

Separation of Logic and Rendering

The Square object is essentially a button that also contains some information for display, such as the number of surrounding bombs.

The problem you are having is that this GUI element is communicating directly with the game board of your minesweeper game model. When Square gets clicked, it tells the board to check the amount of bombs.

I'm not very familiar with Swing, but typically I would expect there to be a Scene or Window at the top level of the hierarchy. Once clicked, the button would tell the controller to tell the game model to perform the necessary action, and then the controller would update the view based on changes to the model.

In this approach you could possibly have a Game object, Board object, and Square object in the game model. On a button click, the coordinates of the Square button object in the view would be passed into the Game, and the appropriate changes would be made to the Board and to the game state. For example, the coordinates have a bomb, and so the state of the Game is set to GameState.LOSS.

In this approach, you could make the Board object available to the view.
After each move, the view could update based on the new state of the board, marking the squares that have flags, have been uncovered, etc.

You could also do something such as compute the positions of the nearby Square objects at the start of the game, and then you could check for bombs like this:

int bombCount = 0;
for (Position position : square.neighbors) {
    Square neighbor = board.get(position);
    if (neighbor.hasBomb) {
        bombCount++;
    }
}


Or alternatively store a reference to the actual Square objects, if you want.

The advantage of all of this is that if you some day want to use a different graphical representation other than Swing, you could easily take the code for the game model and use a different controller and view. You would still use the model in the same way, passing in the coordinates of the location on the board that is clicked.

Code Snippets

int bombCount = 0;
for (Position position : square.neighbors) {
    Square neighbor = board.get(position);
    if (neighbor.hasBomb) {
        bombCount++;
    }
}

Context

StackExchange Code Review Q#104013, answer score: 5

Revisions (0)

No revisions yet.