0

I'm trying to make a lights out game, I simplified it to only change one tile at a time but I'm still encountering one bug. I can click to change from yellow to black but I can't click and have the opposite happen. Here is the game if you are unfamiliar: http://www.logicgamesonline.com/lightsout/

My code:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.net.*;

public class LightsOutPanel extends JPanel implements MouseListener {
    private boolean[][] lights;

    public static void main(String[] args) throws Exception {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Lights Out!");
        frame.setResizable(false);
        frame.setVisible(true);

        LightsOutPanel panel = new LightsOutPanel();
        if (panel.lights == null) {
            System.out.println("You did not initialize your light array!" +
                               "It's still null...");
            System.exit(-1);
        }
        panel.addMouseListener(panel);
        panel.setPreferredSize(new Dimension(601, 501));
        panel.setMinimumSize(new Dimension(601, 501));

        Container c = frame.getContentPane();
        c.setLayout(new BorderLayout());
        c.add(panel, BorderLayout.CENTER);

        frame.pack();
    }

    public LightsOutPanel() {
        lights = new boolean[5][6];
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 6; j++) {
                lights[i][j] = true;
            }
        }

    }

    // unused methods
    public void mouseClicked(MouseEvent e) {}

    public void mouseReleased(MouseEvent e) {}

    public void mouseEntered(MouseEvent e) {}

    public void mouseExited(MouseEvent e) {}

    public void paint(Graphics g) {
        int boxWidth = 600 / 6;
        int boxHeight = 500 / 5;

        int y = 0;
        for (int row = 0; row < 5; row++) {
            int x = 0;
            for (int col = 0; col < 6; col++) {
                if (lights[row][col]==true) {
                    g.setColor(Color.YELLOW);
                } else {
                    g.setColor(Color.BLACK);
                }
                g.fillRect(x, y, boxWidth, boxHeight);

                g.setColor(Color.BLUE);
                g.drawRect(x, y, boxWidth, boxHeight);
                x += boxWidth;
            }
            y += boxHeight;
        }
    }

    // called when the mouse is pressed - determines what row/column the user
    // has clicked
    public void mousePressed(MouseEvent e) {
        int mouseX = e.getX();
        int mouseY = e.getY();

        int panelWidth = getWidth();
        int panelHeight = getHeight();

        int boxWidth = panelWidth / lights[0].length;
        int boxHeight = panelHeight / lights.length;

        int col = mouseX / boxWidth;
        int row = mouseY / boxHeight;

        toggle(row, col);
        repaint();
    }

    // called to "toggle" the selected row and column, as well as the four
    // adjacent lights
    public void toggle(int row, int col) {

        if (row >= 0 && col >= 0 && row < lights.length && 
            col < lights[0].length)
        {
            if (lights[row][col] = true) {
                lights[row][col] = false;
            } else {
                lights[row][col] = true;
            }
        }

    }
}
Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
MickDom
  • 157
  • 2
  • 12
  • 1
    @MadProgrammer is going to advise you to not override `paint()` and instead override `paintComponent()`. – Jonny Henly Feb 26 '16 at 01:51
  • What do you mean by that? – MickDom Feb 26 '16 at 02:01
  • Also, your `if` statements in `toggle()` use the assignment operator `=` instead of the equality operator `==`. And your `paint(Graphics g)` method should make a call to `super(g)` before anything else. – Jonny Henly Feb 26 '16 at 02:02
  • omg all I was missing was that one equals, thanks. – MickDom Feb 26 '16 at 02:04
  • 1
    You should also look into overriding `paintComponent(Graphics g)` instead of `paint(Graphics g)`. Take a look at [Concerns about the function of JPanel: paintcomponent()](http://stackoverflow.com/questions/5446396/concerns-about-the-function-of-jpanel-paintcomponent). – Jonny Henly Feb 26 '16 at 02:05
  • Start by having a look at [Painting in AWT and Swing](http://www.oracle.com/technetwork/java/painting-140037.html) and [Performing Custom Painting](http://docs.oracle.com/javase/tutorial/uiswing/painting/). You've violate the paint method chain contract (by not calling `super.paint`) – MadProgrammer Feb 26 '16 at 04:24

1 Answers1

1

Your "core" problem is in your toggle method...

if (lights[row][col] = true) {

= is an assignment, so you saying assign true to lights[row][col] and if lights[row][col] == true then do the following...so it's always true.

A simpler method would be to do....

lights[row][col] = !lights[row][col];

no, if's or else's, nice a simple.

You should also have a a look at Painting in AWT and Swing and Performing Custom Painting. You've violate the paint method chain contract (by not calling super.paint)

Instead of overriding paint, you should be using paintComponent AND you should be calling super.paintComponent before you do any custom painting, this will ensure that the Graphics context is nicely prepared for you

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366