This is my first time working with Java Swing, so my program is a bit chaotic to say the least. The goal is to have an 8-puzzle take an image, divide it into 9 sectors, then place 8 of them in a specific order (Drop 1 for movement). The program works fine the first time through. Once it is solved it is supposed to randomize the JButton
components and allow you to solve again.The buttons Randomize, but do not allow me to move them. Any help is greatly appreciated.
Normally I would post just the code that I think would have the issue, but due to the chaotic nature of the code, I am posting my entire class.
EDIT: After going through the code line by line, the issue seems to be in the Order() method. If i remove the second "if" statement all together, the program works fine just does not randomize the components. (Same if i use "else" & "else if" for that statement)
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class JEightPuzzleFrame extends JFrame implements ActionListener {
JButton[] buttons = new JButton[9];
JButton[][] format = new JButton[3][3];
JPanel puzzle = new JPanel();
JPanel jp = new JPanel();
String path = null;
int h;
int w;
public JEightPuzzleFrame(String Title, String Path) {
super();
path = Path;
add(puzzle);
makeFrame();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(w + 10, h + 10);
setTitle(Title);
setResizable(false);
jp.setVisible(true);
}
public void makeFrame() {
puzzle.setVisible(true);
puzzle.setBounds(100, 100, 612, 519);
makeBtnImg();
puzzle.setLayout(new GridLayout(3, 3));
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzle.add(format[i][j]);
if (format[i][j] == buttons[8]) {
puzzle.remove(format[i][j]);
puzzle.add(jp);
}
}
}
}
public void makeBtnImg() {
try {
BufferedImage pic = ImageIO.read(new File(path));
jp.setSize(h, w);
h = pic.getHeight();
w = pic.getWidth();
int count = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
BufferedImage bimg = pic.getSubimage(i * w / 3, j * h / 3, w / 3, h / 3);
if (count < 9) {
buttons[count] = new JButton(new ImageIcon(bimg));
buttons[count].addActionListener(this);
}
count++;
}
}
order(true);
} catch (IOException e) {
}
}
public void order(boolean initial) {
if (initial == true) {
format[0][0] = buttons[8];
format[1][0] = buttons[4];
format[2][0] = buttons[1];
format[0][1] = buttons[0];
format[1][1] = buttons[7];
format[2][1] = buttons[2];
format[0][2] = buttons[3];
format[1][2] = buttons[6];
format[2][2] = buttons[5];
}
if (initial == false) {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int rd = (int) Math.random() * (9 - 0);
JButton temp = buttons[rd];
format[i][j] = temp;
}
}
}
refresh();
}
public void refresh() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzle.remove(format[i][j]);
}
}
puzzle.remove(jp);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
puzzle.add(format[i][j]);
if (format[i][j] == buttons[8]) {
puzzle.remove(format[i][j]);
puzzle.add(jp);
}
}
}
getContentPane().validate();
if (format[0][0] == buttons[0] && format[0][1] == buttons[3] && format[0][2] == buttons[6]
&& format[1][0] == buttons[1] && format[1][1] == buttons[4] && format[1][2] == buttons[7]
&& format[2][0] == buttons[2] && format[2][1] == buttons[5] && format[2][2] == buttons[8]) {
JOptionPane.showMessageDialog(null, "YOU WON!");
order(false);
}
}
@Override
public void actionPerformed(ActionEvent e) {
JButton temp;
JButton button = (JButton) e.getSource();
Dimension size = button.getSize();
int buttonX = button.getX();
int buttonY = button.getY();
int buttonPosX = buttonX / size.width;
int buttonPosY = buttonY / size.height;
int leftNeighbor = buttonPosX - 1;
int rightNeighbor = buttonPosX + 1;
int topNeighbor = buttonPosY - 1;
int bottomNeighbor = buttonPosY + 1;
int c = 0;
if (leftNeighbor >= 0 && format[buttonPosY][leftNeighbor] == buttons[8]) {
c = 1;
} else if (rightNeighbor < 3 && format[buttonPosY][rightNeighbor] == buttons[8]) {
c = 2;
} else if (topNeighbor >= 0 && format[topNeighbor][buttonPosX] == buttons[8]) {
c = 3;
} else if (bottomNeighbor <= 2 && format[bottomNeighbor][buttonPosX] == buttons[8]) {
c = 4;
} else {
c = 0;
}
switch (c) {
case 0:
break;
case 1:
temp = format[buttonPosY][buttonPosX];
format[buttonPosY][buttonPosX] = format[buttonPosY][leftNeighbor];
format[buttonPosY][leftNeighbor] = temp;
refresh();
break;
case 2:
temp = format[buttonPosY][buttonPosX];
format[buttonPosY][buttonPosX] = format[buttonPosY][rightNeighbor];
format[buttonPosY][rightNeighbor] = temp;
refresh();
break;
case 3:
temp = format[buttonPosY][buttonPosX];
format[buttonPosY][buttonPosX] = format[topNeighbor][buttonPosX];
format[topNeighbor][buttonPosX] = temp;
refresh();
break;
case 4:
temp = format[buttonPosY][buttonPosX];
format[buttonPosY][buttonPosX] = format[bottomNeighbor][buttonPosX];
format[bottomNeighbor][buttonPosX] = temp;
refresh();
break;
}
}
}
First of all this code is hard to read for a few reasons:
As for your specific question the problem does indeed lie in the order
method as you suspected. It's this line:
int rd = (int) Math.random() * (9 - 0);
The casting to int
happens before the multiplication so you're always getting a result of 0 here. This causes all the buttons in your format
array to be identical.
However, there's a bigger problem. Even if you fix the above line by doing this:
int rd = (int) (Math.random() * (9 - 0));
you will still have problems because you never ensure that you only use each button once. In other words, rd
can be 3 in the current loop and then be 3 again in the next loop because it's random - there is no memory of what has and has not been used before. What you need is a mechanism to prevent duplicates so that each button is unique.
So, something like this should do the trick:
if (initial == false) {
boolean[] isUsed = new boolean[buttons.length];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int rd = -1;
do{
rd = (int) (Math.random() * (9 - 0));
}while(isUsed[rd]);
isUsed[rd] = true;
JButton temp = buttons[rd];
format[i][j] = temp;
}
}
}