-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathButtonPanel.java
331 lines (284 loc) · 10.6 KB
/
ButtonPanel.java
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/* ------------------------------------------------
* 8 Tiles GUI
*
* Class: CS 342, Fall 2016
* System: Windows 10, IntelliJ IDE
* Author: Five
* ------------------------------------------------- */
import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import static java.lang.System.exit;
/**
* GUI class which creates functionality for the tile board based upon the actual underlying board
* Handles the creation of the tile board as well as movement of tiles
*/
public class ButtonPanel extends JPanel
{
private Board gameBoard; //Underlying board from which the GUI is based
private JPanel gridPanel; //3x3 grid of tiles
private int[] inputArr; //User's input of choosing board
private int numInput; //Number of input the user has entered
private int solIterator; //Iterator for the autoSolution
public ButtonPanel(boolean user)
{
//Constructor and set to BorderLayout
super();
this.setLayout(new BorderLayout());
//Construct the grid which will contain the tiles
gridPanel = new JPanel();
gridPanel.setLayout(new GridLayout(Constants.BOARD_SIZE,Constants.BOARD_SIZE));
//Add the grid to the overarching JPanel
this.add(gridPanel,BorderLayout.CENTER);
gameBoard = null;
//Create random board or let the user set-up the board
if(!user)
{
initRandBoard();
}
else
{
numInput = 0;
inputArr = new int[Constants.BOARD_SIZE*Constants.BOARD_SIZE];
initUserBoard();
}
}
/**
* Returns the underlying Board structure
*/
public Board getGameBoard() {
return gameBoard;
}
/**
* Create randomly generated board and corresponding grid GUI
*/
private void initRandBoard()
{
gameBoard = new Board();
JButton tile;
//Loop through board grid and create corresponding buttons
int[][] tempGrid = gameBoard.getGrid();
for(int i=0;i<Constants.BOARD_SIZE;i++)
{
for(int j=0;j<Constants.BOARD_SIZE;j++)
{
int tileNum = tempGrid[i][j];
if(tileNum!=0)
{
tile = new JButton(Integer.toString(tileNum));
}
else
{
tile = new JButton(" ");
}
tile.addActionListener(new MoveHandler());
gridPanel.add(tile);
}
}
//Add options of the Solve and displaying Hueristic Value
addGameOptions();
}
/**
* Create user initilized board and corresponding grid GUI
*/
private void initUserBoard()
{
//Add nine blank buttons to the grid GUI
for(int i=0;i<(Constants.BOARD_SIZE*Constants.BOARD_SIZE);i++)
{
JButton tile = new JButton("Click Me [" + i + "]");
tile.addActionListener(new CreationHandler());
gridPanel.add(tile);
}
}
/**
* Removes all and Redraws the grid GUI based upon lastest
* update of the underlying game board
* @param user : Whether or not there is user input (should happen at most once)
*/
private void updatePanel(boolean user)
{
gridPanel.removeAll();
this.removeAll();
//Create a new board based upon user input if flag is set
if(user)
{
gameBoard = new Board(inputArr);
}
//Goto grid and create corresponding buttons
int[][] tempGrid = gameBoard.getGrid();
JButton tile;
for(int i=0;i<Constants.BOARD_SIZE;i++)
{
for(int j=0;j<Constants.BOARD_SIZE;j++)
{
int tileNum = tempGrid[i][j];
if(tileNum!=0)
{
tile = new JButton(Integer.toString(tileNum)); //Create corresponding JButton
}
else
{
tile = new JButton(" "); //Since tileNum is zero, make the button blank
}
tile.addActionListener(new MoveHandler()); //Set the action listener to be the move handler
gridPanel.add(tile);
}
}
gridPanel.revalidate();
this.add(gridPanel,BorderLayout.CENTER);
addGameOptions();
this.revalidate();
}
/**
* Add an auto solve option and a display for the Heuristic Value of the current board
*/
private void addGameOptions()
{
//Create Solve Button and Heuristic Label
JButton solveGame = new JButton("SOLVE!!");
String score = Integer.toString(gameBoard.gethVal());
JLabel hValDisplay = new JLabel("Board Score: " + score);
solveGame.addActionListener(new SolutionHandler());
//Add to the JPanel and Refresh the Panel
this.add(solveGame,BorderLayout.NORTH);
this.add(hValDisplay,BorderLayout.SOUTH);
this.revalidate();
}
/**
* Update the user input array based upon the button that is chosen
*/
private void userInputUpdate(String chosen)
{
for(int i=0;i<9;i++)
{
if(chosen.contains(Integer.toString(i)))
{
inputArr[i] = numInput;
numInput++;
}
}
}
/**
* ActionListener class which handles the auto solution of the board
*/
private class SolutionHandler implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//Create SearchTree and auto solve
SearchTree solution = new SearchTree();
//Auto solve and get the list of taken steps
ArrayList<Board> solvedList = solution.getSolvedBoards();
boolean isSolved = solution.autoSolve(gameBoard);
solIterator = 0;
//Timer used to update GUI every 300ms
final Timer timer = new Timer(300, null);
//ActionListener for timer used to update board GUI every 300ms
ActionListener listener = new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e) {
//Get a board from the list and display it
if (solIterator < solvedList.size()) {
gameBoard = solvedList.get(solIterator);
updatePanel(false);
solIterator++;
}
//If iterated through entire list...
else
{
//Stop the timer
timer.stop();
//If solved, display puzzle has been solved
if(isSolved)
{
JOptionPane.showMessageDialog(ButtonPanel.this, "Puzzle has been solved!");
}
//If not solved, display best board that was found
else
{
JOptionPane.showMessageDialog(ButtonPanel.this, "All solutions have been tried. There is no solution. " +
"Here is the best board!");
gameBoard =solution.getBestBoard();
updatePanel(false);
}
}
}
}; //End ActionListener
//Start the timer
timer.addActionListener(listener);
timer.start();
}
}
/**
* ActionListener class which handles user set-up of board
*/
private class CreationHandler implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//If chosen tile has not been assigned, assign it to a number
String chosenButton = event.getActionCommand();
if(chosenButton.contains("Click Me"))
{
JButton temp = (JButton)event.getSource();
temp.setText(Integer.toString(numInput));
userInputUpdate(chosenButton);
}
//If user has picked all tiles, create new board based upon the input and display it
if(numInput == 9)
{
updatePanel(true);
}
//If user has already assigned the clicked tile, display error message
if(!(chosenButton.contains("Click Me")))
{
JOptionPane.showMessageDialog(ButtonPanel.this, event.getActionCommand() + " Has Already Been Set");
}
}
}
/**
* ActionListener class which handles movement of a tile on the grid
*/
private class MoveHandler implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
//Cannot move blank tile
if(event.getActionCommand().equals(" "))
{
JOptionPane.showMessageDialog(ButtonPanel.this, event.getActionCommand() + " Is Not A Valid Move");
}
else
{
//Obtain tile chosen and check if valid
int toMove = Integer.parseInt(event.getActionCommand());
//If valid move...
if(gameBoard.checkMove(toMove))
{
//Move on underlying board structure
gameBoard.move(toMove);
System.out.println("");
gameBoard.printBoard();
gameBoard.printHeuristic();
//Update GUI respectivley
ButtonPanel.this.updatePanel(false);
//If hVal after move is zero, display game won message
if(gameBoard.gethVal()==0)
{
JOptionPane.showMessageDialog(ButtonPanel.this, "YOU'VE SOLVED THE PUZZLE!");
//exit(0);
}
}
//Not a valid move, display error message
else
{
JOptionPane.showMessageDialog(ButtonPanel.this, event.getActionCommand() + " Is Not A Valid Move");
}
}
}
}
} //End ButtonPanel