universe@3: /* universe@3: * Copyright 2013 Mike Becker. All rights reserved. universe@10: * universe@3: * Redistribution and use in source and binary forms, with or without universe@3: * modification, are permitted provided that the following conditions are met: universe@10: * universe@3: * 1. Redistributions of source code must retain the above copyright universe@3: * notice, this list of conditions and the following disclaimer. universe@10: * universe@3: * 2. Redistributions in binary form must reproduce the above copyright universe@3: * notice, this list of conditions and the following disclaimer in the universe@3: * documentation and/or other materials provided with the distribution. universe@10: * universe@3: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@3: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@3: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@3: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@3: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@3: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@3: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@3: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@3: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@3: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@3: * POSSIBILITY OF SUCH DAMAGE. universe@3: */ universe@3: universe@1: package de.uapcore.sudoku; universe@1: universe@9: import javax.swing.*; universe@9: import java.awt.*; universe@1: import java.awt.image.BufferedImage; universe@1: universe@1: /** universe@10: * A panel rendering the Sudoku field. universe@10: *

universe@10: * Cells are identified by zero-based indices from top-left to bottom-right. universe@1: */ universe@2: public final class Field extends JPanel { universe@12: private final SudokuTextField[][] cells; universe@10: universe@10: /** universe@10: * Constructs a new 9x9 Sudoku grid. universe@10: */ universe@1: public Field() { universe@1: setBackground(Color.WHITE); universe@10: universe@1: setLayout(new GridBagLayout()); universe@1: GridBagConstraints c = new GridBagConstraints(); universe@1: c.insets = new Insets(5, 5, 5, 5); universe@10: universe@1: cells = new SudokuTextField[9][9]; universe@10: for (int x = 0; x < 9; x++) { universe@10: for (int y = 0; y < 9; y++) { universe@1: cells[x][y] = new SudokuTextField(); universe@1: c.gridx = x; universe@1: c.gridy = y; universe@1: add(cells[x][y], c); universe@1: } universe@1: } universe@1: } universe@1: universe@10: /** universe@10: * Paints the grid and all contained cells. universe@10: * universe@10: * @param graphics the graphics context universe@10: */ universe@1: @Override universe@1: public void paint(Graphics graphics) { universe@1: final int w = getWidth(); universe@1: final int h = getHeight(); universe@1: final int cw = w / 9; universe@1: final int ch = h / 9; universe@10: universe@1: BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); universe@1: Graphics2D g = img.createGraphics(); universe@1: g.setBackground(Color.WHITE); universe@1: g.clearRect(0, 0, w, h); universe@10: universe@1: g.setColor(Color.BLACK); universe@10: g.drawRect(1, 1, w - 2, h - 2); universe@10: g.drawRect(2, 2, w - 4, h - 4); universe@10: for (int x = cw; x < w; x += cw) { universe@10: for (int y = ch; y < h; y += ch) { universe@10: g.drawLine(x, 2, x, h - 2); universe@10: g.drawLine(2, y, w - 2, y); universe@1: if ((x / cw) % 3 == 0) { universe@10: g.drawLine(x + 1, 2, x + 1, h - 2); universe@1: } universe@1: if ((y / ch) % 3 == 0) { universe@10: g.drawLine(2, y + 1, w - 2, y + 1); universe@1: } universe@1: } universe@1: } universe@10: universe@1: graphics.drawImage(img, 0, 0, this); universe@5: super.paintChildren(graphics); universe@1: } universe@10: universe@10: /** universe@10: * Checks whether a cell is empty universe@10: * universe@10: * @param x horizontal position universe@10: * @param y vertical position universe@10: * @return true if the cell is empty, false otherwise universe@10: */ universe@7: public boolean isCellEmpty(int x, int y) { universe@7: return getCellValue(x, y) == 0; universe@7: } universe@10: universe@10: /** universe@10: * Returns value of a specific cell. universe@10: * universe@10: * @param x horizontal position universe@10: * @param y vertical position universe@10: * @return the cell's value universe@10: */ universe@2: public int getCellValue(int x, int y) { universe@2: return cells[x][y].getValue(); universe@2: } universe@10: universe@10: /** universe@10: * Sets the value of a specific cell. universe@10: * universe@10: * @param x horizontal position universe@10: * @param y vertical position universe@10: * @param v the cells value universe@12: * @throws IllegalArgumentException if v is not between 0 and 9 universe@10: */ universe@2: public void setCellValue(int x, int y, int v) { universe@2: cells[x][y].setValue(v); universe@2: } universe@10: universe@10: /** universe@10: * Clears the value of a specific cell. universe@10: * universe@10: * @param x horizontal position universe@10: * @param y vertical position universe@10: */ universe@7: public void clearCellValue(int x, int y) { universe@7: setCellValue(x, y, 0); universe@7: } universe@10: universe@10: /** universe@10: * Sets the modified state of a specific cell. universe@10: * universe@10: * @param x horizontal position universe@10: * @param y vertical position universe@10: * @param modified the modified state universe@10: */ universe@7: public void setCellModified(int x, int y, boolean modified) { universe@7: cells[x][y].setModified(modified); universe@7: } universe@10: universe@10: /** universe@22: * Checks the modified state of a specific cell. universe@22: * universe@22: * @param x horizontal position universe@22: * @param y vertical position universe@22: * @return the modified state universe@22: */ universe@22: public boolean isCellModified(int x, int y) { universe@22: return cells[x][y].isModified(); universe@22: } universe@22: universe@22: /** universe@10: * Sets the modified state of all cells. universe@10: * universe@10: * @param modified the modified state universe@10: */ universe@2: public void setAllCellsModified(boolean modified) { universe@10: for (int x = 0; x < 9; x++) { universe@10: for (int y = 0; y < 9; y++) { universe@2: cells[x][y].setModified(modified); universe@2: } universe@2: } universe@2: } universe@10: universe@10: /** universe@10: * Checks whether any cell is modified. universe@10: * universe@10: * @return true if any cell is modified, false otherwise universe@10: */ universe@2: public boolean isAnyCellModified() { universe@10: for (int x = 0; x < 9; x++) { universe@10: for (int y = 0; y < 9; y++) { universe@2: if (cells[x][y].isModified()) { universe@2: return true; universe@2: } universe@2: } universe@2: } universe@2: return false; universe@2: } universe@10: universe@10: /** universe@10: * Clears all cells. universe@10: */ universe@4: public void clear() { universe@10: for (int x = 0; x < 9; x++) { universe@10: for (int y = 0; y < 9; y++) { universe@4: cells[x][y].setValue(0); universe@4: } universe@4: } universe@4: } universe@10: universe@10: /** universe@10: * Returns a square identified by square coordinates. universe@10: *

universe@10: * Cells within the square are identified by the same coordinate system. universe@10: * universe@10: * @param x horizontal position from 0 to 2 universe@10: * @param y vertical position from 0 to 2 universe@10: * @return a two-dimensional array containing the square cell values universe@12: * @throws IllegalArgumentException if the coordinates are out of bounds universe@10: */ universe@5: public int[][] getSquare(int x, int y) { universe@5: if (x < 0 || x > 2 || y < 0 || y > 2) { universe@5: throw new IllegalArgumentException("Invalid square coordinates"); universe@5: } universe@5: int[][] square = new int[3][3]; universe@10: universe@10: for (int u = 0; u < 3; u++) { universe@10: for (int v = 0; v < 3; v++) { universe@10: square[u][v] = getCellValue(3 * x + u, 3 * y + v); universe@5: } universe@5: } universe@10: universe@5: return square; universe@5: } universe@10: universe@10: /** universe@10: * Returns an entire row. universe@10: * universe@10: * @param y the row position universe@10: * @return an array containing the row values universe@12: * @throws IllegalArgumentException if y is not between 0 and 8 universe@10: */ universe@5: public int[] getRow(int y) { universe@5: if (y < 0 || y > 8) { universe@5: throw new IllegalArgumentException("Invalid row number"); universe@5: } universe@12: int[] row = new int[9]; universe@10: universe@10: for (int x = 0; x < 9; x++) { universe@5: row[x] = getCellValue(x, y); universe@5: } universe@10: universe@5: return row; universe@5: } universe@10: universe@10: /** universe@10: * Returns an entire column universe@10: * universe@10: * @param x the column position universe@10: * @return an array containing the column values universe@12: * @throws IllegalArgumentException if x is not between 0 and 8 universe@10: */ universe@5: public int[] getColumn(int x) { universe@5: if (x < 0 || x > 8) { universe@5: throw new IllegalArgumentException("Invalid column number"); universe@5: } universe@12: int[] column = new int[9]; universe@10: universe@10: for (int y = 0; y < 9; y++) { universe@5: column[y] = getCellValue(x, y); universe@5: } universe@10: universe@5: return column; universe@5: } universe@1: }