All pastes #267606 Raw Edit

Miscellany

public text v1 · immutable
·published 2006-12-04 23:25 UTC
rendered paste body
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. All menu items work as advertised.
 * 
 * @author Kyle Wilson
 * @version 30 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);
		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);
						sBoard[i][j] = -1;
					}
					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. 
	 * note: algorithm revised as of version 2006.11.30
	 */
	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 i = 0; i < 9; i++)
		  {
			  for(int j = 0; j < 9; j++)
			  {
				  int myx = i - (i % 3);
				  int myy = j - (j % 3);
				  for(int x=myx; x<myx+3; x++) {
						for(int y=myy; y<myy+3; y++) {
							if(x!=i && y!=j && sBoard[x][y] == sBoard[i][j] && sBoard[x][y] != -1) {
								sudokuBoard[i][j].duplicate = true;
								
							}
						}
					}
			  }
		  }
		  }
	
		  private void updateSudokuBoard()
		  {
			  for(int i = 0; i<9;i++)
				  for(int j=0;j<9;j++)
				  {
					  if(sBoard[i][j] != -1)
						  sudokuBoard[i][j].setText(sBoard[i][j] + "");
					  else
						  sudokuBoard[i][j].setText("");
				  }
		  }
		  
	      /**
	       * 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("");}
		    updatesBoard();
		    checkDuplicate();
		    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)); 
		      sBoard = (int[][]) in.readObject();
		      in.close(); 
		      updateSudokuBoard();
		      repaint();
		    } catch (IOException e1) {
		      System.out.println("Unable to open file: " + filename); 
		    } catch (ClassNotFoundException e2) {
		      System.out.println(e2 + "oh no"); 
		    }
		  }
		  
		  /**
		   * Saves a sudoku puzzle currently in progress.
		   * @param filename - the name to save the sudoku puzzle under.
		   */
		  public void saveFile(String filename) { 
			  updatesBoard();
		    try {
		      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename)); 
		      out.writeObject(sBoard);
		      out.close(); 
		      System.out.println("Save Sudoku to " + filename);
		    } catch (IOException e) {
		      System.out.println("Unable to write file: " + filename); 
		    }  
		  }
		  

		  
		  
		  /**
		   * Extension of the JTextField class that provides a boolean value
		   * to specify whether the SudokuTextField is a duplicate and values
		   * for the x and y location in the sudokuBoard grid.
		   * @author kyle
		   *
		   */
			class SudokuTextField extends JTextField {
				int x,y;
				String value;
				boolean duplicate;

				/**
				 * default constructor
				 * @param x x position in the sudokuBoard grid
				 * @param y y position in the sudokuBoard grid
				 */
				public SudokuTextField(int x, int y) {
					this.x = x;
					this.y = y;
					duplicate = false;

					setOpaque(false);

				}
				
				/**
				 * accessor method to modify duplicate
				 * @param dupe value to set duplicate to.
				 */
				public void setDuplicate(boolean dupe)
				{
					duplicate = dupe;
				}
				
				
				  /**
				   * standard update method.
				   */
				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 int x, y;
		  protected SudokuTextField[][] sudokuBoard; //the board of SudokuTextField objects; what the user sees.
		  protected int[][] sBoard; //int sudokuBoard representation, used for duplicate checking

}