Java实现——拼图游戏

目录

一、准备项目结构

1.1 主方法

1.2Jframe界面包

二、代码的实现

2.1 主方法

2.2 GameJframe 

2.2.1 资源包引用

2.2.2 构建GameJframe类

2.2.3 GameJframe的成员变量


完整的实现效果

使用Java实现拼图游戏。界面使用的是JFrame实现。

一、准备项目结构

1.1 主方法

在我们实现代码之前,先把项目结构构建好。我们以一个名为App的类作为运行的主方法,在其中调用游戏界面,我们将所有的游戏业务都实现在名为GameJframe的类中。

1.2Jframe界面包

在这里面,我们实现了三个类,第一个GameJframe是我们的游戏界面,第二个LoginJframe是登陆界面,第三个是RegisterJframe注册界面。我们在这里就不实现注册界面与登陆界面了,我们只讲解游戏界面的实现。

准备好这样的结构之后,我们就可以开始进行代码的书写了。

二、代码的实现

下面的内容,我将逐步分析代码的组成与功能,不能直接看到完整的代码,完整的代码放在了此目录的最后,在目录上点击    2.2.4.6 完整代码    可以查看。

2.1 主方法

import Jframe.GameJframe;

//拼图游戏
public class App {
    public static void main(String[] args) {
        new GameJframe();
    }
}

我们调用Jframe中的GameJframe类,来创建一个新的Jframe界面用来实现我们的游戏界面,其余的登录界面与注册界面暂不实现。所以主方法就非常简单,只需这一步即可。

2.2 GameJframe 

2.2.1 资源包引用

首先,我们声明一下包,与要引入的资源,在使用idea开发的过程中自动添加,不需要刻意关注,如果使用的编译器没有此功能,自己在开发的过程中搜索添加即可。

package Jframe;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.Random;

2.2.2 构建GameJframe类

之后呢,我们构建GameJframe类。因为我们要在这里面实现窗体,所以我们继承JFrame类。又因为我们在使用游戏的时候,需要用到鼠标与键盘操作,所以我们再写入KeyListener键盘接听接口,与ActionListener接口,由于我们不需要太复杂的鼠标操作,只需点击即可,所我没有使用MouseListener。

public class GameJframe extends JFrame implements KeyListener, ActionListener {


}

2.2.3 GameJframe的成员变量

来思考需要用到的成员变量,很多东西在我们将要实现的方法中会用到,比如存放各块拼图的二维数组,用来计步数的变量。游戏菜单的各项功能。判断是否胜利的数组,这个数组保存着我们图片的正确顺序。

2.2.3.1 计数器
int counter = 0;
2.2.3.2 二维数组

由于我们只实现了4*4的游戏,所以只需要创建一个4*4的二维数组即可,需要别的玩法可自行创建

int[][] data = new int[4][4];
2.2.3.3 游戏菜单

游戏菜单的具体逻辑是这样的,JMenuBar包含JMenu,JMenu包含着JMenuItem

JMenuBar是整个菜单,所以我们从JMeun开始实现

    JMenu functionJMenu = new JMenu("功能");
    JMenu aboutJMenu = new JMenu("关于我们");

在功能中,我们要实现更换图片,但是更换图片也需要选项,所以,更换图片也是一个包含JMenuItem的JMenu,再把更换图片的这个JMenu加到功能这个JMenu中即可,所以更换图片JMenu中的JMenu。

    JMenu changeImage = new JMenu("更换图片");
    //我们这里将崩坏星穹铁道的图标设置在游戏中
    //或许我们还可以将其他的关于崩铁的图片设置在里面,所以
    //我们直接把“崩铁”做成一个菜单
    JMenu Star_rail = new JMenu("崩铁");

接下来,我们实现JMenuItem,也就是上述的各种菜单中的选项。

​
    //这些是功能中的选项
    JMenuItem replayItem = new JMenuItem("重新游戏");
    JMenuItem reLoginItem = new JMenuItem("重新登陆");
    JMenuItem closeItem = new JMenuItem("关闭游戏");
    JMenu changeImage = new JMenu("更换图片");
    //这些是关于我们中的选项
    //公众号只是举个例子,你可以是先别的来这里
    JMenuItem accountItem = new JMenuItem("公众号");

    //这个是更改图片中的崩铁中的选项
    //创建崩铁下的选项
    JMenuItem March = new JMenuItem("三月七");
    JMenuItem FireFly = new JMenuItem("流萤");

    

​

用以判断的胜利数组,存放着正确的顺序(最后一项为空,也就是拼图游戏中空白的格子)。

    int[][] win = {
            {1,2,3,4},
            {5,6,7,8},
            {9,10,11,12},
            {13,14,15,0}
    };
 2.2.3.4 图片路径

为了方便代码的书写,我们干脆一劳永逸,直接把路径定义为变量,之后的代码只需要改变这个量即可。

​
    //记录16块图片路径  默认为Star_rail 后续可以更改
    String path1 = "image/Star_rail/(";
    //记录完整图片路径
    String pathAll = "image/Star_rail/Start Rail.jpg";

​

这下我们的GameJframe的成员变量就书写完毕了。

2.2.4 GameJframe的方法

2.2.4.1 加载数据方法

写到这里,我们应该加载数据了,其中包括,写一个0-15的数组,将其打乱,将打乱的数组放入我们先前准备好的二维数组。一些必要的注释已经写在里面了。

    private void initData(){
        //需求:把0-15的数据打乱顺序
        //然后再按照4各一组的方式添加到二维数组中
        int[] tempArr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        //打乱数组中的数字
        Random r = new Random();
        for (int i = 0; i < tempArr.length; i++) {
            //随机索引
            int index = r.nextInt(tempArr.length);
            int temp = tempArr[i];
            tempArr[i] = tempArr[index];
            tempArr[index] = temp;
        }

        //给二维数组添加数据
        for(int i :tempArr){
            if(tempArr[i]==0){
                x = i / 4;
                y = i % 4;
            }
            data[i / 4][i % 4] = tempArr[i];
        }
    }
2.2.4.2 判断胜利的方法

我们在不断的交换图片过程中,其实就是改变data中数据的过程,判断胜利,只需要比较data与我们的win数组是否相同即可。

    private boolean check_win(){
        return Arrays.deepEquals(data, win);
    }
2.2.4.3加载图片的方法

写到这里,我们要开始加载图片了,结合了我们先前打乱的二维数组来插入图片,所以没我们的图片也要打乱,那如何建立两者之间的联系呢?做到这里的读者,请务必将分好的16张图片,按照图片顺序,进行1-16的命名,这样的话,我们只需要在路径中,运用数字,将图片添加进来。

再定义一个int num;获取二维数组的值,我们就可以按照num添加照片了。比如,在我的16张图片中,均命名为  (1).jpg…………,(16).jpg,这样我们添加的时候,就可以添加

"image/("+num+").jpg";  那这样,他就会分别添加"image/(1).jpg","image/(2).jpg","image/(3).jpg"…………,最终添加到"image/(15).jpg"。而且,因为数组只添加0-15,空下来的0,由于找不到对应的图片,就会打印空白,正好对应了我们拼图中的空白。接下来的移动,无非就是这个空白图片与相邻图片的交换而已。 

我们还需要做一个胜利图标,我的可能跟你们的不一样,所以你们实现完之后,要根据图片大小,修改位置。

    private void initImage() {
        this.getContentPane().removeAll();
        if(check_win()){
            //显示胜利图标
            JLabel winJLabel = new JLabel(new ImageIcon("image/winJframe.jpg"));
            winJLabel.setBounds(173,-5,210,80);
            this.getContentPane().add(winJLabel);
        }
        JLabel Stepcounter = new JLabel("步数:"+counter);
        Stepcounter.setBounds(50,30,100,20);
        this.getContentPane().add(Stepcounter);


        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 4; i++) {
                //获取打乱二维数组序号
                int num = data[j][i];
                JLabel jLabel = new JLabel(new ImageIcon(path1+num+").jpg"));
                jLabel.setBounds(105 * i+83, 105*j+134, 105, 105);

                //给图片加边框
                jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));
                this.getContentPane().add(jLabel);
            }
        }
        //刷新界面
        this.getContentPane().repaint();
    }
2.2.4.4 创建菜单界面

很多注意事项都放在了注释中,需要额外注意的是,

 private void initJMenuBar() {
        //创建菜单
        JMenuBar jMenuBar = new JMenuBar();

        //将Item添加到JMenu中
        functionJMenu.add(replayItem);
        functionJMenu.add(reLoginItem);
        functionJMenu.add(closeItem);
        functionJMenu.add(changeImage);
        aboutJMenu.add(accountItem);

        //给更改图片加菜单
        changeImage.add(Star_rail);


        //给崩铁加选项  其中March表示的是崩铁的图标,FireFly是流萤的图片
        Star_rail.add(March);
        Star_rail.add(FireFly);


        //将JMenu添加到JMenuBar中
        jMenuBar.add(functionJMenu);
        jMenuBar.add(aboutJMenu);

        //给游戏功能绑定事件
        replayItem.addActionListener(this);
        reLoginItem.addActionListener(this);
        closeItem.addActionListener(this);
        accountItem.addActionListener(this);

        //给选项添加监听
        FireFly.addActionListener(this);
        March.addActionListener(this);

        //将菜单放在界面中
        this.setJMenuBar(jMenuBar);

    }
2.2.4.5 键盘监听重构方法

keyPressed表示按住不动某个键要实现的代码,根据这个逻辑,我们可以设置按住A不动时,我们加载整张图片供玩家查看。这样会方便玩家解出。

我们的逻辑就是,按住A时,删除界面所有图片,添加完整的一张图,刷新界面。A的编号是65,所以我们keyPressed中参数e在按住A的时候等于65。

​
@Override
    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if(code == 65){
            //把界面中所有图片删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            JLabel all = new JLabel(new ImageIcon(pathAll));
            all.setBounds(83,134,420,420);
            this.getContentPane().add(all);
            //刷新界面
            this.getContentPane().repaint();
        }
    }

​

接下来就是移动图片了keyReleased方法,可以检测我们是否松开了某个键,所以常用来实现功能,键盘上的左,对应的是37,上是38,右是39,下是40,每按下相应的按钮,就交换对应的两张图片,每按一次就判断游戏是否胜利,胜利了就返回方法。

 @Override
    public void keyReleased(KeyEvent e) {
        //判断游戏游戏是否胜利
        if(check_win()){
            return;
        }
        //对应的编码  左:37  上:38  右:39 下:40
        //
        int code = e.getKeyCode();
        if(code == 37){
            data[x][y] = data[x][y+1];
            data[x][y+1] = 0;
            y = y+1;
            counter++;
            initImage();
        }else if(code == 38){
            data[x][y] = data[x+1][y];
            data[x+1][y] = 0;
            x = x+1;
            counter++;
            initImage();
        }else if(code == 39){
            data[x][y] =data[x][y-1];
            data[x][y-1] = 0;
            y=y-1;
            counter++;
            initImage();
        }else if(code == 40){
            data[x][y] = data[x-1][y];
            data[x-1][y] = 0;
            x = x-1;
            counter++;
            initImage();
        }else if(code == 65){
            initImage();
        }else if(code == 87){
            data = new int[][]{
                    {1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,0}
            };
            initImage();
        }
    }

2.2.4.6 鼠标监听重构方法

 @Override
    public void actionPerformed(ActionEvent e) {
        //获取当前被点击的对象
        Object obj = e.getSource();
        if(obj == replayItem){
            //再次打乱
            initData();
            //计数器清零
            counter =0;
            //重新加载
            initImage();

        }else if(obj == reLoginItem){
            //返回登陆界面
            //关闭当前游戏界面
            this.setVisible(false);
            //打开登陆界面 这里由于我们没有实现,所以无法使用
            new LoginJframe();
        }else if(obj == closeItem){
            System.exit(0);
        }else if(obj == accountItem){
            //创建一个弹窗对象
            JDialog jDialog = new JDialog();
            //管理图片
            JLabel jLabel = new JLabel(new ImageIcon("这里放入你公众号,或者别的什么图片路径"));
            //根据图片大小修改位置,我的不一定适配你的
            jLabel.setBounds(0,0,258,258);
            jDialog.getContentPane().add(jLabel);
            jDialog.setSize(344,344);
            jDialog.setAlwaysOnTop(true);
            //居中
            jDialog.setLocationRelativeTo(null);
            //弹窗不关闭无法操作当前界面
            jDialog.setModal(true);
            //显示弹窗
            jDialog.setVisible(true);
        }else if(obj == March){
            pathAll = "image/Star_rail/Start Rail.jpg";
            path1 = "image/Star_rail/(";
            initImage();
        }else if(obj == FireFly) {
            pathAll = "image/Fire fly/Fire Fly.jpg";
            path1 = "image/Fire fly/(";
            initImage();
        }
2.2.4.6 完整代码
2.2.4.6.1 主函数
import Jframe.GameJframe;

//拼图游戏
public class App {
    public static void main(String[] args) {
        new GameJframe();
    }
}
2.2.4.6.2 游戏界面
package Jframe;

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
import java.util.Random;

public class GameJframe extends JFrame implements KeyListener, ActionListener {
    //建立随机二维数组
    //加载图片的时候,根据二维数组加载
    int[][] data = new int[4][4];
    //计数器,用来统计步数
    int counter = 0;

    //记录分散图片路径
    String path1 = "image/Star_rail/(";
    //记录完成图片路径
    String pathAll = "image/Star_rail/Start Rail.jpg";

    //初始化菜单选项
    JMenu functionJMenu = new JMenu("功能");
    JMenu aboutJMenu = new JMenu("关于我");

    //创建选项下面的条目对象
    JMenuItem replayItem = new JMenuItem("重新游戏");
    JMenuItem reLoginItem = new JMenuItem("重新登陆");
    JMenuItem closeItem = new JMenuItem("关闭游戏");
    JMenu changeImage = new JMenu("更换图片");
    JMenu Star_rail = new JMenu("崩铁");

    //创建更改图片下的菜单

    JMenuItem accountItem = new JMenuItem("公众号");

    //创建崩铁下的选项
    JMenuItem March = new JMenuItem("三月七");
    JMenuItem FireFly = new JMenuItem("流萤");



    int[][] win = {
            {1,2,3,4},
            {5,6,7,8},
            {9,10,11,12},
            {13,14,15,0}
    };

    public GameJframe(){

        //设置界面大小
        initJFrame();

        //初始化菜单
        initJMenuBar();

        //初始化数据
        initData();

        //初始化图片(根据打乱之后的结果加载图片)
        initImage();

        //展示整个界面
        this.setVisible(true);

    }

    //初始化数据
    //记录空白方块的位置
    int x,y;
    private void initData(){
        //需求:把0-15的数据打乱顺序
        //然后再按照4各一组的方式添加到二维数组中
        int[] tempArr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
        //打乱数组中的数字
        Random r = new Random();
        for (int i = 0; i < tempArr.length; i++) {
            //随机索引
            int index = r.nextInt(tempArr.length);
            int temp = tempArr[i];
            tempArr[i] = tempArr[index];
            tempArr[index] = temp;
        }

        //给二维数组添加数据
        for(int i :tempArr){
            if(tempArr[i]==0){
                x = i / 4;
                y = i % 4;
            }
            data[i / 4][i % 4] = tempArr[i];
        }
    }

    //初始化图片
    //先加载的图片在上方,后加载的,塞到了先加载的后方
    private void initImage() {
        this.getContentPane().removeAll();
        if(check_win()){
            //显示胜利图标
            JLabel winJLabel = new JLabel(new ImageIcon("image/winJframe.jpg"));
            winJLabel.setBounds(173,-5,210,80);
            this.getContentPane().add(winJLabel);
        }
        JLabel Stepcounter = new JLabel("步数:"+counter);
        Stepcounter.setBounds(50,30,100,20);
        this.getContentPane().add(Stepcounter);


        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 4; i++) {
                //获取打乱二维数组序号
                int num = data[j][i];
                JLabel jLabel = new JLabel(new ImageIcon(path1+num+").jpg"));
                jLabel.setBounds(105 * i+83, 105*j+134, 105, 105);

                //给图片加边框
                jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));
                this.getContentPane().add(jLabel);
            }
        }
        //刷新界面
        this.getContentPane().repaint();
    }


    //创建菜单界面
    private void initJMenuBar() {
        JMenuBar jMenuBar = new JMenuBar();
        //将Item添加到JMenu中
        functionJMenu.add(replayItem);
        functionJMenu.add(reLoginItem);
        functionJMenu.add(closeItem);
        functionJMenu.add(changeImage);
        aboutJMenu.add(accountItem);

        //给更改图片加菜单
        changeImage.add(Star_rail);


        //给崩铁加选项
        Star_rail.add(March);
        Star_rail.add(FireFly);


        //将JMenu添加到JMenuBar中
        jMenuBar.add(functionJMenu);
        jMenuBar.add(aboutJMenu);

        //给游戏功能绑定事件
        replayItem.addActionListener(this);
        reLoginItem.addActionListener(this);
        closeItem.addActionListener(this);
        accountItem.addActionListener(this);

        //给选项添加监听
        March.addActionListener(this);
        FireFly.addActionListener(this);

        //将菜单放在界面中
        this.setJMenuBar(jMenuBar);

    }
    //判断胜利
    private boolean check_win(){
        return Arrays.deepEquals(data, win);
    }
    private void initJFrame() {
        this.setSize(603,680);
        //设置界面标题
        this.setTitle("拼图单机版");
        //设置界面保持上层
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置界面关闭模式
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //取消默认居中放置,之后才能按照xy轴放置
        this.setLayout(null);

        //给整个界面添加键盘监听事件
        this.addKeyListener(this);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {
        int code = e.getKeyCode();
        if(code == 65){
            //把界面中所有图片删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            JLabel all = new JLabel(new ImageIcon(pathAll));      
            all.setBounds(83,134,420,420);
            this.getContentPane().add(all);
            //刷新界面
            this.getContentPane().repaint();
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        //判断游戏游戏是否胜利
        if(check_win()){
            return;
        }
        //左:37  上:38  右:39 下:40
        //
        int code = e.getKeyCode();
        if(code == 37){
            data[x][y] = data[x][y+1];
            data[x][y+1] = 0;
            y = y+1;
            counter++;
            initImage();
        }else if(code == 38){
            data[x][y] = data[x+1][y];
            data[x+1][y] = 0;
            x = x+1;
            counter++;
            initImage();
        }else if(code == 39){
            data[x][y] =data[x][y-1];
            data[x][y-1] = 0;
            y=y-1;
            counter++;
            initImage();
        }else if(code == 40){
            data[x][y] = data[x-1][y];
            data[x-1][y] = 0;
            x = x-1;
            counter++;
            initImage();
        }else if(code == 65){
            initImage();
        }else if(code == 87){
            data = new int[][]{
                    {1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,0}
            };
            initImage();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //获取当前被点击的对象
        Object obj = e.getSource();
        if(obj == replayItem){
            //再次打乱
            initData();
            //计数器清零
            counter =0;
            //重新加载
            initImage();

        }else if(obj == reLoginItem){
            //返回登陆界面
            //关闭当前游戏界面
            this.setVisible(false);
            //打开登陆界面
            new LoginJframe();
        }else if(obj == closeItem){
            System.exit(0);
        }else if(obj == accountItem){
            //创建一个弹窗对象
            JDialog jDialog = new JDialog();
            //管理图片
            JLabel jLabel = new JLabel(new ImageIcon("放入你公众号的图片"));
            jLabel.setBounds(0,0,258,258);
            jDialog.getContentPane().add(jLabel);
            jDialog.setSize(344,344);
            jDialog.setAlwaysOnTop(true);
            //居中
            jDialog.setLocationRelativeTo(null);
            //弹窗不关闭无法操作当前界面
            jDialog.setModal(true);
            //显示弹窗
            jDialog.setVisible(true);
        }else if(obj == March){
            pathAll = "image/Star_rail/Start Rail.jpg";
            path1 = "image/Star_rail/(";
            initImage();
        }else if(obj == FireFly) {
            pathAll = "image/Fire fly/Fire Fly.jpg";
            path1 = "image/Fire fly/(";
            initImage();
        }
    }
}

三、注意事项

没什么其他可讲的,如果出现了图片未加载出来,多半是因为你的图片路径不对。我上述的代码涉及到的路径,你可以照着写一个,但是如果你有你的图片路径,一定要找到这个图片路径,再重新写入。

  • 26
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,下面是一个简单的 Java 编写的拼图游戏实现,它使用了 Java Swing GUI 库来创建用户界面。 首先,我们需要创建一个继承自 JFrame 的主窗口类 PuzzleGameFrame: ```java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PuzzleGameFrame extends JFrame { private PuzzleGamePanel puzzleGamePanel; public PuzzleGameFrame() { super("Puzzle Game"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setResizable(false); puzzleGamePanel = new PuzzleGamePanel(); getContentPane().add(puzzleGamePanel, BorderLayout.CENTER); pack(); setLocationRelativeTo(null); setVisible(true); } public static void main(String[] args) { new PuzzleGameFrame(); } } ``` 在主窗口类中,我们创建了一个 PuzzleGamePanel 对象并将其添加到窗口的中心位置。 接下来,我们需要创建一个继承自 JPanel 的面板类 PuzzleGamePanel: ```java import java.awt.*; import java.awt.event.*; import javax.swing.*; public class PuzzleGamePanel extends JPanel { private final int ROWS = 3; private final int COLUMNS = 3; private JButton[][] puzzleButtons; private ImageIcon[][] puzzleImages; private ImageIcon blankImage; private int blankRow; private int blankColumn; public PuzzleGamePanel() { setLayout(new GridLayout(ROWS, COLUMNS)); puzzleButtons = new JButton[ROWS][COLUMNS]; puzzleImages = new ImageIcon[ROWS][COLUMNS]; for (int row = 0; row < ROWS; row++) { for (int column = 0; column < COLUMNS; column++) { int index = row * COLUMNS + column; puzzleImages[row][column] = new ImageIcon("image" + index + ".jpg"); puzzleButtons[row][column] = new JButton(puzzleImages[row][column]); puzzleButtons[row][column].addActionListener(new PuzzleButtonListener(row, column)); add(puzzleButtons[row][column]); } } blankImage = new ImageIcon("imageblank.jpg"); blankRow = ROWS - 1; blankColumn = COLUMNS - 1; puzzleButtons[blankRow][blankColumn].setIcon(blankImage); } private void swap(int row1, int column1, int row2, int column2) { ImageIcon temp = puzzleImages[row1][column1]; puzzleImages[row1][column1] = puzzleImages[row2][column2]; puzzleImages[row2][column2] = temp; puzzleButtons[row1][column1].setIcon(puzzleImages[row1][column1]); puzzleButtons[row2][column2].setIcon(puzzleImages[row2][column2]); } private boolean isAdjacent(int row1, int column1, int row2, int column2) { if (row1 == row2 && Math.abs(column1 - column2) == 1) { return true; } if (column1 == column2 && Math.abs(row1 - row2) == 1) { return true; } return false; } private boolean isSolved() { int index = 0; for (int row = 0; row < ROWS; row++) { for (int column = 0; column < COLUMNS; column++) { if (index != ROWS * COLUMNS - 1 && puzzleImages[row][column] != puzzleImages[index / COLUMNS][index % COLUMNS]) { return false; } index++; } } return true; } private class PuzzleButtonListener implements ActionListener { private int row; private int column; public PuzzleButtonListener(int row, int column) { this.row = row; this.column = column; } public void actionPerformed(ActionEvent event) { if (isAdjacent(row, column, blankRow, blankColumn)) { swap(row, column, blankRow, blankColumn); blankRow = row; blankColumn = column; if (isSolved()) { JOptionPane.showMessageDialog(null, "Congratulations, you solved the puzzle!"); } } } } } ``` 在面板类中,我们创建了一个 3x3 的拼图游戏,并为每个按钮添加了一个 ActionListener 监听器。当用户点击一个按钮时,程序会检查该按钮是否与空白按钮相邻,如果是,则交换它们的位置。当所有的按钮都被正确地交换到其正确的位置时,程序会弹出一个消息框,告知用户已经完成了拼图。 最后,我们需要将图像文件 image0.jpg 到 image8.jpg 和 imageblank.jpg 放置在程序的根目录下。 这是一个简单的 Java 编写的拼图游戏实现。您可以根据自己的需要进行修改和定制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值