src/main/java/de/uapcore/sudoku/Field.java

Tue, 28 Jul 2020 14:27:14 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 28 Jul 2020 14:27:14 +0200
changeset 22
06170a0be62a
parent 12
1c62c6009161
permissions
-rw-r--r--

bugfix: modified state is reset even when saving fails + more tests

universe@3 1 /*
universe@3 2 * Copyright 2013 Mike Becker. All rights reserved.
universe@10 3 *
universe@3 4 * Redistribution and use in source and binary forms, with or without
universe@3 5 * modification, are permitted provided that the following conditions are met:
universe@10 6 *
universe@3 7 * 1. Redistributions of source code must retain the above copyright
universe@3 8 * notice, this list of conditions and the following disclaimer.
universe@10 9 *
universe@3 10 * 2. Redistributions in binary form must reproduce the above copyright
universe@3 11 * notice, this list of conditions and the following disclaimer in the
universe@3 12 * documentation and/or other materials provided with the distribution.
universe@10 13 *
universe@3 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@3 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@3 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@3 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@3 18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@3 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@3 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@3 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@3 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@3 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@3 24 * POSSIBILITY OF SUCH DAMAGE.
universe@3 25 */
universe@3 26
universe@1 27 package de.uapcore.sudoku;
universe@1 28
universe@9 29 import javax.swing.*;
universe@9 30 import java.awt.*;
universe@1 31 import java.awt.image.BufferedImage;
universe@1 32
universe@1 33 /**
universe@10 34 * A panel rendering the Sudoku field.
universe@10 35 * <p>
universe@10 36 * Cells are identified by zero-based indices from top-left to bottom-right.
universe@1 37 */
universe@2 38 public final class Field extends JPanel {
universe@12 39 private final SudokuTextField[][] cells;
universe@10 40
universe@10 41 /**
universe@10 42 * Constructs a new 9x9 Sudoku grid.
universe@10 43 */
universe@1 44 public Field() {
universe@1 45 setBackground(Color.WHITE);
universe@10 46
universe@1 47 setLayout(new GridBagLayout());
universe@1 48 GridBagConstraints c = new GridBagConstraints();
universe@1 49 c.insets = new Insets(5, 5, 5, 5);
universe@10 50
universe@1 51 cells = new SudokuTextField[9][9];
universe@10 52 for (int x = 0; x < 9; x++) {
universe@10 53 for (int y = 0; y < 9; y++) {
universe@1 54 cells[x][y] = new SudokuTextField();
universe@1 55 c.gridx = x;
universe@1 56 c.gridy = y;
universe@1 57 add(cells[x][y], c);
universe@1 58 }
universe@1 59 }
universe@1 60 }
universe@1 61
universe@10 62 /**
universe@10 63 * Paints the grid and all contained cells.
universe@10 64 *
universe@10 65 * @param graphics the graphics context
universe@10 66 */
universe@1 67 @Override
universe@1 68 public void paint(Graphics graphics) {
universe@1 69 final int w = getWidth();
universe@1 70 final int h = getHeight();
universe@1 71 final int cw = w / 9;
universe@1 72 final int ch = h / 9;
universe@10 73
universe@1 74 BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
universe@1 75 Graphics2D g = img.createGraphics();
universe@1 76 g.setBackground(Color.WHITE);
universe@1 77 g.clearRect(0, 0, w, h);
universe@10 78
universe@1 79 g.setColor(Color.BLACK);
universe@10 80 g.drawRect(1, 1, w - 2, h - 2);
universe@10 81 g.drawRect(2, 2, w - 4, h - 4);
universe@10 82 for (int x = cw; x < w; x += cw) {
universe@10 83 for (int y = ch; y < h; y += ch) {
universe@10 84 g.drawLine(x, 2, x, h - 2);
universe@10 85 g.drawLine(2, y, w - 2, y);
universe@1 86 if ((x / cw) % 3 == 0) {
universe@10 87 g.drawLine(x + 1, 2, x + 1, h - 2);
universe@1 88 }
universe@1 89 if ((y / ch) % 3 == 0) {
universe@10 90 g.drawLine(2, y + 1, w - 2, y + 1);
universe@1 91 }
universe@1 92 }
universe@1 93 }
universe@10 94
universe@1 95 graphics.drawImage(img, 0, 0, this);
universe@5 96 super.paintChildren(graphics);
universe@1 97 }
universe@10 98
universe@10 99 /**
universe@10 100 * Checks whether a cell is empty
universe@10 101 *
universe@10 102 * @param x horizontal position
universe@10 103 * @param y vertical position
universe@10 104 * @return true if the cell is empty, false otherwise
universe@10 105 */
universe@7 106 public boolean isCellEmpty(int x, int y) {
universe@7 107 return getCellValue(x, y) == 0;
universe@7 108 }
universe@10 109
universe@10 110 /**
universe@10 111 * Returns value of a specific cell.
universe@10 112 *
universe@10 113 * @param x horizontal position
universe@10 114 * @param y vertical position
universe@10 115 * @return the cell's value
universe@10 116 */
universe@2 117 public int getCellValue(int x, int y) {
universe@2 118 return cells[x][y].getValue();
universe@2 119 }
universe@10 120
universe@10 121 /**
universe@10 122 * Sets the value of a specific cell.
universe@10 123 *
universe@10 124 * @param x horizontal position
universe@10 125 * @param y vertical position
universe@10 126 * @param v the cells value
universe@12 127 * @throws IllegalArgumentException if v is not between 0 and 9
universe@10 128 */
universe@2 129 public void setCellValue(int x, int y, int v) {
universe@2 130 cells[x][y].setValue(v);
universe@2 131 }
universe@10 132
universe@10 133 /**
universe@10 134 * Clears the value of a specific cell.
universe@10 135 *
universe@10 136 * @param x horizontal position
universe@10 137 * @param y vertical position
universe@10 138 */
universe@7 139 public void clearCellValue(int x, int y) {
universe@7 140 setCellValue(x, y, 0);
universe@7 141 }
universe@10 142
universe@10 143 /**
universe@10 144 * Sets the modified state of a specific cell.
universe@10 145 *
universe@10 146 * @param x horizontal position
universe@10 147 * @param y vertical position
universe@10 148 * @param modified the modified state
universe@10 149 */
universe@7 150 public void setCellModified(int x, int y, boolean modified) {
universe@7 151 cells[x][y].setModified(modified);
universe@7 152 }
universe@10 153
universe@10 154 /**
universe@22 155 * Checks the modified state of a specific cell.
universe@22 156 *
universe@22 157 * @param x horizontal position
universe@22 158 * @param y vertical position
universe@22 159 * @return the modified state
universe@22 160 */
universe@22 161 public boolean isCellModified(int x, int y) {
universe@22 162 return cells[x][y].isModified();
universe@22 163 }
universe@22 164
universe@22 165 /**
universe@10 166 * Sets the modified state of all cells.
universe@10 167 *
universe@10 168 * @param modified the modified state
universe@10 169 */
universe@2 170 public void setAllCellsModified(boolean modified) {
universe@10 171 for (int x = 0; x < 9; x++) {
universe@10 172 for (int y = 0; y < 9; y++) {
universe@2 173 cells[x][y].setModified(modified);
universe@2 174 }
universe@2 175 }
universe@2 176 }
universe@10 177
universe@10 178 /**
universe@10 179 * Checks whether any cell is modified.
universe@10 180 *
universe@10 181 * @return true if any cell is modified, false otherwise
universe@10 182 */
universe@2 183 public boolean isAnyCellModified() {
universe@10 184 for (int x = 0; x < 9; x++) {
universe@10 185 for (int y = 0; y < 9; y++) {
universe@2 186 if (cells[x][y].isModified()) {
universe@2 187 return true;
universe@2 188 }
universe@2 189 }
universe@2 190 }
universe@2 191 return false;
universe@2 192 }
universe@10 193
universe@10 194 /**
universe@10 195 * Clears all cells.
universe@10 196 */
universe@4 197 public void clear() {
universe@10 198 for (int x = 0; x < 9; x++) {
universe@10 199 for (int y = 0; y < 9; y++) {
universe@4 200 cells[x][y].setValue(0);
universe@4 201 }
universe@4 202 }
universe@4 203 }
universe@10 204
universe@10 205 /**
universe@10 206 * Returns a square identified by square coordinates.
universe@10 207 * <p>
universe@10 208 * Cells within the square are identified by the same coordinate system.
universe@10 209 *
universe@10 210 * @param x horizontal position from 0 to 2
universe@10 211 * @param y vertical position from 0 to 2
universe@10 212 * @return a two-dimensional array containing the square cell values
universe@12 213 * @throws IllegalArgumentException if the coordinates are out of bounds
universe@10 214 */
universe@5 215 public int[][] getSquare(int x, int y) {
universe@5 216 if (x < 0 || x > 2 || y < 0 || y > 2) {
universe@5 217 throw new IllegalArgumentException("Invalid square coordinates");
universe@5 218 }
universe@5 219 int[][] square = new int[3][3];
universe@10 220
universe@10 221 for (int u = 0; u < 3; u++) {
universe@10 222 for (int v = 0; v < 3; v++) {
universe@10 223 square[u][v] = getCellValue(3 * x + u, 3 * y + v);
universe@5 224 }
universe@5 225 }
universe@10 226
universe@5 227 return square;
universe@5 228 }
universe@10 229
universe@10 230 /**
universe@10 231 * Returns an entire row.
universe@10 232 *
universe@10 233 * @param y the row position
universe@10 234 * @return an array containing the row values
universe@12 235 * @throws IllegalArgumentException if y is not between 0 and 8
universe@10 236 */
universe@5 237 public int[] getRow(int y) {
universe@5 238 if (y < 0 || y > 8) {
universe@5 239 throw new IllegalArgumentException("Invalid row number");
universe@5 240 }
universe@12 241 int[] row = new int[9];
universe@10 242
universe@10 243 for (int x = 0; x < 9; x++) {
universe@5 244 row[x] = getCellValue(x, y);
universe@5 245 }
universe@10 246
universe@5 247 return row;
universe@5 248 }
universe@10 249
universe@10 250 /**
universe@10 251 * Returns an entire column
universe@10 252 *
universe@10 253 * @param x the column position
universe@10 254 * @return an array containing the column values
universe@12 255 * @throws IllegalArgumentException if x is not between 0 and 8
universe@10 256 */
universe@5 257 public int[] getColumn(int x) {
universe@5 258 if (x < 0 || x > 8) {
universe@5 259 throw new IllegalArgumentException("Invalid column number");
universe@5 260 }
universe@12 261 int[] column = new int[9];
universe@10 262
universe@10 263 for (int y = 0; y < 9; y++) {
universe@5 264 column[y] = getCellValue(x, y);
universe@5 265 }
universe@10 266
universe@5 267 return column;
universe@5 268 }
universe@1 269 }

mercurial