The sliding puzzle game features a 3x3 grid with numbered tiles and one empty space. Players rearrnage tiles by sliding them into the empty position using keyboard controls.
Functionality
- Directional tile movement (arrow keys)
- Move counter tracking
- Multiple image sets (portratis/animals)
- Game reset capability
- Instant win cheat code (W key)
- Full image preview (A key)
- Victory condition detection
Implementation
Main Entry Class
public class PuzzleLauncher {
public static void main(String[] args) {
new PuzzleGameWindow();
}
}
Game Window Class
package ui;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.*;
import java.util.*;
public class PuzzleGameWindow extends JFrame implements KeyListener, ActionListener {
private JMenuItem portraitSet = new JMenuItem("Portraits");
private JMenuItem animalSet = new JMenuItem("Animals");
private JMenuItem restartGame = new JMenuItem("Restart");
private JMenuItem exitGame = new JMenuItem("Exit");
private String currentImagePath = "assets/portrait/set1-";
private List<String> portraitPaths = Arrays.asList(
"assets/portrait/set1-",
"assets/portrait/set2-",
"assets/portrait/set3-"
);
private List<String> animalPaths = Arrays.asList(
"assets/animal/cat-",
"assets/animal/dog-"
);
private int[][] gameBoard = new int[3][3];
private int blankRow = 0;
private int blankCol = 0;
private final int[][] solutionPattern = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 0}
};
private int moveCounter = 0;
public PuzzleGameWindow() {
configureWindow();
setupMenu();
initializeBoard();
renderTiles();
setVisible(true);
}
private void configureWindow() {
setSize(600, 650);
setTitle("Sliding Puzzle v1.0");
setAlwaysOnTop(true);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(null);
addKeyListener(this);
}
private void setupMenu() {
JMenuBar menuBar = new JMenuBar();
JMenu gameMenu = new JMenu("Game");
JMenu imageMenu = new JMenu("Themes");
imageMenu.add(portraitSet);
imageMenu.add(animalSet);
gameMenu.add(imageMenu);
gameMenu.add(restartGame);
gameMenu.add(exitGame);
menuBar.add(gameMenu);
setJMenuBar(menuBar);
portraitSet.addActionListener(this);
animalSet.addActionListener(this);
restartGame.addActionListener(this);
exitGame.addActionListener(this);
}
private void initializeBoard() {
List<Integer> positions = new ArrayList<>(Arrays.asList(0,1,2,3,4,5,6,7,8));
Collections.shuffle(positions);
for (int idx = 0; idx < 9; idx++) {
int row = idx / 3;
int col = idx % 3;
int value = positions.get(idx);
gameBoard[row][col] = value;
if (value == 0) {
blankRow = row;
blankCol = col;
}
}
moveCounter = 0;
}
private void renderTiles() {
getContentPane().removeAll();
if (checkVictory()) {
JLabel victoryBanner = new JLabel(new ImageIcon("assets/victory.png"));
victoryBanner.setBounds(0, 0, 600, 650);
getContentPane().add(victoryBanner);
} else {
JLabel movesDisplay = new JLabel("Moves: " + moveCounter);
movesDisplay.setBounds(10, 10, 100, 20);
getContentPane().add(movesDisplay);
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
int tileValue = gameBoard[row][col];
if (tileValue != 0) {
JLabel tile = new JLabel(new ImageIcon(currentImagePath + tileValue + ".png"));
tile.setBounds(col * 200, row * 216, 200, 216);
tile.setBorder(new BevelBorder(BevelBorder.RAISED));
getContentPane().add(tile);
}
}
}
}
getContentPane().revalidate();
getContentPane().repaint();
}
@Override
public void keyReleased(KeyEvent e) {
if (checkVictory()) return;
switch (e.getKeyCode()) {
case KeyEvent.VK_LEFT:
if (blankCol < 2) shiftTile(blankRow, blankCol + 1);
break;
case KeyEvent.VK_RIGHT:
if (blankCol > 0) shiftTile(blankRow, blankCol - 1);
break;
case KeyEvent.VK_UP:
if (blankRow < 2) shiftTile(blankRow + 1, blankCol);
break;
case KeyEvent.VK_DOWN:
if (blankRow > 0) shiftTile(blankRow - 1, blankCol);
break;
case KeyEvent.VK_A:
showCompleteImage();
break;
case KeyEvent.VK_W:
activateSolution();
break;
}
}
private void shiftTile(int srcRow, int srcCol) {
gameBoard[blankRow][blankCol] = gameBoard[srcRow][srcCol];
gameBoard[srcRow][srcCol] = 0;
blankRow = srcRow;
blankCol = srcCol;
moveCounter++;
renderTiles();
}
private void showCompleteImage() {
getContentPane().removeAll();
JLabel fullImage = new JLabel(new ImageIcon(currentImagePath + "full.png"));
fullImage.setBounds(0, 0, 600, 650);
getContentPane().add(fullImage);
getContentPane().revalidate();
getContentPane().repaint();
}
private void activateSolution() {
gameBoard = new int[][]{{1,2,3},{4,5,6},{7,8,0}};
blankRow = 2;
blankCol = 2;
moveCounter = 0;
renderTiles();
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == restartGame) {
initializeBoard();
renderTiles();
} else if (e.getSource() == exitGame) {
System.exit(0);
} else if (e.getSource() == portraitSet) {
int randIdx = new Random().nextInt(portraitPaths.size());
currentImagePath = portraitPaths.get(randIdx);
initializeBoard();
renderTiles();
} else if (e.getSource() == animalSet) {
int randIdx = new Random().nextInt(animalPaths.size());
currentImagePath = animalPaths.get(randIdx);
initializeBoard();
renderTiles();
}
}
private boolean checkVictory() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (gameBoard[i][j] != solutionPattern[i][j]) {
return false;
}
}
}
return true;
}
@Override public void keyPressed(KeyEvent e) {}
@Override public void keyTyped(KeyEvent e) {}
}