侧边栏壁纸
博主头像
马杰如的博客

一切有为法,如梦幻泡影,如露亦如电,应作如是观。

  • 累计撰写 10 篇文章
  • 累计创建 7 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Java-------拼图小游戏

马杰如
2025-06-08 / 0 评论 / 1 点赞 / 7 阅读 / 0 字
温馨提示:
部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

根据b站黑马程序员的视频教程写的,做了一些改进和优化,例如直接随机打乱存在无法复原的情况,要对初始状态进行一定的校验,如果无解就重新打乱.保证游戏有解.游戏我也做成了安装包,想体验可以下载游玩.

https://www.123684.com/s/NbKDjv-19AAA

下面是游戏的主体代码,继承JFrame实现GUI,实现KeyListener, ActionListener 接口,对鼠标和键盘的操作进行监听.

import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.*;
import java.net.URI;
import java.util.Random;

//游戏的主界面
public class GameJFrame extends JFrame implements KeyListener, ActionListener {
    //记录所有图片的索引
    private int[][] Array = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}};
    //记录空白的坐标
    private int x = 0, y = 0;
    //记录图片的路径
    private String path = "image\\animal\\animal3\\";
    //记录走的步数
    private int step = 0;
    //创建选项下面的条目对象
    private JMenuItem replayItem = new JMenuItem("重新游戏");
    private JMenuItem closeItem = new JMenuItem("关闭游戏");

    private JMenuItem accountItem = new JMenuItem("主播粉丝群");
    private JMenuItem blogItem = new JMenuItem("主播博客");

    private JMenuItem girl = new JMenuItem("美女");
    private JMenuItem animal = new JMenuItem("动物");
    private JMenuItem sport = new JMenuItem("运动");
    Random rand = new Random();

    public GameJFrame() {
        //初始化窗口
        InitJframe();
        //初始化菜单
        InitMenu();
        //初始化数据
        InitData();
        //初始化图片
        InitImage();
        //让界面显示出来,写在最后
        setVisible(true);
    }


    //实现打乱图片的效果
    public void InitData() {
        //初始化一维数组
        int[] tempArr = new int[16];
        for (int i = 0; i < tempArr.length; i++) {
            tempArr[i] = i;
        }
        while (true) {
            //Fisher–Yates 洗牌算法打乱数组
            for (int i = tempArr.length - 1; i >= 0; i--) {
                int index = rand.nextInt(i + 1);
                int temp = tempArr[index];
                tempArr[index] = tempArr[i];
                tempArr[i] = temp;
            }
            //计算逆序数和0所在的行,保证游戏有解
            int temp_count = 0;
            for (int i = 0; i < tempArr.length; i++) {
                if (tempArr[i] == 0) {
                    continue;
                }
                for (int j = i + 1; j < tempArr.length; j++) {
                    if (tempArr[j] == 0) {
                        continue;
                    }
                    if (tempArr[i] > tempArr[j]) {
                        temp_count++;
                    }
                }
            }
            //将一维数组的数据转移到4X4的二维数组
            for (int i = 0; i < tempArr.length; i++) {
                if (tempArr[i] == 0) {
                    x = i / 4;
                    y = i % 4;
                }
                Array[i / 4][i % 4] = tempArr[i];
                System.out.print(tempArr[i] + ",");
            }
            System.out.println();
            temp_count += (4 - x);
            if (temp_count % 2 == 0) {
                break;
            }
        }
    }


    public void InitImage() {
        //清空之前存在的元素
        this.getContentPane().removeAll();
        //判断是否胜利,添加胜利图片
        if (victory()) {
            JLabel win_picture = new JLabel(new ImageIcon(".\\image\\win.png"));
            win_picture.setBounds(203, 283, 197, 73);
            getContentPane().add(win_picture);
        }
        JLabel step_count = new JLabel("步数:" + step);
        step_count.setBounds(50, 30, 100, 20);
        getContentPane().add(step_count);
        //添加游戏图片
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                int num = Array[i][j];
                //获取图片的url
                String url = path + num + ".jpg";
                //创建一个图片imageIcaon对象
                ImageIcon icon = new ImageIcon(url);
                //创建一个JLable对象(管理容器)
                JLabel jl = new JLabel(icon);
                //指定图片位置
                jl.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
                //给图片添加边框
                //0代表图片凸起来
                //1代表图片凹下去
                jl.setBorder(new BevelBorder(1));
                //把管理容器添加到界面
                getContentPane().add(jl);
            }
        }
        //添加背景图片
        ImageIcon bg = new ImageIcon(".\\image\\background.png");
        JLabel background = new JLabel(bg);
        background.setBounds(40, 40, 508, 560);
        getContentPane().add(background);
        //刷新界面
        getContentPane().repaint();
    }

    public void InitJframe() {
        //设置界面的宽和高
        setSize(603, 680);
        //设置界面的标题
        setTitle("拼图单机版 V1.0");
        //设置界面置顶
        setAlwaysOnTop(true);
        //设置窗口不可拉伸
        setResizable(false);
        //设置界面居中显示
        setLocationRelativeTo(null);
        //设置关闭模式
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //取消默认的居中放置,取消之后才会按照x,y坐标放置图片
        setLayout(null);
        //添加键盘监听事件
        addKeyListener(this);
    }

    public void InitMenu() {
        //初始化菜单
        //创建整个的菜单对象
        JMenuBar menuBar = new JMenuBar();

        //创建菜单上的两个选项的对象(功能,关于我们)
        JMenu functionJmenu = new JMenu("功能");
        JMenu aboutJmenu = new JMenu("关于作者");
        JMenu charge = new JMenu("更换图片");
        //将每一个选项下面的条目添加到选项当中
        functionJmenu.add(charge);
        functionJmenu.add(replayItem);
        functionJmenu.add(closeItem);

        aboutJmenu.add(accountItem);
        aboutJmenu.add(blogItem);

        charge.add(girl);
        charge.add(animal);
        charge.add(sport);
        //给条目绑定事件
        girl.addActionListener(this);
        animal.addActionListener(this);
        sport.addActionListener(this);
        replayItem.addActionListener(this);
        closeItem.addActionListener(this);
        accountItem.addActionListener(this);
        blogItem.addActionListener(this);
        //将两个选项添加到菜单里
        menuBar.add(functionJmenu);
        menuBar.add(aboutJmenu);
        //将菜单添加到整个界面
        setJMenuBar(menuBar);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //按下不松调用的方法
    @Override
    public void keyPressed(KeyEvent e) {
        //游戏结束不能进行其他操作
        if (victory()) {
            return;
        }
        int code = e.getKeyCode();
        if (code == 65) {
            //删除全部图片
            this.getContentPane().removeAll();
            //加载完整的图片
            JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
            all.setBounds(83, 134, 420, 420);
            this.getContentPane().add(all);
            //加载背景图片
            ImageIcon bg = new ImageIcon(".\\image\\background.png");
            JLabel background = new JLabel(bg);
            background.setBounds(40, 40, 508, 560);
            getContentPane().add(background);
            //刷新界面
            getContentPane().repaint();


        }
    }

    //按下松开后调用的方法
    @Override
    public void keyReleased(KeyEvent e) {
        //游戏结束不能再进行其他操作
        if (victory()) {
            return;
        }
        int code = e.getKeyCode();
        //左37,上38,右39,下40
        if (code == 37) {
            if (y + 1 < 4) {
                Array[x][y] = Array[x][y + 1];
                Array[x][y + 1] = 0;
                y++;
                step++;
                InitImage();
                System.out.println("向左移动");
            } else {
                System.out.println("向左移动失败");
            }
        } else if (code == 38) {
            if (x + 1 < 4) {
                Array[x][y] = Array[x + 1][y];
                Array[x + 1][y] = 0;
                x++;
                step++;
                InitImage();
                System.out.println("向上移动");
            } else {
                System.out.println("向上移动失败");
            }
        } else if (code == 39) {
            if (y - 1 >= 0) {
                Array[x][y] = Array[x][y - 1];
                Array[x][y - 1] = 0;
                y--;
                step++;
                InitImage();
                System.out.println("向右移动");
            } else {
                System.out.println("向右移动失败");
            }
        } else if (code == 40) {

            if (x - 1 >= 0) {
                Array[x][y] = Array[x - 1][y];
                Array[x - 1][y] = 0;
                x--;
                step++;
                InitImage();
                System.out.println("向下移动");
            } else {
                System.out.println("向下移动失败");
            }
        } else if (code == 65) {
            InitImage();
        } else if (code == 80) {
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    Array[i][j] = i * 4 + j + 1;
                }
            }
            Array[3][3] = 0;
            InitImage();
        }
    }

    //判断是否胜利
    public boolean victory() {
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                if (i == 3 && j == 3) {
                    continue;
                }
                if (Array[i][j] != i * 4 + j + 1) {
                    return false;
                }
            }
        }
        return true;
    }

    //鼠标点击事件
    @Override
    public void actionPerformed(ActionEvent e) {
        Object obj = e.getSource();
        if (obj == replayItem) {
            step = 0;
            InitData();
            InitImage();
            System.out.println("重新游戏");
        } else if (obj == closeItem) {
            System.exit(0);
            System.out.println("关闭游戏");
        } else if (obj == accountItem) {
            try {
                Desktop desktop = Desktop.getDesktop();
                desktop.browse(new URI("https://qm.qq.com/q/dgv5awkpDG"));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            System.out.println("粉丝群");
        } else if (obj == blogItem) {
            try {
                Desktop desktop = Desktop.getDesktop();
                desktop.browse(new URI("https://homeofmjr.top"));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            System.out.println("博客");
        } else if (obj == girl) {
            int number = rand.nextInt(11) + 1;
            path = "image\\girl\\girl" + number + "\\";
            step = 0;
            InitData();
            InitImage();
            System.out.println("美女图片");
        } else if (obj == animal) {
            int number = rand.nextInt(8) + 1;
            path = "image\\animal\\animal" + number + "\\";
            step = 0;
            InitData();
            InitImage();
            System.out.println("动物图片");
        } else if (obj == sport) {
            int number = rand.nextInt(10) + 1;
            path = "image\\sport\\sport" + number + "\\";
            step = 0;
            InitData();
            InitImage();
            System.out.println("运动图片");
        }
    }
}

下面是程序的主入口

public class App {
    public static void main(String[] args) {
new GameJFrame();
    }
}

1

评论区