笔记四:Java基础阶段结束,用GUI实现的美女拼图游戏

Java
230
0
0
2023-07-17

此小游戏可通过按钮来实现上下左右的拼图,还可以通过求助和重置按钮来复原和重新开始游戏。

在项目开始之前,希望大家多多支持,点个赞。谢谢!

思路分析:

  • – 绘制游戏界面
  • – 实现图片打乱
  • – 给按钮添加事件
  • – 移动空白图片按钮的实现
  • – 求助按钮的实现
  • – 重置按钮的实现

1、用 GUI 绘制游戏界面

思路分析:

  • 新建一个类:PictureFrame,让这个类继承自JFrame。
  • – 在PictureFrame类中编写无参 构造方法 ,在构造方法中调用两个方法;initFrame()方法,用于窗口的基本设置。setVisible(true)方法,用于设置窗口可见。
  • – 在initFrame()方法中设置窗口可见:
  • 1、窗口大小
  • 2、窗口标题
  • 3、窗口居中
  • 4、窗口关闭是退出程序
  • 5、窗口位于其他窗口之上
  • 6、取消窗口默认布局
  • 定义方法用于窗口上组件的绘制:paintView();并在构造方法中调用。
  • – 把所有的按钮和面板定义为成员变量,写进PictureFrame类中。
  • – 定义测试类App;创建PictureFrame的对象进行测试。
 public class PictureFrame  extends   JFrame  {
    //定义按钮的成员变量
 private  JButton shangButton;
    private JButton zuoButton;
    private JButton xiaButton;
    private JButton youButton;
    private JButton qiuZhuButton;
    private JButton chongZhiButton;
    //设置一个面板的成员变量
    private  JPanel  imagePanel;
    public PictureFrame() {
        //用于 窗体 的基本设置
        initFrame();
        //窗口上组件的绘制
        paintview();
        //设置窗体可见
        this.setVisible(true);
    }
    public  void  initFrame() {
        //设置窗口大小
        this.setSize(, 565);
        //设置窗口关闭时默认操作(整数表示:窗口关闭时退出应用程序)
        this.setDefaultCloseOperation();
        //设置位置,值为null,则窗口位置屏幕中央
        this.setLocationRelativeTo(null);
        //设置此窗口是否始终位于其他窗口之上
        this.setAlwaysOnTop(true);
        //设置窗口标题
        this.setTitle("动漫拼图");
        //取消JFrame的默认布局
        this.setLayout(null);
    }
    //窗体上组件的绘制
    public void paintview() {
        //标题图片
        JLabel titleLabel = new JLabel(new ImageIcon("day\images\title.png"));
        titleLabel.setBounds(, 27, 232, 57);
        this.add(titleLabel);
        //创建面板
        imagePanel = new JPanel();
        imagePanel.setBounds(, 114, 360, 360);
        imagePanel.setLayout(null);
        //遍历 二维数组 ,得到图片编号
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                //创建JLabel对象,加载图片资源
                JLabel imagesJlabel = new JLabel(new ImageIcon("day\\images\\" + datas[i][j] + ".png"));
                //调整照片位置
                imagesJlabel.setBounds(j *, i * 90, 90, 90);
                imagePanel.add(imagesJlabel);
            }
        }
        //把面板添加到窗体上
        this.add(imagePanel);
        //拼图参照图
        JLabel canZhaoTuLabel = new JLabel(new ImageIcon("day\images\canzhaotu.png"));
        canZhaoTuLabel.setBounds(, 114, 122, 121);
        this.add(canZhaoTuLabel);
        //上下左右、求助、重置按钮
        shangButton = new JButton(new ImageIcon("day\images\shang.png"));
        shangButton.setBounds(, 265, 57, 57);
        this.add(shangButton);
        zuoButton = new JButton(new ImageIcon("day\images\zuo.png"));
        zuoButton.setBounds(, 347, 57, 57);
        this.add(zuoButton);
        xiaButton = new JButton(new ImageIcon("day\images\xia.png"));
        xiaButton.setBounds(, 347, 57, 57);
        this.add(xiaButton);
        youButton = new JButton(new ImageIcon("day\images\you.png"));
        youButton.setBounds(, 347, 57, 57);
        this.add(youButton);
        qiuZhuButton = new JButton(new ImageIcon("day\images\qiuzhu.png"));
        qiuZhuButton.setBounds(, 444, 108, 45);
        this.add(qiuZhuButton);
        chongZhiButton = new JButton(new ImageIcon("day\images\chongzhi.png"));
        chongZhiButton.setBounds(, 444, 108, 45);
        this.add(chongZhiButton);
        //展示背景图
        JLabel backgroundLabel = new JLabel(new ImageIcon("day\images\background.png"));
        backgroundLabel.setBounds(, 0, 960, 530);
        this.add(backgroundLabel);
    }
} 

测试类:

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

2、图片打乱并给按钮添加事件(用按钮移动空白图片)

思路分析

  • – 定义方法,用于打乱二维数组:initData()
  • – 创建Random对象,遍历存储的二维数字,得到每一个元素
  • – 产生两个随机索引,进行二维数组元素交换
  • – 定义之前现在类中定义一个二维数组
  • – 在构造方法中调用initData()方法
  • – 数组中的0是用来记录0号索引空白图片
  • – 给按钮添加事件,用来实现移动空白图片的位置,
  • 1、移动空白图片的位置就是和上下左右的图片进行交互,
  • 2、交换完成之后调用重回方法:rePainView(),
  • 3、处理边界问题。
  • – 在测试类App中测试

“` java

 public class PictureFrame extends JFrame {
    //定义一个二维数组,用来储存图片的编号
    private int[][] datas = {
    {, 2, 3, 4},
    {, 6, 7, 8,},
    {, 10, 11, 12},
    {, 14, 15, 0}
    };

    //定义按钮的成员变量
    private JButton shangButton;
    private JButton zuoButton;
    private JButton xiaButton;
    private JButton youButton;
    private JButton qiuZhuButton;
    private JButton chongZhiButton;
    //设置一个面板的成员变量
    private JPanel imagePanel;
    public PictureFrame() {
        //用于窗体的基本设置
        initFrame();
        //窗口上组件的绘制
        paintview();
        //设置窗体可见
        this.setVisible(true);
    }
    public void initFrame() {
        //设置窗口大小
        this.setSize(, 565);
        //设置窗体关闭时默认操作(整数表示:窗口关闭时退出应用程序)
        this.setDefaultCloseOperation();
        //设置位置,值为null,则窗口位置屏幕中央
        this.setLocationRelativeTo(null);
        //设置此窗口是否始终位于其他窗口之上
        this.setAlwaysOnTop(true);
        //设置窗口标题
        this.setTitle("动漫拼图");
        //取消JFrame的默认布局
        this.setLayout(null);
    }
    //窗体上组件的绘制
    public void paintview() {
        //标题图片
        JLabel titleLabel = new JLabel(new ImageIcon("day\images\title.png"));
        titleLabel.setBounds(, 27, 232, 57);
        this.add(titleLabel);
        //创建面板
        imagePanel = new JPanel();
        imagePanel.setBounds(, 114, 360, 360);
        imagePanel.setLayout(null);
        //遍历二维数组,得到图片编号
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                //创建JLabel对象,加载图片资源
                JLabel imagesJlabel = new JLabel(new ImageIcon("day\\images\\" + datas[i][j] + ".png"));
                //调整照片位置
                imagesJlabel.setBounds(j *, i * 90, 90, 90);
                imagePanel.add(imagesJlabel);
            }
        }
        //把面板添加到窗体上
        this.add(imagePanel);
        //拼图参照图
        JLabel canZhaoTuLabel = new JLabel(new ImageIcon("day\images\canzhaotu.png"));
        canZhaoTuLabel.setBounds(, 114, 122, 121);
        this.add(canZhaoTuLabel);
        //上下左右、求助、重置按钮
        shangButton = new JButton(new ImageIcon("day\images\shang.png"));
        shangButton.setBounds(, 265, 57, 57);
        this.add(shangButton);
        zuoButton = new JButton(new ImageIcon("day\images\zuo.png"));
        zuoButton.setBounds(, 347, 57, 57);
        this.add(zuoButton);
        xiaButton = new JButton(new ImageIcon("day\images\xia.png"));
        xiaButton.setBounds(, 347, 57, 57);
        this.add(xiaButton);
        youButton = new JButton(new ImageIcon("day\images\you.png"));
        youButton.setBounds(, 347, 57, 57);
        this.add(youButton);
        qiuZhuButton = new JButton(new ImageIcon("day\images\qiuzhu.png"));
        qiuZhuButton.setBounds(, 444, 108, 45);
        this.add(qiuZhuButton);
        chongZhiButton = new JButton(new ImageIcon("day\images\chongzhi.png"));
        chongZhiButton.setBounds(, 444, 108, 45);
        this.add(chongZhiButton);
        //展示背景图
        JLabel backgroundLabel = new JLabel(new ImageIcon("day\images\background.png"));
        backgroundLabel.setBounds(, 0, 960, 530);
        this.add(backgroundLabel);
        //按钮添加事件
        shangButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (x == 3) {
                    return;
                }
                datas[x][y0] = datas[x0 + 1][y0];
                //这一步作用是啥,为什么要让datas[x+1][y0]=0;
                //原理是交换,datas[x][y0]=0是固定的,然后把datas[x0+1][y0]赋值给datas[x0][y0]
                //再把给datas[x0+1][y0],
                datas[x + 1][y0] = 0;
                x = x0 + 1;
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
        zuoButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (y == 3) {
                    return;
                }
                datas[x][y0] = datas[x0][y0 + 1];
                datas[x][y0 + 1] = 0;
                y = y0 + 1;
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
        xiaButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (x == 0) {
                    return;
                }
                datas[x][y0] = datas[x0 - 1][y0];
                datas[x - 1][y0] = 0;
                x = x0 - 1;
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
        youButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (y == 0) {
                    return;
                }
                datas[x][y0] = datas[x0][y0 - 1];
                datas[x][y0 - 1] = 0;
                y = y0 - 1;

                //对图片进行重新遍历输出
                rePaintView();
            }
        });
    }

    //定义两个int类型的变量,用于记录号图片的位置
    //号图片作用是啥,为什么要定义0号图片
    //号图片作用是和数组里面的编号图片作一交换,用来完成拼图
    private int x;
    private int y;
    //打乱二维数组
    public void randomData() {
        Random random = new Random();
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                int x = random.nextInt(datas.length);
                int y = random.nextInt(datas[i].length);
                int temp = datas[i][j];
                datas[i][j] = datas[x][y];
                datas[x][y] = temp;
            }
        }
        //记录号图片的位置 wc作用是啥?wc作用是给最外层for循环起了一个名字,之后用 break 结束整体循环
        wc:
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                if (datas[i][j] ==) {
                    x = i;
                    y = j;
                    break wc;
                }
            }
        }
    }
    //遍历移动后的图形,移动的图形重新绘制
    public void rePaintView() {
        //移除所有:移除的是JPanel标签上的全部组件,目的就是清空里面的数据
        imagePanel.removeAll();
        //遍历二维数组
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                //创建JLabel对象,加载图片资源
                JLabel imagesJlabel = new JLabel(new ImageIcon("day09\\images\\" + datas[i][j] + ".png"));
                //调整照片位置
                imagesJlabel.setBounds(j * 90, i * 90, 90, 90);
                imagePanel.add(imagesJlabel);
            }
        }
        //对JPanel里面的组件进行从新打印
        imagePanel.repaint();
    }
} 

3、求助按钮和重置按钮、游戏成功后的实现

思路分析

  • – 定义移动成功分方法:success();
  • 1、在方法中实现成功之后按钮不可用,
  • – 在求助按钮中调用两个方式实现操作
  • 1、调用success();
  • 2、调用rePaintView();
  • – 当重置之后需要修个数组,使数组变为之前带有0号图片的数组
  • – 打乱数组
  • – 重绘面板
  • – 设置按钮可用
  • – 万一有人成功通过游戏怎么办
  • 先在PictureFrame类中定义新的成功的二维数组
  • 1、定义一个方法,用于比较两个数组(`新的数组和老的数组`)元素是否相同
  • 2、每次移动一个按钮调用这个方法,如果返回为true,则调用success()方法;
  • – 去测试类中测试代码的可行性就完成了
 public class PictureFrame extends JFrame {
    //定义一个二维数组,用来储存图片的编号
    private int[][] datas = {
    {, 2, 3, 4},
    {, 6, 7, 8,},
    {, 10, 11, 12},
    {, 14, 15, 0}
    };
    //定义一个成功的二维数组
    private int[][] winDatas = {
    {, 2, 3, 4},
    {, 6, 7, 8},
    {, 10, 11, 12},
    {, 14, 15, 0}
    };
    //定义按钮的成员变量
    private JButton shangButton;
    private JButton zuoButton;
    private JButton xiaButton;
    private JButton youButton;
    private JButton qiuZhuButton;
    private JButton chongZhiButton;
    //设置一个面板的成员变量
    private JPanel imagePanel;
    public PictureFrame() {
        //用于窗体的基本设置
        initFrame();
        //窗口上组件的绘制
        paintview();
        //设置窗体可见
        this.setVisible(true);
    }
    public void initFrame() {
        //设置窗口大小
        this.setSize(, 565);
        //设置窗体关闭时默认操作(整数表示:窗口关闭时退出应用程序)
        this.setDefaultCloseOperation();
        //设置位置,值为null,则窗口位置屏幕中央
        this.setLocationRelativeTo(null);
        //设置此窗口是否始终位于其他窗口之上
        this.setAlwaysOnTop(true);
        //设置窗口标题
        this.setTitle("动漫拼图");
        //取消JFrame的默认布局
        this.setLayout(null);
    }
    //窗体上组件的绘制
    public void paintview() {
        //标题图片
        JLabel titleLabel = new JLabel(new ImageIcon("day\images\title.png"));
        titleLabel.setBounds(, 27, 232, 57);
        this.add(titleLabel);
        //创建面板
        imagePanel = new JPanel();
        imagePanel.setBounds(, 114, 360, 360);
        imagePanel.setLayout(null);
        //遍历二维数组,得到图片编号
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                //创建JLabel对象,加载图片资源
                JLabel imagesJlabel = new JLabel(new ImageIcon("day\\images\\" + datas[i][j] + ".png"));
                //调整照片位置
                imagesJlabel.setBounds(j *, i * 90, 90, 90);
                imagePanel.add(imagesJlabel);
            }
        }
        //把面板添加到窗体上
        this.add(imagePanel);
        //拼图参照图
        JLabel canZhaoTuLabel = new JLabel(new ImageIcon("day\images\canzhaotu.png"));
        canZhaoTuLabel.setBounds(, 114, 122, 121);
        this.add(canZhaoTuLabel);
        //上下左右、求助、重置按钮
        shangButton = new JButton(new ImageIcon("day\images\shang.png"));
        shangButton.setBounds(, 265, 57, 57);
        this.add(shangButton);
        zuoButton = new JButton(new ImageIcon("day\images\zuo.png"));
        zuoButton.setBounds(, 347, 57, 57);
        this.add(zuoButton);
        xiaButton = new JButton(new ImageIcon("day\images\xia.png"));
        xiaButton.setBounds(, 347, 57, 57);
        this.add(xiaButton);
        youButton = new JButton(new ImageIcon("day\images\you.png"));
        youButton.setBounds(, 347, 57, 57);
        this.add(youButton);
        qiuZhuButton = new JButton(new ImageIcon("day\images\qiuzhu.png"));
        qiuZhuButton.setBounds(, 444, 108, 45);
        this.add(qiuZhuButton);
        chongZhiButton = new JButton(new ImageIcon("day\images\chongzhi.png"));
        chongZhiButton.setBounds(, 444, 108, 45);
        this.add(chongZhiButton);
        //展示背景图
        JLabel backgroundLabel = new JLabel(new ImageIcon("day\images\background.png"));
        backgroundLabel.setBounds(, 0, 960, 530);
        this.add(backgroundLabel);
        //按钮添加事件
        shangButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (x == 3) {
                    return;
                }
                datas[x][y0] = datas[x0 + 1][y0];
                //这一步作用是啥,为什么要让datas[x+1][y0]=0;
                //原理是交换,datas[x][y0]=0是固定的,然后把datas[x0+1][y0]赋值给datas[x0][y0]
                //再把给datas[x0+1][y0],
                datas[x + 1][y0] = 0;
                x = x0 + 1;
                //调用判断方法,成功之后调用提示按钮的方法
                if (isSuccess()) {
                    success();
                }
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
        zuoButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (y == 3) {
                    return;
                }
                datas[x][y0] = datas[x0][y0 + 1];
                datas[x][y0 + 1] = 0;
                y = y0 + 1;
                //调用判断方法,成功之后调用提示按钮的方法
                if (isSuccess()) {
                    success();
                }
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
        xiaButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (x == 0) {
                    return;
                }
                datas[x][y0] = datas[x0 - 1][y0];
                datas[x - 1][y0] = 0;
                x = x0 - 1;
                //调用判断方法,成功之后调用提示按钮的方法
                if (isSuccess()) {
                    success();
                }
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
        youButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (y == 0) {
                    return;
                }
                datas[x][y0] = datas[x0][y0 - 1];
                datas[x][y0 - 1] = 0;
                y = y0 - 1;
                //调用判断方法,成功之后调用提示按钮的方法
                if (isSuccess()) {
                    success();
                }
                //对图片进行重新遍历输出
                rePaintView();
            }
        });
    }

    //定义两个int类型的变量,用于记录号图片的位置
    //号图片作用是啥,为什么要定义0号图片
    //号图片作用是和数组里面的编号图片作一交换,用来完成拼图
    private int x;
    private int y;
    //打乱二维数组
    public void randomData() {
        Random random = new Random();
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                int x = random.nextInt(datas.length);
                int y = random.nextInt(datas[i].length);
                int temp = datas[i][j];
                datas[i][j] = datas[x][y];
                datas[x][y] = temp;
            }
        }
        //记录号图片的位置 wc作用是啥?wc作用是给最外层for循环起了一个名字,之后用break结束整体循环
        wc:
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                if (datas[i][j] ==) {
                    x = i;
                    y = j;
                    break wc;
                }
            }
        }
    }
    //遍历移动后的图形,移动的图形重新绘制
    public void rePaintView() {
        //移除所有:移除的是JPanel标签上的全部组件,目的就是清空里面的数据
        imagePanel.removeAll();
        //遍历二维数组
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                //创建JLabel对象,加载图片资源
                JLabel imagesJlabel = new JLabel(new ImageIcon("day09\\images\\" + datas[i][j] + ".png"));
                //调整照片位置
                imagesJlabel.setBounds(j * 90, i * 90, 90, 90);
                imagePanel.add(imagesJlabel);
            }
        }
        //对JPanel里面的组件进行从新打印
        imagePanel.repaint();
    }
    //定义一个成功的操作,用提示来调用
    public void success() {
        datas = new int[][]{
        {, 2, 3, 4},
        {, 6, 7, 8},
        {, 10, 11, 12},
        {, 14, 15, 16}
        };
        shangButton.setEnabled(false);
        zuoButton.setEnabled(false);
        xiaButton.setEnabled(false);
        youButton.setEnabled(false);
    }
    //定义一个点击按钮判断是否成功的方法
    public boolean isSuccess() {
        for (int i =; i < datas.length; i++) {
            for (int j =; j < datas[i].length; j++) {
                if (datas[i][j] != winDatas[i][j]) {
                    return false;
                }
            }
        }
        return true;
    }
}