侧边栏壁纸
博主头像
青菜-halo2 博主等级

行动起来,活在当下

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

目 录CONTENT

文章目录

16-阶段项目-拼图小游戏_01

Administrator
2025-11-18 / 0 评论 / 3 点赞 / 28 阅读 / 0 字

1.界面搭建

1.1 主界面分析:

  • 组件:

    • JFrame:最外层的窗体

    • JmenuBar:最上层的菜单

    • JLbel:管理文字和图片的容器

1.2 创建主界面1:

创建一个宽603像素,高680像素的游戏主界面
创建一个款488像素,高430像素的登录界面
创建一个款488像素,高500像素的注册界面
​
//App.java
public class App {
    public static void main(String[] args) {
        //表示程序的启动入口
        new LoginJFrame();
        new RegisterJFrame();
        new GameJFrame();
    }
}
​
//GameJFrame.java
public class GameJFrame extends JFrame {
    //游戏相关的所有代码,在此类中
    public GameJFrame(){
        this.setSize(603, 680);
        this.setVisible(true);
    }
}
​
public class LoginJFrame extends JFrame {
    //所有与登录相关的代码,在此类中
    public LoginJFrame(){
        //在创建登录页面的时候,同时给这个页面设置一些信息,比如宽、高、显示
        this.setSize(488,430);
        this.setVisible(true);
    }
}
​
//RegisterJFrame.java
public class RegisterJFrame extends JFrame {
    //注册相关的代码,在此类中
    public RegisterJFrame(){
        this.setSize(488, 500);
        this.setVisible(true);
    }
}

2.界面设置和菜单搭建

2.1 界面设置

public class GameJFrame extends JFrame {
    //游戏相关的所有代码,在此类中
    public GameJFrame(){
        //设置界面的宽高
        this.setSize(603, 680);
        //设置界面的标题
        this.setTitle("拼图单机版 v1.0");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        //this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setDefaultCloseOperation(3);
        //让界面显示,写在最后
        this.setVisible(true);
    }
}
//其他类似

2.2 菜单制作

JmenuBar:表示整个菜单

Jmenu:选项

  • JmenuItem:条目

import javax.swing.*;
​
public class GameJFrame extends JFrame {
    //游戏相关的所有代码,在此类中
    public GameJFrame(){
        //初始化界面
        initJFrame();
​
        //初始化菜单
        initJMnuBar();
​
        //让界面显示,写在最后
        this.setVisible(true);
    }
​
    private void initJMnuBar() {
​
        //创建整个菜单对象
        JMenuBar jMenuBar = new JMenuBar();
​
        //创建菜单上面的两个选项的对象(功能 关于我们)
        JMenu functionJMenu = new JMenu("功能");
        JMenu aboutJMenu = new JMenu("关于我们");
​
        //创建选项下面的条目对象
        JMenuItem replayItem = new JMenuItem("重新游戏");
        JMenuItem reLoginItem = new JMenuItem("重新登录");
        JMenuItem closeItem = new JMenuItem("关闭游戏");
​
        JMenuItem accountItem = new JMenuItem("公众号");
​
        //将每一个选项下面的条目,添加到选项中
        functionJMenu.add(replayItem);
        functionJMenu.add(reLoginItem);
        functionJMenu.add(closeItem);
​
        aboutJMenu.add(accountItem);
​
        //将菜单里面的两个选项添加到菜单当中
        jMenuBar.add(functionJMenu);
        jMenuBar.add(aboutJMenu);
​
        //给整个界面设置菜单
        this.setJMenuBar(jMenuBar);
    }
​
    private void initJFrame() {
        //设置界面的宽高
        this.setSize(603, 680);
        //设置界面的标题
        this.setTitle("拼图单机版 v1.0");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面居中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        //this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        this.setDefaultCloseOperation(3);
    }
}
​

3.添加图片

3.1 添加图片基础逻辑

  • imageicon:地址图片的位置,图片左上角的点位置

  • JLabel 管理区域:存放图片、文字

  • JLabel 添加到 JFrame

    private void initImage() {
        //创建一个图片ImageIcon对象
        ImageIcon icon = new ImageIcon("Z:\\00-暂存区\\java-dev\\src\\day16\\image\\animal\\animal3\\3.jpg");
​
        //创建一个JLable的对象(管理容器)
        JLabel jLabel = new JLabel(icon);
​
        //将管理容器添加到界面中
        this.add(jLabel);
​
    }

3.2 图片放入指定位置

  • 坐标:左上角为原点,横坐标x,纵坐标y

  • 隐藏容器:JFrame 里面存在getContentPane() 获取

//需要在initJFrame中取消默认居中
    private void initJFrame() {
        //。。。
        //取消默认剧中放置
        this.setLayout(null);
    }
​
//修改initImage方法
    private void initImage() {
        //创建一个图片ImageIcon对象
        ImageIcon icon = new ImageIcon("Z:\\00-暂存区\\java-dev\\src\\day16\\image\\animal\\animal3\\1.jpg");
​
        //创建一个JLable的对象(管理容器)
        JLabel jLabel = new JLabel(icon);
​
        //指定图片位置
        jLabel.setBounds(0, 0 , 105, 105);
​
        //将管理容器添加到界面中
        //this.add(jLabel);
        this.getContentPane().add(jLabel);
    }
​

  • 多张图片坐标

图片左上角的点,对应界面上的点
第一行第一张, 坐标(0,0)
第一行第二张, 坐标(105,0)
第二行第一张, 坐标(0,105)
    private void initImage() {
        int number = 1;
        //外循环 -- 将内循环重复执行了4次
        for (int i = 0; i < 4; i++) {
            //内循环 -- 表示在一行添加4张图片
            for (int j = 0; j < 4; j++) {
                //创建一个图片ImageIcon对象
                //创建一个JLable的对象(管理容器)
                JLabel jLabel = new JLabel(new ImageIcon("Z:\\00-暂存区\\java-dev\\src\\day16\\image\\animal\\animal3\\"+number+".jpg"));
                //指定图片位置
                jLabel.setBounds(105 * j , 105 * i , 105, 105);
                //将管理容器添加到界面中
                //this.add(jLabel);
                this.getContentPane().add(jLabel);
​
                //添加一次后,number+1,表示下一次加载后面一张图片
                number++;
                //number = 16时,如果找不到 16.jpg,仍然会加载jLabel,只不过为空
            }
        }
    }

4.打乱图片

4.1 前置练习:

打乱一维数组的数据
int[] tempArr = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}
要求:打乱一维数组中的数据,并按照4个一组的方式添加到二维数组中

实现代码:

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        //1.定义一个一维数组
        int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        //2.打乱数组中数据的顺序
        Random r = new Random();
        for (int i = 0; i < tempArr.length; i++) {
            //获取随机u偶姻
            int index = r.nextInt(tempArr.length);
            int temp = tempArr[i];
            tempArr[i] = tempArr[index];
            tempArr[index] = temp;
        }
        //3.遍历数组
        for (int i = 0; i < tempArr.length; i++) {
            System.out.print(tempArr[i] + " ");
        }
        System.out.println();
        //4.创建一个二维数组
        int[][] date = new int[4][4];

        //5.给二维数组添加数据
        /*
        //解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
        for (int i = 0; i < tempArr.length; i++) {
            date[i/4][i%4] = tempArr[i];
        }
        //遍历二维数组
        for (int i = 0; i < date.length; i++) {
            for (int j = 0; j < date[i].length; j++) {
                System.out.print(date[i][j]+ " ");
            }
            System.out.println();
        }
        */

        //解法二:遍历二维数组,给里面的每一个数组赋值
        int index = 0;
        for (int i = 0; i < date.length; i++) {
            for (int j = 0; j < date[i].length; j++) {
                date[i][j] = tempArr[index];
                index++;
            }
        }

        for (int i = 0; i < date.length; i++) {
            for (int j = 0; j < date[i].length; j++) {
                System.out.print(date[i][j]+ " ");
            }
            System.out.println();
        }
    }
}

4.2 打乱游戏图片

实现代码:

import javax.swing.*;
import java.util.Random;

public class GameJFrame extends JFrame {
    //创建一个二维数组,用来管理数据,加载图片时,会根据二维数组中的数据进行加载
    int[][] date = new int[4][4];

    //游戏相关的所有代码,在此类中
    public GameJFrame(){
        //初始化界面
        initJFrame();

        //初始化菜单
        initJMnuBar();

        //初始化数据(打乱)
        initData();

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

        //让界面显示,写在最后
        this.setVisible(true);
    }

    //初始化数据(打乱)
    private void initData() {
        //定义一个一维数组
        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;
        }

        //给二维数组添加数据
        /*
        //解法一:遍历一维数组tempArr得到每一个元素,然后把每一个元素添加到二维数组中
        for (int i = 0; i < tempArr.length; i++) {
            date[i/4][i%4] = tempArr[i];
        }
        //遍历二维数组
        for (int i = 0; i < date.length; i++) {
            for (int j = 0; j < date[i].length; j++) {
                System.out.print(date[i][j]+ " ");
            }
            System.out.println();
        }
        */

        //解法二:遍历二维数组,给里面的每一个数组赋值
        int index = 0;
        for (int i = 0; i < date.length; i++) {
            for (int j = 0; j < date[i].length; j++) {
                date[i][j] = tempArr[index];
                index++;
            }
        }
    }

    //初始化图片,添加图片时,需要按照二维数组中管理的数据添加图片
    private void initImage() {
        //外循环 -- 将内循环重复执行了4次
        for (int i = 0; i < 4; i++) {
            //内循环 -- 表示在一行添加4张图片
            for (int j = 0; j < 4; j++) {
                //获取当前加载图片的序号
                int num = date[i][j];

                //创建一个JLable的对象(管理容器)
                JLabel jLabel = new JLabel(new ImageIcon("Z:\\00-暂存区\\java-dev\\src\\day16\\image\\animal\\animal3\\"+num+".jpg"));
                //指定图片位置
                jLabel.setBounds(105 * j , 105 * i , 105, 105);
                //将管理容器添加到界面中
                //this.add(jLabel);
                this.getContentPane().add(jLabel);

            }
        }
    }

    private void initJMnuBar() {
        //...
    }

    private void initJFrame() {
        //...
    }
}

5.事件

  • 事件源:按钮、图片、窗体。。。

  • 事件:某些操作(鼠标点击、鼠标划入)

  • 绑定事件:当事件源上发生了某个事件,则执行某段代码

    • 键盘监听(KeyListener)、鼠标监听(MouseListener)、动作监听(ActionListener)

5.1 动作监听 - ActionListener

  • 本类中匿名内部类 实现

//Test3.java
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Test3 {
    public static void main(String[] args) {
        // 界面基础设置
        //....

        //创建一个按钮对象
        JButton jbt = new JButton("点我");
        //设置按钮位置、宽高
        jbt.setBounds(0,0,100,50);

        //设置按钮动作监听(包含鼠标剪辑,空格)
        //jbt.addActionListener(new MyActionListener()); //调用新建的实现类实现
        //用匿名内部类实现
        jbt.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("按钮被点击了!!!");
            }
        });


        //将按钮添加到界面
        jFrame.getContentPane().add(jbt);
        //显示界面
        jFrame.setVisible(true);
    }
}

//MyActionListener.java
public class MyActionListener implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("按钮被点击了");
    }
}

  • 本类中实现接口,重写方法写入本类

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

public class MyJFrame extends JFrame implements ActionListener {
    //第一个按钮
    JButton jtb1 = new JButton("点我");
    //第二个按钮
    JButton jtb2 = new JButton("再点我");

    public MyJFrame(){
        //设置宽高
        this.setSize(603,680);
        //设置标题
        this.setTitle("事件演示");
        //设置界面置顶
        this.setAlwaysOnTop(true);
        //设置界面剧中
        this.setLocationRelativeTo(null);
        //设置关闭模式
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //取消容器默认剧中,让XY坐标形式添加组件
        this.setLayout(null);

        jtb1.setBounds(0,0,100,50);
        jtb1.addActionListener(this);

        jtb2.setBounds(100,0,100,50);
        jtb2.addActionListener(this);

        //按钮添加到界面
        this.getContentPane().add(jtb1);
        this.getContentPane().add(jtb2);
        //显示界面
        this.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        //对当前的按钮进行判断
        Object source = e.getSource(); //获取当前被操作的按钮对象
        if (source == jtb1) {
            jtb1.setSize(200,200);
        } else if(source == jtb2) {
            Random r = new Random();
            jtb2.setLocation(r.nextInt(500),r.nextInt(500));
        }
    }
}

//Test4.java
public class Test4 {
    public static void main(String[] args) {
        new MyJFrame();
    }
}

5.2 鼠标监听 - MouseListener

  • 划入动作

  • 按下动作(单击事件)

  • 松开动作(单击事件)

  • 划出动作

方法摘要:

Modifier and Type

方法

描述

void

mouseClicked (MouseEvent e)

在组件上单击(按下并释放)鼠标按钮时调用

void

mouseEntered (MouseEvent e)

当鼠标进入组件时调用

void

mouseExited (MouseEvent e)

当鼠标退出组件时调用

void

mousePressed (MouseEvent e)

当组件上按下鼠标按钮时调用

void

mouseReleased (MouseEvent e)

在组件上释放鼠标按钮时调用

示例代码:

//MyJFrame2.java
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class MyJFrame2 extends JFrame implements MouseListener {
    JButton jtb1 = new JButton("点我");
    public MyJFrame2(){
        this.setSize(603,680); //宽高
        this.setTitle("拼图单机版 v1.0");  //标题
        this.setAlwaysOnTop(true); //置顶
        this.setLocationRelativeTo(null); //居中
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //关闭模式
        this.setLayout(null); //取消默认居中位置,让xy参数生效

        jtb1.setBounds(0,0,100,50); //按钮位置、宽高

        //给按钮设置鼠标事件
        jtb1.addMouseListener(this);

        this.getContentPane().add(jtb1); //按钮加入界面
        this.setVisible(true); //显示界面
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("单机");
    }

    @Override
    public void mousePressed(MouseEvent e) {
        System.out.println("按下不松");
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        System.out.println("松开");
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        System.out.println("划入");
    }

    @Override
    public void mouseExited(MouseEvent e) {
        System.out.println("划出");
    }
}

//Test4.java
public class Test4 {
    public static void main(String[] args) {
        new MyJFrame2();
    }
}

5.3 键盘监听 - KeyListener

Modifier and Type

方法

描述

void

KeyPressed (KeyEvent e)

按下键时调用

void

KeyReleased (KeyEvent e)

当键已被释放时调用

void

KeyTyped (KeyEvent e)

键入键时调用

示例代码:

//MyJFrame3.java
import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class MyJFrame3 extends JFrame implements KeyListener {
    public MyJFrame3() {
        this.setSize(603, 680); //宽高
        this.setTitle("拼图单机版 v1.0");  //标题
        this.setAlwaysOnTop(true); //置顶
        this.setLocationRelativeTo(null); //居中
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //关闭模式
        this.setLayout(null); //取消默认居中位置,让xy参数生效

        //给整个窗体添加键盘监听
        //调用者this:苯类对象,当前的界面对象,表示我要给整个界面添加监听
        //addKeyListener:表示要给本界面添加键盘监听
        //参数this:当事件被出发之后,会执行本类中的对应代码
        this.addKeyListener(this);

        this.setVisible(true); //显示界面
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    //细节1:如果按下按键没有松开,则会重复调用KeyPressed方法
    //细节2:每个按键有不同的编号,getKeyCode获取不同按键的编号
    @Override
    public void keyPressed(KeyEvent e) {
        System.out.println("按下不松");
        System.out.println(e.getKeyCode());
    }

    @Override
    public void keyReleased(KeyEvent e) {
        System.out.println("松开按键");
        int code = e.getKeyCode();
        System.out.println(code);
        if (code == 65) {
            System.out.println("现在按的是A");
        } else if (code == 66){
            System.out.println("现在按的是B");
        }
    }
}


//Test4.java
public class Test4 {
    public static void main(String[] args) {
        new MyJFrame3();
    }
}


3

评论区