29 import javax.swing.*; |
29 import javax.swing.*; |
30 import java.awt.*; |
30 import java.awt.*; |
31 import java.awt.image.BufferedImage; |
31 import java.awt.image.BufferedImage; |
32 |
32 |
33 /** |
33 /** |
34 * |
34 * A panel rendering the Sudoku field. |
35 * @author mike |
35 * <p> |
|
36 * Cells are identified by zero-based indices from top-left to bottom-right. |
36 */ |
37 */ |
37 public final class Field extends JPanel { |
38 public final class Field extends JPanel { |
38 private SudokuTextField[][] cells; |
39 private SudokuTextField[][] cells; |
39 |
40 |
|
41 /** |
|
42 * Constructs a new 9x9 Sudoku grid. |
|
43 */ |
40 public Field() { |
44 public Field() { |
41 setBackground(Color.WHITE); |
45 setBackground(Color.WHITE); |
42 |
46 |
43 setLayout(new GridBagLayout()); |
47 setLayout(new GridBagLayout()); |
44 GridBagConstraints c = new GridBagConstraints(); |
48 GridBagConstraints c = new GridBagConstraints(); |
45 c.insets = new Insets(5, 5, 5, 5); |
49 c.insets = new Insets(5, 5, 5, 5); |
46 |
50 |
47 cells = new SudokuTextField[9][9]; |
51 cells = new SudokuTextField[9][9]; |
48 for (int x = 0 ; x < 9 ; x++) { |
52 for (int x = 0; x < 9; x++) { |
49 for (int y = 0 ; y < 9 ; y++) { |
53 for (int y = 0; y < 9; y++) { |
50 cells[x][y] = new SudokuTextField(); |
54 cells[x][y] = new SudokuTextField(); |
51 c.gridx = x; |
55 c.gridx = x; |
52 c.gridy = y; |
56 c.gridy = y; |
53 add(cells[x][y], c); |
57 add(cells[x][y], c); |
54 } |
58 } |
55 } |
59 } |
56 } |
60 } |
57 |
61 |
|
62 /** |
|
63 * Paints the grid and all contained cells. |
|
64 * |
|
65 * @param graphics the graphics context |
|
66 */ |
58 @Override |
67 @Override |
59 public void paint(Graphics graphics) { |
68 public void paint(Graphics graphics) { |
60 final int w = getWidth(); |
69 final int w = getWidth(); |
61 final int h = getHeight(); |
70 final int h = getHeight(); |
62 final int cw = w / 9; |
71 final int cw = w / 9; |
63 final int ch = h / 9; |
72 final int ch = h / 9; |
64 |
73 |
65 BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); |
74 BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); |
66 Graphics2D g = img.createGraphics(); |
75 Graphics2D g = img.createGraphics(); |
67 g.setBackground(Color.WHITE); |
76 g.setBackground(Color.WHITE); |
68 g.clearRect(0, 0, w, h); |
77 g.clearRect(0, 0, w, h); |
69 |
78 |
70 g.setColor(Color.BLACK); |
79 g.setColor(Color.BLACK); |
71 g.drawRect(1, 1, w-2, h-2); |
80 g.drawRect(1, 1, w - 2, h - 2); |
72 g.drawRect(2, 2, w-4, h-4); |
81 g.drawRect(2, 2, w - 4, h - 4); |
73 for (int x = cw ; x < w ; x += cw) { |
82 for (int x = cw; x < w; x += cw) { |
74 for (int y = ch ; y < h ; y += ch) { |
83 for (int y = ch; y < h; y += ch) { |
75 g.drawLine(x, 2, x, h-2); |
84 g.drawLine(x, 2, x, h - 2); |
76 g.drawLine(2, y, w-2, y); |
85 g.drawLine(2, y, w - 2, y); |
77 if ((x / cw) % 3 == 0) { |
86 if ((x / cw) % 3 == 0) { |
78 g.drawLine(x+1, 2, x+1, h-2); |
87 g.drawLine(x + 1, 2, x + 1, h - 2); |
79 } |
88 } |
80 if ((y / ch) % 3 == 0) { |
89 if ((y / ch) % 3 == 0) { |
81 g.drawLine(2, y+1, w-2, y+1); |
90 g.drawLine(2, y + 1, w - 2, y + 1); |
82 } |
91 } |
83 } |
92 } |
84 } |
93 } |
85 |
94 |
86 graphics.drawImage(img, 0, 0, this); |
95 graphics.drawImage(img, 0, 0, this); |
87 super.paintChildren(graphics); |
96 super.paintChildren(graphics); |
88 } |
97 } |
89 |
98 |
|
99 /** |
|
100 * Checks whether a cell is empty |
|
101 * |
|
102 * @param x horizontal position |
|
103 * @param y vertical position |
|
104 * @return true if the cell is empty, false otherwise |
|
105 */ |
90 public boolean isCellEmpty(int x, int y) { |
106 public boolean isCellEmpty(int x, int y) { |
91 return getCellValue(x, y) == 0; |
107 return getCellValue(x, y) == 0; |
92 } |
108 } |
93 |
109 |
|
110 /** |
|
111 * Returns value of a specific cell. |
|
112 * |
|
113 * @param x horizontal position |
|
114 * @param y vertical position |
|
115 * @return the cell's value |
|
116 */ |
94 public int getCellValue(int x, int y) { |
117 public int getCellValue(int x, int y) { |
95 return cells[x][y].getValue(); |
118 return cells[x][y].getValue(); |
96 } |
119 } |
97 |
120 |
|
121 /** |
|
122 * Sets the value of a specific cell. |
|
123 * |
|
124 * @param x horizontal position |
|
125 * @param y vertical position |
|
126 * @param v the cells value |
|
127 */ |
98 public void setCellValue(int x, int y, int v) { |
128 public void setCellValue(int x, int y, int v) { |
99 cells[x][y].setValue(v); |
129 cells[x][y].setValue(v); |
100 } |
130 } |
101 |
131 |
|
132 /** |
|
133 * Clears the value of a specific cell. |
|
134 * |
|
135 * @param x horizontal position |
|
136 * @param y vertical position |
|
137 */ |
102 public void clearCellValue(int x, int y) { |
138 public void clearCellValue(int x, int y) { |
103 setCellValue(x, y, 0); |
139 setCellValue(x, y, 0); |
104 } |
140 } |
105 |
141 |
|
142 /** |
|
143 * Sets the modified state of a specific cell. |
|
144 * |
|
145 * @param x horizontal position |
|
146 * @param y vertical position |
|
147 * @param modified the modified state |
|
148 */ |
106 public void setCellModified(int x, int y, boolean modified) { |
149 public void setCellModified(int x, int y, boolean modified) { |
107 cells[x][y].setModified(modified); |
150 cells[x][y].setModified(modified); |
108 } |
151 } |
109 |
152 |
|
153 /** |
|
154 * Sets the modified state of all cells. |
|
155 * |
|
156 * @param modified the modified state |
|
157 */ |
110 public void setAllCellsModified(boolean modified) { |
158 public void setAllCellsModified(boolean modified) { |
111 for (int x = 0 ; x < 9 ; x++) { |
159 for (int x = 0; x < 9; x++) { |
112 for (int y = 0 ; y < 9 ; y++) { |
160 for (int y = 0; y < 9; y++) { |
113 cells[x][y].setModified(modified); |
161 cells[x][y].setModified(modified); |
114 } |
162 } |
115 } |
163 } |
116 } |
164 } |
117 |
165 |
|
166 /** |
|
167 * Checks whether any cell is modified. |
|
168 * |
|
169 * @return true if any cell is modified, false otherwise |
|
170 */ |
118 public boolean isAnyCellModified() { |
171 public boolean isAnyCellModified() { |
119 for (int x = 0 ; x < 9 ; x++) { |
172 for (int x = 0; x < 9; x++) { |
120 for (int y = 0 ; y < 9 ; y++) { |
173 for (int y = 0; y < 9; y++) { |
121 if (cells[x][y].isModified()) { |
174 if (cells[x][y].isModified()) { |
122 return true; |
175 return true; |
123 } |
176 } |
124 } |
177 } |
125 } |
178 } |
126 return false; |
179 return false; |
127 } |
180 } |
128 |
181 |
|
182 /** |
|
183 * Clears all cells. |
|
184 */ |
129 public void clear() { |
185 public void clear() { |
130 for (int x = 0 ; x < 9 ; x++) { |
186 for (int x = 0; x < 9; x++) { |
131 for (int y = 0 ; y < 9 ; y++) { |
187 for (int y = 0; y < 9; y++) { |
132 cells[x][y].setValue(0); |
188 cells[x][y].setValue(0); |
133 } |
189 } |
134 } |
190 } |
135 } |
191 } |
136 |
192 |
|
193 /** |
|
194 * Returns a square identified by square coordinates. |
|
195 * <p> |
|
196 * Cells within the square are identified by the same coordinate system. |
|
197 * |
|
198 * @param x horizontal position from 0 to 2 |
|
199 * @param y vertical position from 0 to 2 |
|
200 * @return a two-dimensional array containing the square cell values |
|
201 */ |
137 public int[][] getSquare(int x, int y) { |
202 public int[][] getSquare(int x, int y) { |
138 if (x < 0 || x > 2 || y < 0 || y > 2) { |
203 if (x < 0 || x > 2 || y < 0 || y > 2) { |
139 throw new IllegalArgumentException("Invalid square coordinates"); |
204 throw new IllegalArgumentException("Invalid square coordinates"); |
140 } |
205 } |
141 int[][] square = new int[3][3]; |
206 int[][] square = new int[3][3]; |
142 |
207 |
143 for (int u = 0 ; u < 3 ; u++) { |
208 for (int u = 0; u < 3; u++) { |
144 for (int v = 0 ; v < 3 ; v++) { |
209 for (int v = 0; v < 3; v++) { |
145 square[u][v] = getCellValue(3*x+u, 3*y+v); |
210 square[u][v] = getCellValue(3 * x + u, 3 * y + v); |
146 } |
211 } |
147 } |
212 } |
148 |
213 |
149 return square; |
214 return square; |
150 } |
215 } |
151 |
216 |
|
217 /** |
|
218 * Returns an entire row. |
|
219 * |
|
220 * @param y the row position |
|
221 * @return an array containing the row values |
|
222 */ |
152 public int[] getRow(int y) { |
223 public int[] getRow(int y) { |
153 if (y < 0 || y > 8) { |
224 if (y < 0 || y > 8) { |
154 throw new IllegalArgumentException("Invalid row number"); |
225 throw new IllegalArgumentException("Invalid row number"); |
155 } |
226 } |
156 int row[] = new int[9]; |
227 int row[] = new int[9]; |
157 |
228 |
158 for (int x = 0 ; x < 9 ; x++) { |
229 for (int x = 0; x < 9; x++) { |
159 row[x] = getCellValue(x, y); |
230 row[x] = getCellValue(x, y); |
160 } |
231 } |
161 |
232 |
162 return row; |
233 return row; |
163 } |
234 } |
164 |
235 |
|
236 /** |
|
237 * Returns an entire column |
|
238 * |
|
239 * @param x the column position |
|
240 * @return an array containing the column values |
|
241 */ |
165 public int[] getColumn(int x) { |
242 public int[] getColumn(int x) { |
166 if (x < 0 || x > 8) { |
243 if (x < 0 || x > 8) { |
167 throw new IllegalArgumentException("Invalid column number"); |
244 throw new IllegalArgumentException("Invalid column number"); |
168 } |
245 } |
169 int column[] = new int[9]; |
246 int column[] = new int[9]; |
170 |
247 |
171 for (int y = 0 ; y < 9 ; y++) { |
248 for (int y = 0; y < 9; y++) { |
172 column[y] = getCellValue(x, y); |
249 column[y] = getCellValue(x, y); |
173 } |
250 } |
174 |
251 |
175 return column; |
252 return column; |
176 } |
253 } |
177 } |
254 } |