/*---------------------------------------------------------------------------* | Lights Out! (lightsout.java, .class) | | Written by James Lewis (jalewis2@uiuc.edu) | | Jan. 22, 1998 | | This program is based on the game Lights Out made by Tiger Electronics. | | As such it is not to be used or sold commercially. This version allows | | the user to assign a difficulty level eqiuvalent to the minimum number of | | moves required to finish the puzzle successfully. Each board is randomly | | generated, and the user can also chose to restart the current puzzle from | | it initial state. (For those unfamiliar with java, all comments can be | | viewed after //.) | *---------------------------------------------------------------------------*/ import java.awt.*; import java.applet.*; import java.awt.event.*; public class lightsout extends Applet implements ActionListener, MouseListener { // Variables. Note that the vector arrays are boolean, // represented by trues and falses. So true is on. TextField Difficulty = new TextField("0", 3); Button Restart = new Button("Restart"); Button Generate = new Button("New"); Button Hint = new Button("Hint"); TextField Moves = new TextField("0", 3); boolean finished = false; int MinNumber, movesleft, movecount = 0; boolean[] InitialVectorArray = new boolean[36]; boolean[] CurrentVectorArray = new boolean[36]; boolean[] ZeroArray = new boolean[36]; boolean[] WinningArray = new boolean[36]; int[] InitialButtonArray = new int[36]; int[] CurrentButtonArray = new int[150]; // The program starts here. public void init () { // Creates prompts at top of applet. add(new Label("Difficulty (0-36):")); add(Difficulty); Difficulty.addActionListener(this); add(Restart); Restart.addActionListener(this); add(Generate); Generate.addActionListener(this); add(new Label("Number of Moves Made:")); Moves.setEditable(false); add(Moves); add(Hint); Hint.addActionListener(this); addMouseListener(this); } // Redraws buttons (called by "repaint();"). public void paint (Graphics g) { finished = true; for(int j=0; j<36; j++) { if(CurrentVectorArray[j]!=ZeroArray[j]) finished = false; } if(!finished || movecount>MinNumber) for(int i=0; i<36; i++) if(CurrentVectorArray[i]) { g.setColor(new Color(255, 96, 0)); g.fillRect(5 + 45*(i%6), 70 + 25*(i/6), 40, 20); } else { g.setColor(new Color(0, 0, 170)); g.fillRect(5 + 45*(i%6), 70 + 25*(i/6), 40, 20); } else for(int i=0; i<36; i++) if(WinningArray[i]) { g.setColor(new Color(255, 96, 0)); g.fillRect(5 + 45*(i%6), 70 + 25*(i/6), 40, 20); } else { g.setColor(new Color(0, 0, 170)); g.fillRect(5 + 45*(i%6), 70 + 25*(i/6), 40, 20); } } // Activated when the user enters a number in the prompt // or pushes a button at the top. public void actionPerformed (ActionEvent e) { // Gets difficulty level if changed. if(e.getSource()==Difficulty) MinNumber = Integer.parseInt(Difficulty.getText()); // This long section, continuing at this indentation, // generates a new board. if(e.getSource()==Difficulty || e.getSource()==Generate) { // Initializing arrays. for(int i = 0; i<36; i++) { ZeroArray[i] = false; InitialVectorArray[i] = false; if(i!=7 && i!=10 && i!=18 && i!=23 && i!=25 && i!=26 && i!=27 && i!=28) WinningArray[i] = false; else WinningArray[i] = true; } if(MinNumber>=1 && MinNumber<=36) { // "Filling" the vector array. for(int i = 0; i0) InitialVectorArray[k-1] = !InitialVectorArray[k-1]; if(k%6<5) InitialVectorArray[k+1] = !InitialVectorArray[k+1]; if(k/6>0) InitialVectorArray[k-6] = !InitialVectorArray[k-6]; if(k/6<5) InitialVectorArray[k+6] = !InitialVectorArray[k+6]; } } } // Gives a hint, then redraws. if(e.getSource()==Hint) { movesleft--; movecount++; Moves.setText(Integer.toString(movecount)); while(movesleft>=0 && CurrentButtonArray[movesleft]==-1) movesleft--; if(movesleft<0) movesleft = 0; else { // Changes the states around hinted button. int k = CurrentButtonArray[movesleft]; CurrentVectorArray[k] = !CurrentVectorArray[k]; if(k%6>0) CurrentVectorArray[k-1] = !CurrentVectorArray[k-1]; if(k%6<5) CurrentVectorArray[k+1] = !CurrentVectorArray[k+1]; if(k/6>0) CurrentVectorArray[k-6] = !CurrentVectorArray[k-6]; if(k/6<5) CurrentVectorArray[k+6] = !CurrentVectorArray[k+6]; CurrentButtonArray[movesleft] = -1; } repaint(); } else { // Now we set the move counter back to zero, set the current light // configuration to the inital one, and redraw the buttons. Note that if // the restart button was pressed, a new initial configuration was not // generated, thus restoring the inital state from memory. finished = false; movesleft = MinNumber; movecount = 0; Moves.setText("0"); for(int i=0; i0) CurrentVectorArray[k-1] = !CurrentVectorArray[k-1]; if(k%6<5) CurrentVectorArray[k+1] = !CurrentVectorArray[k+1]; if(k/6>0) CurrentVectorArray[k-6] = !CurrentVectorArray[k-6]; if(k/6<5) CurrentVectorArray[k+6] = !CurrentVectorArray[k+6]; // We check to see, for hint purposes, whether the button was in its // "correct state". If it wasn't, the button should be removed from // the ButtonArray, and the player is closer to his goal. Otherwise, // the user has moved farther away than necessary, and it needs to be // added to the ButtonArray list. boolean inlist=false; for(int j=0; j