Java Swing Implementation of a Sliding Puzzle Game

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) {}
}

Tags: java swing puzzle game desktop

Posted on Thu, 30 Jul 2026 16:06:32 +0000 by MissiCoola