Sign up ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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 void Mark() {
        if(!isChecked) {
            if(!isMarked)
                this.setBackground(Color.GREEN);
            else
                this.setBackground(null);

            isMarked = !isMarked; // toggle on every click
        }
    }

}
share|improve this question
    
What is a Field? How is a Field different from a Square? –  JS1 Sep 7 at 16:36
    
@JS1 Field is the playing board which contains Squares as in playing tiles. –  nkmol Sep 7 at 17:11

1 Answer 1

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.

share|improve this answer
    
Thank you for this insightful post! I see now by creating a controller(logic) for the Squares the Square itself isn't aware of the Field anymore, which is good. However, do you mean to instantiate the controller for every Square or use one Controller for all the Squares which communicates from Square -> Controller -> Field. –  nkmol Sep 12 at 8:18
    
What I am suggesting is that the Controller would have an array of Buttons that make up the GUI and correspond to the Square objects in the model, and then the Controller would also have a Game object which has a Board object which contains the Square objects. Pressing a Button would cause the Controller to pass a command to the Game. –  bazola Sep 12 at 14:32

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.