-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGUI.java
More file actions
202 lines (189 loc) · 8.26 KB
/
GUI.java
File metadata and controls
202 lines (189 loc) · 8.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import java.awt.*; // Uses AWT's Layout Managers
import java.awt.event.*; // Uses AWT's Event Handlers
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
//import java.util.concurrent.Flow;
import javax.swing.*; // Uses Swing's Container/Components
/**
* The Sudoku game.
* To solve the number puzzle, each row, each column, and each of the
* nine 3×3 sub-grids shall contain all of the digits from 1 to 9
*/
public class GUI extends JFrame {
// Constants for the game
static final int GRID_SIZE = 9;
static final int SET_SIZE = (int)Math.sqrt(GRID_SIZE);
// UI Constants
static final int CELL_SIZE = 60;
static final int DISPLAY_WIDTH = CELL_SIZE * GRID_SIZE;
static final int DISPLAY_HEIGHT = DISPLAY_WIDTH;
static final Color FREE_CELL_BGCOLOR = Color.CYAN;
static final Color CORRECT_NUM_COLOR = Color.GREEN;
static final Color INCORRECT_NUM_COLOR = Color.RED;
static final Color FULL_CELL_BGCOLOR = Color.LIGHT_GRAY;
static final Color FULL_TEXT_COLOR = Color.BLACK;
// Game board Data
private JTextField[][] cells = new JTextField[GRID_SIZE][GRID_SIZE];
//
// Puzzle to be solved and the mask (which can be used to control the
// difficulty level).
// Hardcoded here. Extra credit for automatic puzzle generation
// with various difficulty levels.
int[][] _puzzle;
Tile[][] _solution;
// For testing, open only 2 cells.
private Board _myBoard;
/**
* Constructor to setup the game and the UI Components
*/
public GUI(int[][] puzzle) {
_puzzle = puzzle;
_myBoard = new Board(puzzle, GRID_SIZE);
JFrame myFrame = new JFrame("Sudoku");
FlowLayout layout = new FlowLayout();
myFrame.setLayout(layout);
JButton solveButton = new JButton("Solve");
solveButton.addActionListener(new SolveListener());
myFrame.add(solveButton);
Container cp = getContentPane();
cp.setLayout(new GridLayout(GRID_SIZE, GRID_SIZE)); // 9x9 GridLayout
// Allocate a common listener as the ActionEvent listener for all the
// JTextFields
// ... [TODO 3] (Later) ....
InputListener listener = new InputListener();
// Construct 9x9 JTextFields and add to the content-pane
for (int row = 0; row < GRID_SIZE; ++row) {
for (int col = 0; col < GRID_SIZE; ++col) {
cells[row][col] = new JTextField(); // Allocate element of array
cp.add(cells[row][col]); // ContentPane adds JTextField
// _myBoard.addTile(new Tile(row, col, GRID_SIZE));
if (_puzzle[row][col] == 0) {
cells[row][col].setText(""); // set to empty string
cells[row][col].setEditable(true);
cells[row][col].setBackground(FREE_CELL_BGCOLOR);
// Add ActionEvent listener to process the input
// ... [TODO 4] (Later) ...
cells[row][col].addActionListener(listener); // For all editable rows and cols
} else {
// Tile myTile = _myBoard.getTile(row, col);
// myTile.setVal(_puzzle[row][col]);
cells[row][col].setText(_puzzle[row][col] + "");
cells[row][col].setEditable(false);
cells[row][col].setBackground(FULL_CELL_BGCOLOR);
cells[row][col].setForeground(FULL_TEXT_COLOR);
}
// Beautify all the cells
cells[row][col].setHorizontalAlignment(JTextField.CENTER);
}
}
// Set the size of the content-pane and pack all the components
// under this container.
cp.setPreferredSize(new Dimension(DISPLAY_WIDTH, DISPLAY_HEIGHT));
myFrame.add(cp);
myFrame.pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Handle window closing
myFrame.setTitle("Sudoku");
myFrame.setVisible(true);
}
/** The entry main() entry method */
public static void main(String[] args) {
// [TODO 1] (Now)
int[][] puzzle = scanPuzzle("flash");
GUI myGUI = new GUI(puzzle);
// myGUI._myBoard.solve();
// myGUI._solution = myGUI._myBoard._tiles;
}
public static int[][] scanPuzzle(String diff) {
File puzzleFile = new File("puzzles/" + diff + "1.pz");
if (puzzleFile.exists()){
try {
Scanner puzzleScanner = new Scanner(puzzleFile);
int [][] myPuzzle = new int[9][9];
for (int i = 0; i < 9; i += 1) {
for (int j = 0; j < 9; j += 1) {
myPuzzle[i][j] = puzzleScanner.nextInt();
}
}
return myPuzzle;
} catch(FileNotFoundException f){
return null;
}
}
return null;
}
// Define the Listener Inner Class
// ... [TODO 2] (Later) ...
// [TODO 2]
// Inner class to be used as ActionEvent listener for ALL JTextFields
private class SolveListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action performed");
_myBoard.solve();
_solution = _myBoard._tiles;
for (int row = 0; row < GRID_SIZE; ++row) {
for (int col = 0; col < GRID_SIZE; ++col) {
if (_puzzle[row][col] == 0) {
cells[row][col].setText(Integer.toString(_solution[row][col]._num));
cells[row][col].setBackground(Color.YELLOW);
}
}
}
}
}
private class InputListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// _myBoard.solve();
// All the 9*9 JTextFileds invoke this handler. We need to determine
// which JTextField (which row and column) is the source for this invocation.
int rowSelected = -1;
int colSelected = -1;
// Get the source object that fired the event
JTextField source = (JTextField)e.getSource();
// Scan JTextFileds for all rows and columns, and match with the source object
boolean found = false;
for (int row = 0; row < GRID_SIZE && !found; ++row) {
for (int col = 0; col < GRID_SIZE && !found; ++col) {
if (cells[row][col] == source) {
rowSelected = row;
colSelected = col;
found = true; // break the inner/outer loops
}
}
}
/*
* [TODO 5]
* 1. Get the input String via tfCells[rowSelected][colSelected].getText()
* 2. Convert the String to int via Integer.parseInt().
* 3. Assume that the solution is unique. Compare the input number with
* the number in the puzzle[rowSelected][colSelected]. If they are the same,
* set the background to green (Color.GREEN); otherwise, set to red (Color.RED).
*/
String input = cells[rowSelected][colSelected].getText();
Integer num = Integer.parseInt(input);
if (_solution[rowSelected][colSelected]._num != num) {
cells[rowSelected][colSelected].setBackground(INCORRECT_NUM_COLOR);
} else {
cells[rowSelected][colSelected].setBackground(CORRECT_NUM_COLOR);
}
/*
* [TODO 6] Check if the player has solved the puzzle after this move.
* You could update the masks[][] on correct guess, and check the masks[][] if
* any input cell pending.
*/
boolean solved = true;
for (int i = 0 ; i < GRID_SIZE; i += 1) {
for (int j = 0; j < GRID_SIZE; j += 1) {
if (num != _solution[i][j]._num) {
solved = false;
}
}
}
if (solved) {
JOptionPane.showMessageDialog(null, "Congratulations!");
}
}
}
}