This was done as an assignment in school. As I am still learning some of the basic parts of Java be merciless when it comes to my code. As it is an assignment, some things are unchangeable. The specification requires:
Swing. So no third-party library is allowed.Cellclass withgetCol()andgetRow()methods.- For the final product to be a Slide-Game.
![]()
Some extra features that I tried to implement in a good way.
- Dyanmic handle for rows and cols. It should work for anything over 2 rows and 2 cols.
- Victory check and click tracker.
GUI.java
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.ArrayList; import java.util.List; public class GUI implements ActionListener { public static final int WINDOW_MIN_X = 240; public static final int WINDOW_MIN_Y = 200; public static final int COLS = 4; public static final int ROWS = 4; public static final int HGAP = 3; public static final int VGAP = 3; public static final int NUMBER_OF_CELLS = ROWS * COLS; private JFrame frame; private List<Cell> buttons = new ArrayList<>(); private List<Cell> correct = new ArrayList<>(); private Cell emptyButton; private int movesCounter; /** * Constructor for objects of class GUI */ public GUI () { frame = new JFrame("Slide Game"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); frame.setMinimumSize(new Dimension (WINDOW_MIN_X, WINDOW_MIN_Y)); frame.setLayout (new GridLayout (ROWS, COLS, HGAP, VGAP)); for( Integer i = NUMBER_OF_CELLS-1; i >= 0 ; i-- ) { createCell (i); } emptyButton = buttons.get (NUMBER_OF_CELLS-1); frame.setVisible(true); frame.pack(); setVictoryCondition (); } public void actionPerformed (ActionEvent e) { if (checkNeighbour((Cell)e.getSource())) { swap ((Cell)e.getSource()); movesCounter++; checkVictory (); } else { Toolkit.getDefaultToolkit().beep(); } } /** * createCell (String s) * * Creates a Cell and adds an ActionListener * * @param String s */ private void createCell (int v) { Cell c = new Cell (v); c.addActionListener( (ActionEvent e) -> {actionPerformed(e);} ); buttons.add(c); frame.add(c); } /** * checkNeighbour (Cell c) * * Checks if c is within 1 grid of emptyButton (non-diagonal) * * @param Cell c * * @return false if c is more than one grid away from emptyButton */ private boolean checkNeighbour (Cell c) { int x = Math.abs(c.getCol() - emptyButton.getCol()); int y = Math.abs(c.getRow() - emptyButton.getRow()); if (!(x == 0 && y == 1 || y == 0 && x == 1)) { return false; } return true; } /** * swap (Cell c) * * Swaps c with emptyButton * * @param Cell c */ private void swap (Cell c) { // swap c and empty String tmp = emptyButton.getText (); emptyButton.setText (c.getText ()); c.setText (tmp); // update reference to empty button emptyButton = c; } /** * setVictoryCondition () * * Initiates correct list */ private void setVictoryCondition () { for (Integer i = 1; i < NUMBER_OF_CELLS; i++) { correct.add (new Cell (i)); } correct.add(new Cell (0)); } /** * checkVictory () * * Compares buttons to correct lists, if match declare victory! */ private void checkVictory () { for (int i = 0; i < NUMBER_OF_CELLS; i++) { if (!(buttons.get(i).getText ().equals( correct.get(i).getText ()))) { return; } } JOptionPane.showMessageDialog(null, "You achieved victory in " + movesCounter + " moves.", "Congratulations!", JOptionPane.INFORMATION_MESSAGE); } } Cell.java
import javax.swing.*; public class Cell extends JButton { private static final long serialVersionUID = 8822510600483479089L; private int row; private int col; public Cell (Integer value) { if (value == 0) { setText (" "); } else { setText(value.toString()); } row = GUI.NUMBER_OF_CELLS / GUI.COLS-1 - ( value / GUI.COLS); col = GUI.NUMBER_OF_CELLS-1 - (row*GUI.COLS + value); } public int getCol (){ return col; } public int getRow (){ return row; } } In short, the code is working. I am fairly happy with the result. I wonder if (and if so where) there are room for improvements.