Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
214
Task/15-puzzle-game/Java/15-puzzle-game.java
Normal file
214
Task/15-puzzle-game/Java/15-puzzle-game.java
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
package fifteenpuzzle;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.Random;
|
||||
import javax.swing.*;
|
||||
|
||||
class FifteenPuzzle extends JPanel {
|
||||
|
||||
private final int side = 4;
|
||||
private final int numTiles = side * side - 1;
|
||||
|
||||
private final Random rand = new Random();
|
||||
private final int[] tiles = new int[numTiles + 1];
|
||||
private final int tileSize;
|
||||
private int blankPos;
|
||||
private final int margin;
|
||||
private final int gridSize;
|
||||
private boolean gameOver;
|
||||
|
||||
private FifteenPuzzle() {
|
||||
final int dim = 640;
|
||||
|
||||
margin = 80;
|
||||
tileSize = (dim - 2 * margin) / side;
|
||||
gridSize = tileSize * side;
|
||||
|
||||
setPreferredSize(new Dimension(dim, dim + margin));
|
||||
setBackground(Color.WHITE);
|
||||
setForeground(new Color(0x6495ED)); // cornflowerblue
|
||||
setFont(new Font("SansSerif", Font.BOLD, 60));
|
||||
|
||||
gameOver = true;
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (gameOver) {
|
||||
newGame();
|
||||
|
||||
} else {
|
||||
|
||||
int ex = e.getX() - margin;
|
||||
int ey = e.getY() - margin;
|
||||
|
||||
if (ex < 0 || ex > gridSize || ey < 0 || ey > gridSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
int c1 = ex / tileSize;
|
||||
int r1 = ey / tileSize;
|
||||
int c2 = blankPos % side;
|
||||
int r2 = blankPos / side;
|
||||
|
||||
int clickPos = r1 * side + c1;
|
||||
|
||||
int dir = 0;
|
||||
if (c1 == c2 && Math.abs(r1 - r2) > 0) {
|
||||
dir = (r1 - r2) > 0 ? 4 : -4;
|
||||
|
||||
} else if (r1 == r2 && Math.abs(c1 - c2) > 0) {
|
||||
dir = (c1 - c2) > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
if (dir != 0) {
|
||||
do {
|
||||
int newBlankPos = blankPos + dir;
|
||||
tiles[blankPos] = tiles[newBlankPos];
|
||||
blankPos = newBlankPos;
|
||||
} while (blankPos != clickPos);
|
||||
tiles[blankPos] = 0;
|
||||
}
|
||||
|
||||
gameOver = isSolved();
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
});
|
||||
|
||||
newGame();
|
||||
}
|
||||
|
||||
private void newGame() {
|
||||
do {
|
||||
reset();
|
||||
shuffle();
|
||||
} while (!isSolvable());
|
||||
gameOver = false;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
for (int i = 0; i < tiles.length; i++) {
|
||||
tiles[i] = (i + 1) % tiles.length;
|
||||
}
|
||||
blankPos = tiles.length - 1;
|
||||
}
|
||||
|
||||
private void shuffle() {
|
||||
// don't include the blank space in the shuffle, leave it
|
||||
// in the home position
|
||||
int n = numTiles;
|
||||
while (n > 1) {
|
||||
int r = rand.nextInt(n--);
|
||||
int tmp = tiles[r];
|
||||
tiles[r] = tiles[n];
|
||||
tiles[n] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Only half the permutations of the puzzle are solvable.
|
||||
|
||||
Whenever a tile is preceded by a tile with higher value it counts
|
||||
as an inversion. In our case, with the blank space in the home
|
||||
position, the number of inversions must be even for the puzzle
|
||||
to be solvable.
|
||||
|
||||
See also:
|
||||
www.cs.bham.ac.uk/~mdr/teaching/modules04/java2/TilesSolvability.html
|
||||
*/
|
||||
private boolean isSolvable() {
|
||||
int countInversions = 0;
|
||||
for (int i = 0; i < numTiles; i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
if (tiles[j] > tiles[i]) {
|
||||
countInversions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return countInversions % 2 == 0;
|
||||
}
|
||||
|
||||
private boolean isSolved() {
|
||||
if (tiles[tiles.length - 1] != 0) {
|
||||
return false;
|
||||
}
|
||||
for (int i = numTiles - 1; i >= 0; i--) {
|
||||
if (tiles[i] != i + 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void drawGrid(Graphics2D g) {
|
||||
for (int i = 0; i < tiles.length; i++) {
|
||||
int r = i / side;
|
||||
int c = i % side;
|
||||
int x = margin + c * tileSize;
|
||||
int y = margin + r * tileSize;
|
||||
|
||||
if (tiles[i] == 0) {
|
||||
if (gameOver) {
|
||||
g.setColor(Color.GREEN);
|
||||
drawCenteredString(g, "\u2713", x, y);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
g.setColor(getForeground());
|
||||
g.fillRoundRect(x, y, tileSize, tileSize, 25, 25);
|
||||
g.setColor(Color.blue.darker());
|
||||
g.drawRoundRect(x, y, tileSize, tileSize, 25, 25);
|
||||
g.setColor(Color.WHITE);
|
||||
|
||||
drawCenteredString(g, String.valueOf(tiles[i]), x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawStartMessage(Graphics2D g) {
|
||||
if (gameOver) {
|
||||
g.setFont(getFont().deriveFont(Font.BOLD, 18));
|
||||
g.setColor(getForeground());
|
||||
String s = "click to start a new game";
|
||||
int x = (getWidth() - g.getFontMetrics().stringWidth(s)) / 2;
|
||||
int y = getHeight() - margin;
|
||||
g.drawString(s, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawCenteredString(Graphics2D g, String s, int x, int y) {
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
int asc = fm.getAscent();
|
||||
int des = fm.getDescent();
|
||||
|
||||
x = x + (tileSize - fm.stringWidth(s)) / 2;
|
||||
y = y + (asc + (tileSize - (asc + des)) / 2);
|
||||
|
||||
g.drawString(s, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintComponent(Graphics gg) {
|
||||
super.paintComponent(gg);
|
||||
Graphics2D g = (Graphics2D) gg;
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
|
||||
RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
drawGrid(g);
|
||||
drawStartMessage(g);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JFrame f = new JFrame();
|
||||
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
f.setTitle("Fifteen Puzzle");
|
||||
f.setResizable(false);
|
||||
f.add(new FifteenPuzzle(), BorderLayout.CENTER);
|
||||
f.pack();
|
||||
f.setLocationRelativeTo(null);
|
||||
f.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue