Java拼图游戏

拼图游戏效果图
这是一个有趣的拼图游戏!这篇文章我将逐步教你编写这个游戏的代码。首先,我们来编写游戏的整体框架。

步骤1:编写游戏的整体框架

我们将创建一个Java项目,并在其中创建以下类:

  1. MainApp:包含main方法,用于启动游戏。
  2. PictureMainFrame:继承自JFrame,表示游戏的主界面。
  3. PictureCanvas:继承自JPanel,表示拼图区域,用于显示拼图小方格。
  4. PicturePreview:继承自JPanel,表示预览区域,用于显示原始图片。
  5. Cell:继承自JButton,表示拼图的每个小方格。

下面是整体框架的结构:

public class MainApp {
    public static void main(String[] args) {
        // 创建主界面
        PictureMainFrame frame = new PictureMainFrame();
        // 显示界面
        frame.setVisible(true);
    }
}

public class PictureMainFrame extends JFrame {
    // 成员变量和构造方法

    // 方法:界面初始化、添加组件、添加事件监听等
}

public class PictureCanvas extends JPanel implements MouseListener {
    // 静态变量:图片ID、步数

    // 成员变量:拼图小方格、空方格位置等

    // 构造方法

    // 方法:重新加载图片、开始游戏、方格移动等
}

public class PicturePreview extends JPanel {
    // 方法:重写绘制组件方法,显示图片
}

public class Cell extends JButton {
    // 构造方法:带有图片的小方格

    // 方法:小方格的移动
}

在这个框架中,MainApp负责启动游戏,PictureMainFrame是游戏的主界面,包含拼图区和预览区,PictureCanvas是拼图区域的实现,PicturePreview用于显示原始图片,Cell表示拼图的每个小方格。接下来,我们将逐步完善这些类的功能。

下一步我们将完善PictureMainFrame类的代码,包括界面的初始化、添加组件和添加事件监听器等功能。

步骤2:完善PictureMainFrame

public class PictureMainFrame extends JFrame {
    public static JTextField step; // 步数
    private final String[] items = {"小女孩儿", "女明星"};
    private JRadioButton addNumInfo; // 数字提示
    private JRadioButton clearNumInfo; // 清除提示
    private PictureCanvas canvas; // 拼图区
    private PicturePreview preview; // 预览区
    private JComboBox<String> box; // 下拉框
    private JTextField name; // 图片名称
    private JButton start; // 开始按钮

    // 空参数构造方法
    public PictureMainFrame() {
        init(); // 界面初始化操作
        addComponent(); // 添加组件
        addPreviewImage(); // 添加预览图片与拼图图片
        addActionListener(); // 为组件添加事件监听
    }

    // 为组件添加事件监听
    private void addActionListener() {
        // 数字提示
        addNumInfo.addActionListener(_ -> {
            canvas.reLoadPictureAddNumber();
        });

        // 清除提示
        clearNumInfo.addActionListener(_ -> {
            canvas.reLoadPictureClearNumber();
        });

        // 下拉框
        box.addItemListener(_ -> {
            int num = box.getSelectedIndex();
            PictureCanvas.pictureID = num + 1;
            preview.repaint();
            canvas.reLoadPictureClearNumber();
            name.setText("图片名称:" + box.getSelectedItem());
            int stepNum = PictureCanvas.stepNum = 0;
            step.setText("步数:" + stepNum);
            clearNumInfo.setSelected(true);
        });

        // 开始按钮
        start.addActionListener(_ -> {
            PictureCanvas.stepNum = 0;
            step.setText("步数:" + PictureCanvas.stepNum);
            canvas.start();
        });
    }

    // 添加预览图片与拼图图片
    private void addPreviewImage() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1, 2));
        canvas = new PictureCanvas();
        canvas.setBorder(new TitledBorder("拼图区"));
        preview = new PicturePreview();
        preview.setBorder(new TitledBorder("预览区"));
        panel.add(canvas, BorderLayout.WEST);
        panel.add(preview, BorderLayout.EAST);
        this.add(panel, BorderLayout.CENTER);
    }

    // 添加组件
    private void addComponent() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1, 2));
        JPanel leftPanel = new JPanel();
        leftPanel.setBorder(new TitledBorder("按钮区"));
        leftPanel.setBackground(Color.PINK);
        addNumInfo = new JRadioButton("数字提示", false);
        clearNumInfo = new JRadioButton("清除提示", true);
        ButtonGroup buttonGroup = new ButtonGroup();
        box = new JComboBox<>(items);
        start = new JButton("Start");
        buttonGroup.add(addNumInfo);
        buttonGroup.add(clearNumInfo);
        addNumInfo.setBackground(Color.PINK);
        clearNumInfo.setBackground(Color.PINK);
        start.setBackground(Color.PINK);
        leftPanel.add(addNumInfo);
        leftPanel.add(clearNumInfo);
        leftPanel.add(new JLabel("                选择图片:"));
        leftPanel.add(box);
        leftPanel.add(start);
        panel.add(leftPanel, BorderLayout.WEST);

        JPanel rightPanel = new JPanel();
        rightPanel.setBorder(new TitledBorder("游戏状态"));
        rightPanel.setBackground(Color.PINK);
        rightPanel.setLayout(new GridLayout(1, 2));
        name = new JTextField("图片名称:小女孩儿");
        step = new JTextField("步数:0");
        name.setEditable(false);
        step.setEditable(false);
        rightPanel.add(name, BorderLayout.WEST);
        rightPanel.add(step, BorderLayout.EAST);
        panel.add(rightPanel, BorderLayout.EAST);
        this.add(panel, BorderLayout.NORTH);
    }

    // 界面初始化方法
    private void init() {
        this.setTitle("拼图游戏");
        this.setSize(1000, 720);
        this.setLocation(150, 10);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

在这一步中,我们完成了PictureMainFrame类的基本框架,并实现了界面的初始化、添加组件和添加事件监听器等功能。下一步我们将继续完善其他类的代码。

下一步我们将完善PictureCanvas类的代码,包括拼图小方格的创建、重新加载图片、开始游戏等功能。

步骤3:完善PictureCanvas

public class PictureCanvas extends JPanel implements MouseListener {
    public static int pictureID = 1;
    public static int stepNum = 0;

    private final Cell[] cell;
    private final Rectangle nullCell;
    private boolean hasAddActionListener = false;

    public PictureCanvas() {
        this.setLayout(null);
        cell = new Cell[12];
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                ImageIcon icon = new ImageIcon("picture\\1_" + (i * 3 + j + 1) + ".gif");
                cell[i * 3 + j] = new Cell(icon);
                cell[i * 3 + j].setLocation(j * 150 + 20, i * 150 + 20);
                this.add(cell[i * 3 + j]);
            }
        }
        this.remove(cell[11]);
        nullCell = new Rectangle(300 + 20, 450 + 20, 150, 150);
    }

    public void reLoadPictureAddNumber() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                ImageIcon icon = new ImageIcon("picture\\" + pictureID + "_" + (i * 3 + j + 1) + ".gif");
                cell[i * 3 + j].setIcon(icon);
                cell[i * 3 + j].setText("" + (i * 3 + j + 1));
                cell[i * 3 + j].setVerticalTextPosition(this.getY() / 2);
                cell[i * 3 + j].setHorizontalTextPosition(this.getX() / 2);
            }
        }
    }

    public void reLoadPictureClearNumber() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                ImageIcon icon = new ImageIcon("picture\\" + pictureID + "_" + (i * 3 + j + 1) + ".gif");
                cell[i * 3 + j].setIcon(icon);
                cell[i * 3 + j].setText("");
            }
        }
    }

    public void start() {
        if (!hasAddActionListener) {
            for (int i = 0; i < 11; i++) {
                cell[i].addMouseListener(this);
            }
            hasAddActionListener = true;
        }
        while (cell[0].getBounds().x <= 170 && cell[0].getBounds().y <= 170) {
            int nullX = nullCell.getBounds().x;
            int nullY = nullCell.getBounds().y;
            int direction = (int) (Math.random() * 4);
            switch (direction) {
                case 0:
                    nullX -= 150;
                    cellMove(nullX, nullY, "RIGHT");
                    break;
                case 1:
                    nullX += 150;
                    cellMove(nullX, nullY, "LEFT");
                    break;
                case 2:
                    nullY -= 150;
                    cellMove(nullX, nullY, "DOWN");
                    break;
                case 3:
                    nullY += 150;
                    cellMove(nullX, nullY, "UP");
                    break;
            }
        }
    }

    private void cellMove(int nullX, int nullY, String direction) {
        for (int i = 0; i < 11; i++) {
            if (cell[i].getBounds().x == nullX && cell[i].getBounds().y == nullY) {
                cell[i].move(direction);
                nullCell.setLocation(nullX, nullY);
                break;
            }
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        Cell button = (Cell) e.getSource();
        int clickX = button.getBounds().x;
        int clickY = button.getBounds().y;
        int nullX = nullCell.getBounds().x;
        int nullY = nullCell.getBounds().y;
        if (clickX == nullX && clickY - nullY == 150) {
            button.move("UP");
        } else if (clickX == nullX && clickY - nullY == -150) {
            button.move("DOWN");
        } else if (clickX - nullX == 150 && clickY == nullY) {
            button.move("LEFT");
        } else if (clickX - null

X == -150 && clickY == nullY) {
            button.move("RIGHT");
        }
        stepNum++;
        PictureMainFrame.step.setText("步数:" + stepNum);
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        boolean isSuccess = true;
        for (int i = 0; i < 11; i++) {
            if (!cell[i].isRightPosition()) {
                isSuccess = false;
                break;
            }
        }
        if (isSuccess) {
            JOptionPane.showMessageDialog(null, "拼图成功!用了" + stepNum + "步。");
            reLoadPictureClearNumber();
            PictureMainFrame.step.setText("步数:0");
            stepNum = 0;
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}

在这一步中,我们完成了PictureCanvas类的基本框架,并实现了拼图小方格的创建、重新加载图片、开始游戏等功能。下一步我们将继续完善其他类的代码。

下一步我们将完善Cell类和PicturePreview类的代码,包括小方格的移动和图片预览功能。

步骤4:完善Cell类和PicturePreview

public class Cell extends JButton {

    public Cell(Icon icon) {
        super(icon);
        this.setSize(150, 150);
    }

    public void move(String direction) {
        switch (direction) {
            case "UP":
                this.setLocation(this.getBounds().x, this.getBounds().y - 150);
                break;
            case "DOWN":
                this.setLocation(this.getBounds().x, this.getBounds().y + 150);
                break;
            case "LEFT":
                this.setLocation(this.getBounds().x - 150, this.getBounds().y);
                break;
            case "RIGHT":
                this.setLocation(this.getBounds().x + 150, this.getBounds().y);
                break;
            default:
                break;
        }
    }

    public boolean isRightPosition() {
        int x = this.getBounds().x;
        int y = this.getBounds().y;
        int index = (y - 20) / 150 * 3 + (x - 20) / 150;
        return index == Integer.parseInt(this.getText()) - 1;
    }
}
public class PicturePreview extends JPanel {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        String filename = "picture\\" + PictureCanvas.pictureID + ".jpg";
        ImageIcon icon = new ImageIcon(filename);
        Image image = icon.getImage();
        g.drawImage(image, 20, 20, 450, 600, this);
    }
}

在这一步中,我们完善了Cell类和PicturePreview类的代码,包括小方格的移动和图片预览功能。接下来我们将继续完善其他类的代码。

下一步,我们将完善PictureCanvas类的代码,包括鼠标点击事件的处理和游戏完成的判断。

步骤5:完善PictureCanvas

public class PictureCanvas extends JPanel implements MouseListener {

    public void mousePressed(MouseEvent e) {
        Cell button = (Cell) e.getSource();
        int clickX = button.getBounds().x;
        int clickY = button.getBounds().y;
        int nullX = nullCell.getBounds().x;
        int nullY = nullCell.getBounds().y;

        if (clickX == nullX && clickY - nullY == 150) {
            button.move("UP");
        } else if (clickX == nullX && clickY - nullY == -150) {
            button.move("DOWN");
        } else if (clickX - nullX == 150 && clickY == nullY) {
            button.move("LEFT");
        } else if (clickX - nullX == -150 && clickY == nullY) {
            button.move("RIGHT");
        } else {
            return;
        }

        nullCell.setLocation(clickX, clickY);
        this.repaint();
        stepNum++;
        PictureMainFrame.step.setText("步数:" + stepNum);

        boolean isSuccess = true;
        for (int i = 0; i < 11; i++) {
            if (!cell[i].isRightPosition()) {
                isSuccess = false;
                break;
            }
        }
        if (isSuccess) {
            JOptionPane.showMessageDialog(null, "拼图成功!用了" + stepNum + "步。");
            reLoadPictureClearNumber();
            PictureMainFrame.step.setText("步数:0");
            stepNum = 0;
        }
    }

    public void mouseClicked(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

在这一步中,我们完成了PictureCanvas类的代码,包括鼠标点击事件的处理和游戏完成的判断。现在我们的拼图游戏已经基本完成,可以运行起来了。

步骤6:重命名+重构逻辑+优化洗牌逻辑(没有限制的重开+不会出现未解之谜)

public class PuzzleGameApp {
    public static void main(String[] args) {
        PuzzleGameFrame mainFrame = new PuzzleGameFrame();
        mainFrame.setVisible(true);
    }
}

import javax.swing.*;
import javax.swing.border.TitledBorder;
import java.awt.*;

public class PuzzleGameFrame extends JFrame {
    public static JTextField stepCounter; // 步数计数器
    private final String[] imageOptions = {"小女孩儿", "女明星"};
    private JRadioButton showNumbersOption; // 显示数字选项
    private JRadioButton hideNumbersOption; // 隐藏数字选项
    private PuzzleArea puzzleArea; // 拼图区域
    private ImagePreviewArea imagePreviewArea; // 图像预览区域
    private JComboBox<String> imageSelector; // 图片选择下拉框
    private JTextField imageNameField; // 图片名称字段
    private JButton startButton; // 开始按钮

    public PuzzleGameFrame() {
        initializeUI();
        addComponents();
        setupInitialImages();
        setupListeners();
    }

    private void setupListeners() {
        showNumbersOption.addActionListener(e -> puzzleArea.loadImageWithNumbers());
        hideNumbersOption.addActionListener(e -> puzzleArea.loadImageWithoutNumbers());
        imageSelector.addItemListener(e -> {
            int selectedIndex = imageSelector.getSelectedIndex();
            PuzzleArea.imageId = selectedIndex + 1;
            imagePreviewArea.repaint();
            puzzleArea.loadImageWithoutNumbers();
            imageNameField.setText("图片名称:" + imageSelector.getSelectedItem());
            int steps = PuzzleArea.steps = 0;
            stepCounter.setText("步数:" + steps);
            hideNumbersOption.setSelected(true);
        });
        startButton.addActionListener(e -> {
            PuzzleArea.steps = 0;
            stepCounter.setText("步数:" + PuzzleArea.steps);
            puzzleArea.startPuzzle();
        });
    }

    private void setupInitialImages() {
        JPanel panel = new JPanel(new GridLayout(1, 2));
        puzzleArea = new PuzzleArea();
        puzzleArea.setBorder(new TitledBorder("拼图区域"));
        imagePreviewArea = new ImagePreviewArea();
        imagePreviewArea.setBorder(new TitledBorder("预览区域"));
        panel.add(puzzleArea, BorderLayout.WEST);
        panel.add(imagePreviewArea, BorderLayout.EAST);
        this.add(panel, BorderLayout.CENTER);
    }

    private void addComponents() {
        JPanel mainPanel = new JPanel(new GridLayout(1, 2));
        JPanel leftPanel = new JPanel();
        leftPanel.setBorder(new TitledBorder("控制区"));
        leftPanel.setBackground(Color.PINK);
        showNumbersOption = new JRadioButton("显示数字", false);
        hideNumbersOption = new JRadioButton("隐藏数字", true);
        ButtonGroup optionGroup = new ButtonGroup();
        imageSelector = new JComboBox<>(imageOptions);
        startButton = new JButton("开始");
        optionGroup.add(showNumbersOption);
        optionGroup.add(hideNumbersOption);
        showNumbersOption.setBackground(Color.PINK);
        hideNumbersOption.setBackground(Color.PINK);
        startButton.setBackground(Color.PINK);
        leftPanel.add(showNumbersOption);
        leftPanel.add(hideNumbersOption);
        leftPanel.add(new JLabel("选择图片:"));
        leftPanel.add(imageSelector);
        leftPanel.add(startButton);
        mainPanel.add(leftPanel, BorderLayout.WEST);

        JPanel rightPanel = new JPanel();
        rightPanel.setBorder(new TitledBorder("游戏状态"));
        rightPanel.setBackground(Color.PINK);
        rightPanel.setLayout(new GridLayout(1, 2));
        imageNameField = new JTextField("图片名称:小女孩儿");
        stepCounter = new JTextField("步数:0");
        imageNameField.setEditable(false);
        stepCounter.setEditable(false);
        rightPanel.add(imageNameField, BorderLayout.WEST);
        rightPanel.add(stepCounter, BorderLayout.EAST);
        mainPanel.add(rightPanel, BorderLayout.EAST);
        this.add(mainPanel, BorderLayout.NORTH);
    }

    private void initializeUI() {
        this.setTitle("拼图游戏");
        this.setSize(1000, 720);
        this.setLocation(150, 10);
        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

public class PuzzleArea extends JPanel implements MouseListener {
    public static int imageId = 1;
    public static int steps = 0;

    private final PuzzlePiece[] puzzlePieces;
    private final Rectangle emptySpot;
    private boolean isListenerAdded = false;

    public PuzzleArea() {
        this.setLayout(null);
        puzzlePieces = new PuzzlePiece[12];
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                ImageIcon icon = new ImageIcon("picture\\1_" + (i * 3 + j + 1) + ".gif");
                puzzlePieces[i * 3 + j] = new PuzzlePiece(icon);
                puzzlePieces[i * 3 + j].setLocation(j * 150 + 20, i * 150 + 20);
                this.add(puzzlePieces[i * 3 + j]);
            }
        }
        this.remove(puzzlePieces[11]);
        emptySpot = new Rectangle(300 + 20, 450 + 20, 150, 150);
    }

    public void loadImageWithNumbers() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                ImageIcon icon = new ImageIcon("picture\\" + imageId + "_" + (i * 3 + j + 1) + ".gif");
                puzzlePieces[i * 3 + j].setIcon(icon);
                puzzlePieces[i * 3 + j].setText("" + (i * 3 + j + 1));
                puzzlePieces[i * 3 + j].setVerticalTextPosition(this.getY() / 2);
                puzzlePieces[i * 3 + j].setHorizontalTextPosition(this.getX() / 2);
            }
        }
    }

    public void loadImageWithoutNumbers() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 3; j++) {
                ImageIcon icon = new ImageIcon("picture\\" + imageId + "_" + (i * 3 + j + 1) + ".gif");
                puzzlePieces[i * 3 + j].setIcon(icon);
                puzzlePieces[i * 3 + j].setText("");
            }
        }
    }

    public void startPuzzle() {
        if (!isListenerAdded) {
            for (int i = 0; i < 11; i++) {
                puzzlePieces[i].addMouseListener(this);
            }
            isListenerAdded = true;
        }
        shufflePieces();
    }

    private void shufflePieces() {
        int shuffleCount = 100; // 定义一个合适的打乱次数
        for (int i = 0; i < shuffleCount; i++) {
            ArrayList<String> possibleMoves = new ArrayList<>();
            int nullX = emptySpot.x;
            int nullY = emptySpot.y;

            // 检查四个可能的移动方向并确认是否可行
            if (nullX > 20) { // 检查左边是否有块可以移动到空位
                possibleMoves.add("LEFT");
            }
            if (nullX < 300) { // 检查右边是否有块可以移动到空位
                possibleMoves.add("RIGHT");
            }
            if (nullY > 20) { // 检查上面是否有块可以移动到空位
                possibleMoves.add("UP");
            }
            if (nullY < 300) { // 检查下面是否有块可以移动到空位
                possibleMoves.add("DOWN");
            }

            // 从可能的移动中随机选择一个执行
            String move = possibleMoves.get((int) (Math.random() * possibleMoves.size()));
            switch (move) {
                case "LEFT":
                    movePiece(nullX - 150, nullY, "RIGHT");
                    break;
                case "RIGHT":
                    movePiece(nullX + 150, nullY, "LEFT");
                    break;
                case "UP":
                    movePiece(nullX, nullY - 150, "DOWN");
                    break;
                case "DOWN":
                    movePiece(nullX, nullY + 150, "UP");
                    break;
            }
        }
    }

    private void movePiece(int nullX, int nullY, String direction) {
        for (int i = 0; i < 11; i++) {
            if (puzzlePieces[i].getBounds().x == nullX && puzzlePieces[i].getBounds().y == nullY) {
                puzzlePieces[i].move(direction);
                emptySpot.setLocation(nullX, nullY);
                break;
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {
        PuzzlePiece clickedPiece = (PuzzlePiece) e.getSource();
        int clickX = clickedPiece.getBounds().x;
        int clickY = clickedPiece.getBounds().y;
        int nullX = emptySpot.getBounds().x;
        int nullY = emptySpot.getBounds().y;

        if (clickX == nullX && clickY - nullY == 150) {
            clickedPiece.move("UP");
        } else if (clickX == nullX && clickY - nullY == -150) {
            clickedPiece.move("DOWN");
        } else if (clickX - nullX == 150 && clickY == nullY) {
            clickedPiece.move("LEFT");
        } else if (clickX - nullX == -150 && clickY == nullY) {
            clickedPiece.move("RIGHT");
        } else {
            return;
        }

        emptySpot.setLocation(clickX, clickY);
        this.repaint();
        steps++;
        PuzzleGameFrame.stepCounter.setText("步数:" + steps);

        checkPuzzleCompletion();
    }

    private void checkPuzzleCompletion() {
        boolean isComplete = true;
        for (int i = 0; i < 11; i++) {
            if (!puzzlePieces[i].isCorrectPosition()) {
                isComplete = false;
                break;
            }
        }
        if (isComplete) {
            JOptionPane.showMessageDialog(null, "拼图成功!用了" + steps + "步。");
            loadImageWithoutNumbers();
            PuzzleGameFrame.stepCounter.setText("步数:0");
            steps = 0;
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mouseReleased(MouseEvent e) {
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }
}

import javax.swing.*;

public class PuzzlePiece extends JButton {

    public PuzzlePiece(Icon icon) {
        super(icon);
        this.setSize(150, 150);
    }

    public void move(String direction) {
        switch (direction) {
            case "UP":
                this.setLocation(this.getBounds().x, this.getBounds().y - 150);
                break;
            case "DOWN":
                this.setLocation(this.getBounds().x, this.getBounds().y + 150);
                break;
            case "LEFT":
                this.setLocation(this.getBounds().x - 150, this.getBounds().y);
                break;
            case "RIGHT":
                this.setLocation(this.getBounds().x + 150, this.getBounds().y);
                break;
            default:
                break;
        }
    }

    public boolean isCorrectPosition() {
        int x = this.getBounds().x;
        int y = this.getBounds().y;
        int index = (y - 20) / 150 * 3 + (x - 20) / 150;
        return index == Integer.parseInt(this.getText()) - 1;
    }
}

import javax.swing.*;
import java.awt.*;

public class ImagePreviewArea extends JPanel {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        String filename = "picture\\" + PuzzleArea.imageId + ".jpg";
        ImageIcon icon = new ImageIcon(filename);
        Image image = icon.getImage();
        g.drawImage(image, 20, 20, 450, 600, this);
    }
}

细节

ButtonGroup 可以保证一组按钮只有一个被选中
addActionListener() 必须在 addComponent() 和 addPreviewImage() 之后调用, 因为 addComponent() 和addPreviewImage() 中完成了对 成员变量 的初始化

在Java Swing中,this.setLayout(null); 这行代码用于设置容器(在这个例子中是 PuzzleArea 类,一个继承自 JPanel 的类)的布局管理器为 null。这意味着该容器不使用任何自动布局管理器来控制其子组件的位置和大小。

当你将布局管理器设置为 null 时,你需要手动指定容器中每个组件的大小和位置。这通常是通过调用组件的 setBounds(x, y, width, height) 或 setLocation(x, y) 和 setSize(width, height) 方法来实现的。这种方式给予了开发者完全的控制权,可以精确地放置和调整组件,但同时也需要更多的工作来确保组件在不同环境(如不同的屏幕分辨率和字体设置)下表现良好。

在 PuzzleArea 类中,使用 null 布局是为了能精确地控制拼图块的位置,因为拼图游戏需要拼图块能够精确地放置在特定的位置。例如,每个拼图块通过 setLocation 方法被放置在特定的坐标上,这些坐标对于游戏的运行至关重要,因为它们决定了拼图块能否正确地拼合。

  • 22
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值