package sudoku;import java.awt.*;import java.awt.event.*;import java.io.*;import java.util.EventListener;import javax.swing.*;/** * The SudokuPanel class currently draws the Sudoku Board and allows for text entry. New and quit work as advertised. * * @author Kyle Wilson * @version 19 November 2006 * * code for menu bar adapted from Scribble Program example by Xiaoping Jia Copyright 2002 * */public class SudokuPanel extends JPanel implements ActionListener{ /** * Constructs a SudokuPanel object and initializes a SudokuPanelListener to act as a MouseListener * */ public SudokuPanel() { super(); sBoard = new int[9][9]; setLayout(new GridLayout(9,9)); sudokuBoard = new SudokuTextField[9][9]; Font font = new Font("Monospace", Font.BOLD, 24); //SudokuPanelListener SPListener = new SudokuPanelListener(this); for(int i=0; i<sudokuBoard.length; i++) { for(int j=0; j<sudokuBoard[i].length; j++) { sudokuBoard[i][j] = new SudokuTextField(j,i); sudokuBoard[i][j].setFont(font); sudokuBoard[i][j].addActionListener(this); add(sudokuBoard[i][j]); sBoard[i][j] = -1; } } } /** * The actionPerformed method is called whenever the user hits enter after entering text into * a SudokuTextField box. It will first update sBoard to any changes in sudokuBoard, then check * for duplicates, then update the GUI to any duplicates. */ public void actionPerformed(ActionEvent evt) { updatesBoard(); checkDuplicate(); repaint(); } /** * Updates all the sBoard entries to reflect their current status. An empty or invalid cell is filled with -1 by default. * */ private void updatesBoard() { for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { try { int testint = Integer.parseInt(sudokuBoard[i][j].getText()); if(testint > 9 || testint < 1) { JOptionPane.showMessageDialog(null, "Sudoku numbers must be between 1 and 9", "Invalid Entry", JOptionPane.ERROR_MESSAGE); } else sBoard[i][j] = testint; } catch(NumberFormatException e) { sBoard[i][j] = -1; } catch(NullPointerException e) { sBoard[i][j] = -1; } } } } /** * Checks for duplicates in every row, column, and blocks. * */ private void checkDuplicate() { for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++) sudokuBoard[i][j].duplicate = false; for(int a = 0; a < 9; a++) { for(int i = 0; i < 9; i++) { for(int j = 0; j < 9; j++) { if(i != j && sBoard[a][i] == sBoard[a][j] && sBoard[a][i] != -1 && sBoard[a][j] != -1) { sudokuBoard[a][i].duplicate = true; sudokuBoard[a][j].duplicate = true; } if(i != j && sBoard[i][a] == sBoard[j][a] && sBoard[i][a] != -1 && sBoard[j][a] != -1) { sudokuBoard[i][a].duplicate = true; sudokuBoard[j][a].duplicate = true; } } } } for(int a = 0; a < 3; a++) for(int i=a*3; i<a*3+3; i++) { for(int j=a*3; j<a*3+3; j++) { for(int i2=a*3; i2<a*3+3; i2++) { for(int j2=a*3; j2<a*3+3; j2++) { if(i != i2 && j != j2 && sBoard[i][j] == sBoard[i2][j2] && sBoard[i][j] != -1 && sBoard[i2][j2] != -1) { sudokuBoard[i][j].duplicate = true; sudokuBoard[i2][j2].duplicate = true; } } } } } } /** * Clears the current Sudoku Puzzle and leave an empty board. * */ public void newFile() { for(int i = 0; i < 9; i++) for(int j = 0; j < 9; j++) { sudokuBoard[i][j].setText("");} repaint(); } /** * Opens a saved Sudoku puzzle. * @param filename - The name of the file to open. */ public void openFile(String filename) { try { ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename)); sudokuBoard = (SudokuTextField[][]) in.readObject(); in.close(); repaint(); } catch (IOException e1) { System.out.println("Unable to open file: " + filename); } catch (ClassNotFoundException e2) { System.out.println(e2); } } /** * Saves a sudoku puzzle currently in progress. * @param filename - the name to save the sudoku puzzle under. */ public void saveFile(String filename) { try { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); out.writeObject(sudokuBoard); out.close(); System.out.println("Save Sudoku to " + filename); } catch (IOException e) { System.out.println("Unable to write file: " + filename); } } class SudokuTextField extends JTextField { int x,y; String value; boolean duplicate; public SudokuTextField(int x, int y) { this.x = x; this.y = y; duplicate = false; setOpaque(false); } public void setDuplicate(boolean dupe) { duplicate = dupe; } public void update(Graphics g) { paint(g); } /** * Draws the border rectangle for each SudokuTextField box which makes up the board * and also will outline the box in red if the entry is a duplicate. */ public void paint(Graphics g) { g.setColor(Color.WHITE); g.fillRect(0,0,getSize().width,getSize().height); if(duplicate){ g.setColor(Color.RED); g.drawLine(0,0,getSize().width-1,0); g.drawLine(0,0,0,getSize().height-1); } else g.setColor(Color.BLACK); g.drawLine(getSize().width-1,0,getSize().width-1,getSize().height); g.drawLine(0,getSize().height-1,getSize().width,getSize().height-1); if(x == 3 || x == 6) { g.drawLine(0,0,0,getSize().width); } if(y == 3 || y == 6) { g.drawLine(0,0,getSize().width,0); } super.paintComponent(g); } } protected EventListener listener; protected boolean mouseButtonDown = false; protected int x, y; protected SudokuTextField[][] sudokuBoard; protected int[][] sBoard;}