CISS-111 GUI Project Extra Credit
In this project you will be revisiting some JavaFX components in addition to building some game logic and reacquainting ourselves with inheritance.
The traditional 15-puzzle is relatively easy to solve. There are 15 tiles in a 4×4 grid. The missing 16th tile allows the tiles to be slid around the field.
Ideally, the puzzle is scrambled by one person, who then times the other person to see how long it takes them to solve it. The game itself has been seen as numbers, letters, and pictures. Solutions are often in a variety of forms. In the event of a picture, the solution is restoring the original picture. With numbers and letters, it is traditionally solved when the tiles are arranged in order from left to right, then top to bottom, as shown below.
For this project, you will:
- Create a JavaFX application.
- Manage a single-dimensioned array to hold the buttons.
Button
s will show the numerical values 1 through 15 except for the blank button. This will have the empty string.- Implement the
EventHandler
interface and thehandle()
method to move buttons around. - The
Scene
will be 300×300. - We recommend using
setMinWidth(75)
andsetMinHeight(75)
for the buttons.
Here are a few lines to jump-start your project:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.event.EventHandler;
import javafx.event.ActionEvent;
import java.util.Arrays;
import java.util.Collections;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
public class FifteenPuzzle extends Application implements EventHandler<ActionEvent> {
GridPane p = new GridPane();
Button[] pieces = new Button[16];
@Override
public void handle (ActionEvent e) {
// I need way more code!
// Also, this is where the button change decisions are made!
}
//...
public static void main(String[] args) {
// standard JavaFX Application object launch
launch(args);
}
}
Now, the general path is to shuffle the buttons and place them on the GridPane
. Sadly, it is not quite that simple because, in the traditional game, you would have shuffled the pieces based on your ability to work around the blank space. The puzzle was always solvable because it started from a solved position. When the pieces are randomly shuffled, there is no guarantee it is solvable.
Now, imagine you removed all the tiles and placed them back on the board in random order. Because you did not follow a path from a solved state, you cannot guarantee that the puzzle is solvable. However, there is some clever math that can make that determination.
If you are interested, follow the link in the code below to learn more about detecting if a puzzle is solvable. Otherwise, you can rest assured that the code will detect a solvable puzzle!
Mathematically, this can be determined, so here is a method to help you on your way:
/*
* Checks the inversion counts as described in
* http://mathworld.wolfram.com/15Puzzle.html
*/
private boolean solvable(Button[] p) {
int n, blank, brn;
int sum = 0, x, y;
blank = findPiece("");
brn = blank / 4 + 1;
for (x = 0; x < 16; x++) {
if (x == blank)
continue;
n = Integer.parseInt(p[x].getText());
for (y = x+1; y < 16; y++) {
if (y == blank)
continue;
if (Integer.parseInt(p[y].getText()) < n)
sum ++;
}
}
System.out.println("sum = " + sum + " brn = " + brn + " ans = " + (sum+brn));
if ((sum+brn) % 2 == 0)
return true;
else
return false;
}
The method is provided to help you determine if a puzzle configuration is solvable. This should be called before a new puzzle is displayed. If this method returns false, you should shuffle up a new one until it is solvable.
Note that solvable()
requires the use of a findPiece()
method that is not provided here. You have to write it. (We will talk about this in class!)
It is also recommended that you write a method complete()
that returns a boolean
so that you know when the solution has been reached. (We will talk about this in class!)
You should present the user with a shuffled game board as shown below:
Figure 2: Shuffled/Scrambled but a solvable puzzle.
When a button is pressed you will need to determine if the button can be exchanged with the blank space. This is the work to be done by the handle()
method that you will need to write. It is strongly suggested that you remove()
all the buttons from the GridPane
, make your determination of which two will be swapped (assuming there is a blank adjacency) and then add()
them to the GridPane
again.
When they complete the puzzle, you should also display a message that it is done and then end the program.