teaching machines

CS 145 Lecture 36 – Lights Out

December 12, 2016 by . Filed under cs145, fall 2016, lectures.

Dear students,

Today we apply a little bit of everything we’ve learned in a case study of the game Lights Out. We’ll use primitives and objects, ifs and loops, arrays, files, exceptions, graphical user interfaces—the whole shebang!

Here’s your TODO to complete before we meet again:

See you next class!

Sincerely,

P.S. Here’s the code we wrote together…

FlipButton.java

package lecture1212;

import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;

public class FlipButton extends JButton {
  private boolean isOn;
  
  public FlipButton() {
    isOn = false;
    setBackground(Color.DARK_GRAY);
    setBorderPainted(false);
    setOpaque(true);
    setPreferredSize(new Dimension(75, 75));
  }
  
  public boolean isOn() {
    return isOn;
  }
  
  public void turnOn() {
    isOn = true;
    setBackground(Color.YELLOW);
  }
  
  public void turnOff() {
    isOn = false;
    setBackground(Color.DARK_GRAY);
  }
  
  public void flip() {
    if (isOn) {
      setBackground(Color.DARK_GRAY);
    } else {
      setBackground(Color.YELLOW);
    }
    isOn = !isOn;
  }
}

LightsOutFrame.java

package lecture1212;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class LightsOutFrame extends JFrame {
  private FlipButton[][] buttons;

  public LightsOutFrame() {
    super("Lights Out!");

    JPanel panel = new JPanel(new GridLayout(5, 5, 2, 2));

    class FlipListener implements ActionListener {
      private int r;
      private int c;

      public FlipListener(int c, int r) {
        this.c = c;
        this.r = r;
      }

      public void actionPerformed(ActionEvent e) {
        // flip the clicked upon button and neighbors
        buttons[r][c].flip();
        if (r < 4)
          buttons[r + 1][c].flip();
        if (r > 0)
          buttons[r - 1][c].flip();
        if (c < 4)
          buttons[r][c + 1].flip();
        if (c > 0)
          buttons[r][c - 1].flip();

        if (isWin()) {
          JOptionPane.showMessageDialog(null, "You didn't lose.");
        }
      }
    }

    buttons = new FlipButton[5][5];
    for (int r = 0; r < 5; ++r) {
      for (int c = 0; c < 5; ++c) {
        buttons[r][c] = new FlipButton();
        buttons[r][c].addActionListener(new FlipListener(c, r));
        panel.add(buttons[r][c]);
      }
    }

    add(panel);
    pack();
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setVisible(true);
  }

  public void loadBoard(File file) throws FileNotFoundException {
    Scanner in = new Scanner(file);
    for (int r = 0; r < 5; ++r) {
      for (int c = 0; c < 5; ++c) {
        if (in.nextInt() == 1) {
          buttons[r][c].turnOn();
        } else {
          buttons[r][c].turnOff();
        }
      }
    }
  }

  public boolean isWin() {
    for (int r = 0; r < 5; ++r) {
      for (int c = 0; c < 5; ++c) {
        if (buttons[r][c].isOn()) {
          return false;
        }
      }
    }
    return true;
  }
}

LightsOut.java

package lecture1212;

import java.io.File;
import java.util.Scanner;

public class LightsOut {
  public static void main(String[] args) {
    LightsOutFrame game = new LightsOutFrame();
    Scanner in = new Scanner(System.in);
    boolean hasGoodBoard = false;
    
    while (!hasGoodBoard) {
      try {
        System.out.print("What board? ");
        game.loadBoard(new File(in.nextLine()));
        hasGoodBoard = true;
      } catch (Exception e) {
        System.err.println("Bad board!");
      }
    }

  }
}

board1.txt

1 0 0 0 1
0 1 0 1 0
0 0 1 0 0
0 1 0 1 0
1 0 0 0 1

board2.txt

0 1 0 1 0
1 1 0 1 1
0 0 0 0 0
1 1 0 1 1
0 1 0 1 0

board3.txt

1 0 0 0 1
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
1 0 0 0 1