8 拼图的第二次迭代不起作用

Second Iteration of 8 Puzzle is Not Working

这是我第一次使用 Java Swing,所以至少可以说我的程序有点混乱。目标是让一个 8 拼图拍摄一张图像,将其分成 9 个扇区,然后按特定顺序放置其中的 8 个扇区(丢弃 1 以进行移动)。该程序第一次运行良好。一旦它被解决,它应该随机化 JButton 组件并允许你解决 again.The 按钮随机化,但不允许我移动它们。任何帮助是极大的赞赏。

通常我 post 只是我认为有问题的代码,但由于代码的混乱性质,我正在 post 整个 class。

编辑: 逐行查看代码后,问题似乎出在 Order() 方法中。如果我一起删除第二个 "if" 语句,该程序可以正常工作,只是不会随机化组件。 (如果我对该语句使用 "else" & "else if" 也是一样)

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;
        }
    }
}

首先,由于以下几个原因,这段代码很难阅读:

  1. 变量名没有意义。 "c" 之类的名称可能对您有某种意义,但当其他人阅读它时,我们只能猜测它可能代表什么。
  2. 您正在使用 Java 提供的基元和 类,尽管它会简化您的代码以创建您自己设计的自定义对象。
  3. 代码中没有注释

至于你的具体问题,问题确实出在你所怀疑的order方法上。就是这一行:

int rd = (int) Math.random() * (9 - 0);

转换为 int 发生在乘法之前,因此您在这里得到的结果总是 0。这会导致 format 数组中的所有按钮都相同。

但是,还有一个更大的问题。即使你通过这样做修复了上面的行:

int rd = (int) (Math.random() * (9 - 0));

您仍然会遇到问题,因为您永远无法确保每个按钮只使用一次。换句话说,rd 可以在当前循环中为 3,然后在下一个循环中再次为 3,因为它是随机的——没有记忆之前使用过和未使用过的内容。您需要的是一种防止重复的机制,以便每个按钮都是唯一的。

所以,像这样的东西应该可以解决问题:

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;
                }
            }
        }