06.查看完整图片,作弊码和判断胜利

华为OD机试真题 2026.11.4. 新系统 【河流水系流量评估】 华为OD机试真题 新系统【河流水系流量评估】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【河流水系流量评估】多语言题解。 阅读详情

一.查看完整图片(效果):

二.以一张图片为例查看完整图片:

1.代码:

package com.itheima.ui;
​
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
​
public class GameJFrame extends JFrame implements KeyListener {
    /* 注意一定要继承JFrame类
      因为此时要创建一个窗体,而JFrame就是一个界面,窗体,
      继承JFrame的子类也表示界面,窗体
    */
    //规定:GameJFrame这个界面表示的就是游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中
​
​
    //创建一个二维数组
    //目的:用来管理数据
    //加载图片的时候,会根据二维数组中的数据进行加载
    int[][] data=new int[4][4];
​
    //记录空白方块在二维数组中的位置-->一开始设为0
    int x=0;
    int y=0;
​
​
    public GameJFrame(){
        //初始化界面
        initJFrame();
​
        //初始化菜单
        initJMenuBar();
​
        //初始化数据(打乱)
        initData();
​
​
        //初始化图片(根据打乱之后的结果去加载图片)
        initImage();
​
​
​
        //参数为true显示界面,为false隐藏界面-->建议写最后
        this.setVisible(true);//gameJframe.show();也可以显示界面
    }
​
​
    //初始化数据(打乱)的方法
    private void initData() {
        //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++) {
            //a.随机生成一个索引
            int index=r.nextInt(tempArr.length-1);
            //b.与i索引上的元素交换位置
            int temp=tempArr[i];
            tempArr[i]=tempArr[index];
            tempArr[index]=temp;
        }
        //3.给二维数组添加数据
        /*遍历一维数组tempArr得到每一个元素,把每一个元素依次添加到二维数组当中 */
        for (int i = 0; i < tempArr.length; i++) {
            if(tempArr[i]==0){
                //为0时对坐标进行改变
                x=i/4;
                y=i%4;
            } else {
                //不为0时添加到二维数组中
                data[i/4][i%4]=tempArr[i];
            }
​
        }
    }
​
​
    //初始化图片的方法
     //初始化数据(打乱)后,在添加图片时,就需要根据二维数组中管理的数据进行添加图片
    private void initImage() {
        //需要先清空原本已经出现的所有图片
        this.getContentPane().removeAll();//之后重新加载
​
​
​
        /* 路径分为两种:
            1.绝对路径:一定是从盘符开始的,如D:\Java
            2.相对路径:相对路径是相对当前项目而言的,不是从盘符开始的.
                如aaa\\bbb,就是在当前项目下去找aaa文件夹,里面再找bbb文件夹
         */
​
​
        /* 细节:
            先加载的图片在上方,后加载的图片在下方。
            本例中背景图片在下方,应该之后加载
         */
​
        //外循环控制x,内循环控制y----嵌套循环(先看内循环,再看外循环)
        //外循环 --- 把内循环重复执行了四次
        for (int i = 0; i < 4; i++) {
            //内循环 --- 表示在一行添加4张图片
            for (int j = 0; j < 4; j++) {
                //获取当前要加载的图片的序号
                int number=data[i][j];
                //创建一个图片ImageIcon的对象,注:number是整型,要单独写出来
                ImageIcon icon=new ImageIcon("..\\PuzzleGame\\image\\animal\\animal3\\"+number+".jpg");/*这是相对路径,PuzzleGame前有个..\\(..//也行)  */
                //创建一个JLabel的对象(管理容器),本例中没有第16张图片,但也会执行new JLabel,只不过加载了个空白
                JLabel jLabel=new JLabel(icon);//放入icon,代表管理icon
                //指定图片位置(必须是在"把管理容器添加到界面中"前)
                /* 83和134是为了把内容移动到中央偏下(这个数值需要自己测试) */
                jLabel.setBounds(105*j+83,105*i+134,105,105);//第一个参数为横坐标,第二个参数为纵坐标,第三个参数为宽(像素),第四个参数为高(像素)
                //给图片添加边框(new BevelBorder(0)代表让图片凸起来,0是RAISED;new BevelBorder(1)代表让图片凹下去,1是LOWERED)
                jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));//也可以是jLabel.setBorder(new BevelBorder(1));
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);//getContentPane()用来获取里面隐藏的容器
            }
        }
​
​
        //添加背景图片
        ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
        //创建一个JLabel的对象(管理容器)
        JLabel background=new JLabel(bg);
        //设置JLabel的对象(管理容器)的位置和宽高-->数值需要自己一点一点测试
        background.setBounds(40,40,508,560);
        //把背景图片(管理容器)添加到界面中
        this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
​
​
​
        //刷新一下界面
        this.getContentPane().repaint();
​
    }
​
​
​
​
​
    //初始化菜单的方法
    private void initJMenuBar() {
        //初始化菜单
        //1.创建整个的菜单对象
        JMenuBar jMenuBar=new JMenuBar();
        //2.创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu=new JMenu("功能");
        JMenu aboutJMenu=new JMenu("关于我们");
        //3.创建选项下面的条目对象
        //功能
        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(3);//3代表一种关闭规则,可通过看源码了解
        //还可以this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //对于关闭模式,必须每个界面都设置一遍才生效。关闭模式2是关了最后一个才结束,关闭模式3是关一个就结束一个
        //本项目这几个界面不会同时出现,因此用关闭模式3即可
        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();
        //本例以A为快捷键,A对应编号为65
        if(code==65){
            //把界面中所有图片全部删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            ImageIcon icon=new ImageIcon("D:\\Java\\PuzzleGame\\image\\animal\\animal3\\all.jpg");
            JLabel all=new JLabel(icon);
            all.setBounds(83,134,420,420);//前两个为坐标,因题而异;后两个为宽高(像素),和图片一致即可
            this.getContentPane().add(all);
            //加载背景图片
            ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
            JLabel background=new JLabel(bg);
            background.setBounds(40,40,508,560);
            this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
            //刷新界面
            this.getContentPane().repaint();
        }
    }
​
    @Override
    public void keyReleased(KeyEvent e) {
        //对上,下,左,右进行判断(各对应一个编号-->不需要记,用的时候打印一下即可知道编号是几)
        //左:37;上:38;右:39;下:40
        int code=e.getKeyCode();
        if(code==37){
            System.out.println("向左移动");
            /* 逻辑:
                把空白方块右方的数字往左移动
             */
            if(y==3){
                //表示空白方块已经在最右方了,他的右方没有图片再能向左移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块右方的数字赋值给空白方块
            data[x][y]=data[x][y+1]; //x,y表示空白方块
            data[x][y+1]=0;//0代表第0张图片即空白图片
            y++;//空白方块此时向右移动了,y也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==38) {
            System.out.println("向上移动");
            /* 逻辑:
                把空白方块下方的数字往上移动
                x,y表示空白方块
                x+1,y表示空白方块下方的数字
             */
            /* 特例:如果空白块在最下方如一开始x=3,y=0
                  此时x+1就越界了
                因此要做越界判断
             */
            if(x==3){
                //表示空白方块已经在最下方了,他的下方没有图片再能向上移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块下方的数字赋值给空白方块
            data[x][y]=data[x+1][y];
            data[x+1][y]=0;//0代表第0张图片即空白图片
            x++;//空白方块此时向下移动了,x也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==39) {
            System.out.println("向右移动");
            /* 逻辑:
                把空白方块左方的数字往右移动
             */
            if(y==0){
                //表示空白方块已经在最左方了,他的左方没有图片再能向右移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块左方的数字赋值给空白方块
            data[x][y]=data[x][y-1]; //x,y表示空白方块
            data[x][y-1]=0;//0代表第0张图片即空白图片
            y--;//空白方块此时向左移动了,y也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==40) {
            System.out.println("向下移动");
            /* 逻辑:
                把空白方块上方的数字往下移动
             */
            if(x==0){
                //表示空白方块已经在最上方了,他的上方没有图片再能向下移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块上方的数字赋值给空白方块
            data[x][y]=data[x-1][y];
            data[x-1][y]=0;//0代表第0张图片即空白图片
            x--;//空白方块此时向上移动了,x也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==65) {
            //此时是松开了,加载图片即可
            initImage();
        }
    }
}
​

2.测试类:

import com.itheima.ui.GameJFrame;
import com.itheima.ui.LoginJFrame;
import com.itheima.ui.RegisterJFrame;
​
public class App {
    public static void main(String[] args) {
        //表示程序的启动入口
​
        //如果我们想要开启一个界面,就创建谁的对象就可以了
        //new LoginJFrame();//调用了登录界面的空参构造
​
        //new RegisterJFrame();
​
        new GameJFrame();
    }
}

​
​

3.运行结果:

英文输入法下按A:


三.查看完整图片代码优化:提取路径为字符串

1.代码:

package com.itheima.ui;
​
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
​
public class GameJFrame extends JFrame implements KeyListener {
    /* 注意一定要继承JFrame类
      因为此时要创建一个窗体,而JFrame就是一个界面,窗体,
      继承JFrame的子类也表示界面,窗体
    */
    //规定:GameJFrame这个界面表示的就是游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中
​
​
    //创建一个二维数组
    //目的:用来管理数据
    //加载图片的时候,会根据二维数组中的数据进行加载
    int[][] data=new int[4][4];
​
    //记录空白方块在二维数组中的位置-->一开始设为0
    int x=0;
    int y=0;
​
​
    //定义一个变量,记录当前展示图片的路径
    String path="..\\PuzzleGame\\image\\girl\\girl3\\";
​
​
    public GameJFrame(){
        //初始化界面
        initJFrame();
​
        //初始化菜单
        initJMenuBar();
​
        //初始化数据(打乱)
        initData();
​
​
        //初始化图片(根据打乱之后的结果去加载图片)
        initImage();
​
​
​
        //参数为true显示界面,为false隐藏界面-->建议写最后
        this.setVisible(true);//gameJframe.show();也可以显示界面
    }
​
​
    //初始化数据(打乱)的方法
    private void initData() {
        //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++) {
            //a.随机生成一个索引
            int index=r.nextInt(tempArr.length-1);
            //b.与i索引上的元素交换位置
            int temp=tempArr[i];
            tempArr[i]=tempArr[index];
            tempArr[index]=temp;
        }
        //3.给二维数组添加数据
        /*遍历一维数组tempArr得到每一个元素,把每一个元素依次添加到二维数组当中 */
        for (int i = 0; i < tempArr.length; i++) {
            if(tempArr[i]==0){
                //为0时对坐标进行改变
                x=i/4;
                y=i%4;
            } else {
                //不为0时添加到二维数组中
                data[i/4][i%4]=tempArr[i];
            }
​
        }
    }
​
​
    //初始化图片的方法
     //初始化数据(打乱)后,在添加图片时,就需要根据二维数组中管理的数据进行添加图片
    private void initImage() {
        //需要先清空原本已经出现的所有图片
        this.getContentPane().removeAll();//之后重新加载
​
​
​
        /* 路径分为两种:
            1.绝对路径:一定是从盘符开始的,如D:\Java
            2.相对路径:相对路径是相对当前项目而言的,不是从盘符开始的.
                如aaa\\bbb,就是在当前项目下去找aaa文件夹,里面再找bbb文件夹
         */
​
​
        /* 细节:
            先加载的图片在上方,后加载的图片在下方。
            本例中背景图片在下方,应该之后加载
         */
​
        //外循环控制x,内循环控制y----嵌套循环(先看内循环,再看外循环)
        //外循环 --- 把内循环重复执行了四次
        for (int i = 0; i < 4; i++) {
            //内循环 --- 表示在一行添加4张图片
            for (int j = 0; j < 4; j++) {
                //获取当前要加载的图片的序号
                int number=data[i][j];
                //创建一个图片ImageIcon的对象,注:number是整型,要单独写出来
                ImageIcon icon=new ImageIcon(path+number+".jpg");/*这是相对路径,PuzzleGame前有个..\\(..//也行)  */
                //创建一个JLabel的对象(管理容器),本例中没有第16张图片,但也会执行new JLabel,只不过加载了个空白
                JLabel jLabel=new JLabel(icon);//放入icon,代表管理icon
                //指定图片位置(必须是在"把管理容器添加到界面中"前)
                /* 83和134是为了把内容移动到中央偏下(这个数值需要自己测试) */
                jLabel.setBounds(105*j+83,105*i+134,105,105);//第一个参数为横坐标,第二个参数为纵坐标,第三个参数为宽(像素),第四个参数为高(像素)
                //给图片添加边框(new BevelBorder(0)代表让图片凸起来,0是RAISED;new BevelBorder(1)代表让图片凹下去,1是LOWERED)
                jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));//也可以是jLabel.setBorder(new BevelBorder(1));
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);//getContentPane()用来获取里面隐藏的容器
            }
        }
​
​
        //添加背景图片
        ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
        //创建一个JLabel的对象(管理容器)
        JLabel background=new JLabel(bg);
        //设置JLabel的对象(管理容器)的位置和宽高-->数值需要自己一点一点测试
        background.setBounds(40,40,508,560);
        //把背景图片(管理容器)添加到界面中
        this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
​
​
​
        //刷新一下界面
        this.getContentPane().repaint();
​
    }
​
​
​
​
​
    //初始化菜单的方法
    private void initJMenuBar() {
        //初始化菜单
        //1.创建整个的菜单对象
        JMenuBar jMenuBar=new JMenuBar();
        //2.创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu=new JMenu("功能");
        JMenu aboutJMenu=new JMenu("关于我们");
        //3.创建选项下面的条目对象
        //功能
        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(3);//3代表一种关闭规则,可通过看源码了解
        //还可以this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //对于关闭模式,必须每个界面都设置一遍才生效。关闭模式2是关了最后一个才结束,关闭模式3是关一个就结束一个
        //本项目这几个界面不会同时出现,因此用关闭模式3即可
        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();
        //本例以A为快捷键,A对应编号为65
        if(code==65){
            //把界面中所有图片全部删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            ImageIcon icon=new ImageIcon(path+"all.jpg");
            JLabel all=new JLabel(icon);
            all.setBounds(83,134,420,420);//前两个为坐标,因题而异;后两个为宽高(像素),和图片一致即可
            this.getContentPane().add(all);
            //加载背景图片
            ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
            JLabel background=new JLabel(bg);
            background.setBounds(40,40,508,560);
            this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
            //刷新界面
            this.getContentPane().repaint();
        }
    }
​
    @Override
    public void keyReleased(KeyEvent e) {
        //对上,下,左,右进行判断(各对应一个编号-->不需要记,用的时候打印一下即可知道编号是几)
        //左:37;上:38;右:39;下:40
        int code=e.getKeyCode();
        if(code==37){
            System.out.println("向左移动");
            /* 逻辑:
                把空白方块右方的数字往左移动
             */
            if(y==3){
                //表示空白方块已经在最右方了,他的右方没有图片再能向左移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块右方的数字赋值给空白方块
            data[x][y]=data[x][y+1]; //x,y表示空白方块
            data[x][y+1]=0;//0代表第0张图片即空白图片
            y++;//空白方块此时向右移动了,y也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==38) {
            System.out.println("向上移动");
            /* 逻辑:
                把空白方块下方的数字往上移动
                x,y表示空白方块
                x+1,y表示空白方块下方的数字
             */
            /* 特例:如果空白块在最下方如一开始x=3,y=0
                  此时x+1就越界了
                因此要做越界判断
             */
            if(x==3){
                //表示空白方块已经在最下方了,他的下方没有图片再能向上移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块下方的数字赋值给空白方块
            data[x][y]=data[x+1][y];
            data[x+1][y]=0;//0代表第0张图片即空白图片
            x++;//空白方块此时向下移动了,x也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==39) {
            System.out.println("向右移动");
            /* 逻辑:
                把空白方块左方的数字往右移动
             */
            if(y==0){
                //表示空白方块已经在最左方了,他的左方没有图片再能向右移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块左方的数字赋值给空白方块
            data[x][y]=data[x][y-1]; //x,y表示空白方块
            data[x][y-1]=0;//0代表第0张图片即空白图片
            y--;//空白方块此时向左移动了,y也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==40) {
            System.out.println("向下移动");
            /* 逻辑:
                把空白方块上方的数字往下移动
             */
            if(x==0){
                //表示空白方块已经在最上方了,他的上方没有图片再能向下移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块上方的数字赋值给空白方块
            data[x][y]=data[x-1][y];
            data[x-1][y]=0;//0代表第0张图片即空白图片
            x--;//空白方块此时向上移动了,x也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==65) {
            //此时是松开了,加载图片即可
            initImage();
        }
    }
}

​

2.测试类:

import com.itheima.ui.GameJFrame;
import com.itheima.ui.LoginJFrame;
import com.itheima.ui.RegisterJFrame;
​
public class App {
    public static void main(String[] args) {
        //表示程序的启动入口
​
        //如果我们想要开启一个界面,就创建谁的对象就可以了
        //new LoginJFrame();//调用了登录界面的空参构造
​
        //new RegisterJFrame();
​
        new GameJFrame();
    }
}

​
​

3.运行结果:

英文输入法下按A:


四.作弊码:要用到键盘监听

五.作弊码代码实现:

1.代码:

package com.itheima.ui;
​
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
​
public class GameJFrame extends JFrame implements KeyListener {
    /* 注意一定要继承JFrame类
      因为此时要创建一个窗体,而JFrame就是一个界面,窗体,
      继承JFrame的子类也表示界面,窗体
    */
    //规定:GameJFrame这个界面表示的就是游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中
​
​
    //创建一个二维数组
    //目的:用来管理数据
    //加载图片的时候,会根据二维数组中的数据进行加载
    int[][] data=new int[4][4];
​
    //记录空白方块在二维数组中的位置-->一开始设为0
    int x=0;
    int y=0;
​
​
    //定义一个变量,记录当前展示图片的路径
    String path="..\\PuzzleGame\\image\\animal\\animal3\\";
​
​
    public GameJFrame(){
        //初始化界面
        initJFrame();
​
        //初始化菜单
        initJMenuBar();
​
        //初始化数据(打乱)
        initData();
​
​
        //初始化图片(根据打乱之后的结果去加载图片)
        initImage();
​
​
​
        //参数为true显示界面,为false隐藏界面-->建议写最后
        this.setVisible(true);//gameJframe.show();也可以显示界面
    }
​
​
    //初始化数据(打乱)的方法
    private void initData() {
        //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++) {
            //a.随机生成一个索引
            int index=r.nextInt(tempArr.length-1);
            //b.与i索引上的元素交换位置
            int temp=tempArr[i];
            tempArr[i]=tempArr[index];
            tempArr[index]=temp;
        }
        //3.给二维数组添加数据
        /*遍历一维数组tempArr得到每一个元素,把每一个元素依次添加到二维数组当中 */
        for (int i = 0; i < tempArr.length; i++) {
            if(tempArr[i]==0){
                //为0时对坐标进行改变
                x=i/4;
                y=i%4;
            } else {
                //不为0时添加到二维数组中
                data[i/4][i%4]=tempArr[i];
            }
​
        }
    }
​
​
    //初始化图片的方法
     //初始化数据(打乱)后,在添加图片时,就需要根据二维数组中管理的数据进行添加图片
    private void initImage() {
        //需要先清空原本已经出现的所有图片
        this.getContentPane().removeAll();//之后重新加载
​
​
​
        /* 路径分为两种:
            1.绝对路径:一定是从盘符开始的,如D:\Java
            2.相对路径:相对路径是相对当前项目而言的,不是从盘符开始的.
                如aaa\\bbb,就是在当前项目下去找aaa文件夹,里面再找bbb文件夹
         */
​
​
        /* 细节:
            先加载的图片在上方,后加载的图片在下方。
            本例中背景图片在下方,应该之后加载
         */
​
        //外循环控制x,内循环控制y----嵌套循环(先看内循环,再看外循环)
        //外循环 --- 把内循环重复执行了四次
        for (int i = 0; i < 4; i++) {
            //内循环 --- 表示在一行添加4张图片
            for (int j = 0; j < 4; j++) {
                //获取当前要加载的图片的序号
                int number=data[i][j];
                //创建一个图片ImageIcon的对象,注:number是整型,要单独写出来
                ImageIcon icon=new ImageIcon(path+number+".jpg");/*这是相对路径,PuzzleGame前有个..\\(..//也行)  */
                //创建一个JLabel的对象(管理容器),本例中没有第16张图片,但也会执行new JLabel,只不过加载了个空白
                JLabel jLabel=new JLabel(icon);//放入icon,代表管理icon
                //指定图片位置(必须是在"把管理容器添加到界面中"前)
                /* 83和134是为了把内容移动到中央偏下(这个数值需要自己测试) */
                jLabel.setBounds(105*j+83,105*i+134,105,105);//第一个参数为横坐标,第二个参数为纵坐标,第三个参数为宽(像素),第四个参数为高(像素)
                //给图片添加边框(new BevelBorder(0)代表让图片凸起来,0是RAISED;new BevelBorder(1)代表让图片凹下去,1是LOWERED)
                jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));//也可以是jLabel.setBorder(new BevelBorder(1));
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);//getContentPane()用来获取里面隐藏的容器
            }
        }
​
​
        //添加背景图片
        ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
        //创建一个JLabel的对象(管理容器)
        JLabel background=new JLabel(bg);
        //设置JLabel的对象(管理容器)的位置和宽高-->数值需要自己一点一点测试
        background.setBounds(40,40,508,560);
        //把背景图片(管理容器)添加到界面中
        this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
​
​
​
        //刷新一下界面
        this.getContentPane().repaint();
​
    }
​
​
​
​
​
    //初始化菜单的方法
    private void initJMenuBar() {
        //初始化菜单
        //1.创建整个的菜单对象
        JMenuBar jMenuBar=new JMenuBar();
        //2.创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu=new JMenu("功能");
        JMenu aboutJMenu=new JMenu("关于我们");
        //3.创建选项下面的条目对象
        //功能
        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(3);//3代表一种关闭规则,可通过看源码了解
        //还可以this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //对于关闭模式,必须每个界面都设置一遍才生效。关闭模式2是关了最后一个才结束,关闭模式3是关一个就结束一个
        //本项目这几个界面不会同时出现,因此用关闭模式3即可
        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();
        //本例以A为快捷键,A对应编号为65
        if(code==65){
            //把界面中所有图片全部删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            ImageIcon icon=new ImageIcon(path+"all.jpg");
            JLabel all=new JLabel(icon);
            all.setBounds(83,134,420,420);//前两个为坐标,因题而异;后两个为宽高(像素),和图片一致即可
            this.getContentPane().add(all);
            //加载背景图片
            ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
            JLabel background=new JLabel(bg);
            background.setBounds(40,40,508,560);
            this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
            //刷新界面
            this.getContentPane().repaint();
        }
    }
​
    @Override
    public void keyReleased(KeyEvent e) {
        //对上,下,左,右进行判断(各对应一个编号-->不需要记,用的时候打印一下即可知道编号是几)
        //左:37;上:38;右:39;下:40
        int code=e.getKeyCode();
        if(code==37){
            System.out.println("向左移动");
            /* 逻辑:
                把空白方块右方的数字往左移动
             */
            if(y==3){
                //表示空白方块已经在最右方了,他的右方没有图片再能向左移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块右方的数字赋值给空白方块
            data[x][y]=data[x][y+1]; //x,y表示空白方块
            data[x][y+1]=0;//0代表第0张图片即空白图片
            y++;//空白方块此时向右移动了,y也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==38) {
            System.out.println("向上移动");
            /* 逻辑:
                把空白方块下方的数字往上移动
                x,y表示空白方块
                x+1,y表示空白方块下方的数字
             */
            /* 特例:如果空白块在最下方如一开始x=3,y=0
                  此时x+1就越界了
                因此要做越界判断
             */
            if(x==3){
                //表示空白方块已经在最下方了,他的下方没有图片再能向上移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块下方的数字赋值给空白方块
            data[x][y]=data[x+1][y];
            data[x+1][y]=0;//0代表第0张图片即空白图片
            x++;//空白方块此时向下移动了,x也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==39) {
            System.out.println("向右移动");
            /* 逻辑:
                把空白方块左方的数字往右移动
             */
            if(y==0){
                //表示空白方块已经在最左方了,他的左方没有图片再能向右移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块左方的数字赋值给空白方块
            data[x][y]=data[x][y-1]; //x,y表示空白方块
            data[x][y-1]=0;//0代表第0张图片即空白图片
            y--;//空白方块此时向左移动了,y也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==40) {
            System.out.println("向下移动");
            /* 逻辑:
                把空白方块上方的数字往下移动
             */
            if(x==0){
                //表示空白方块已经在最上方了,他的上方没有图片再能向下移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块上方的数字赋值给空白方块
            data[x][y]=data[x-1][y];
            data[x-1][y]=0;//0代表第0张图片即空白图片
            x--;//空白方块此时向上移动了,x也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==65) {
            //此时是松开了,加载图片即可
            initImage();
​
        } else if (code==87) { //本例以W为作弊码,W对应编码为87
            //直接把二维数组里的数据变为最终效果即可
            data=new int[][]{  //直接添加元素,1到15和0是图片编号-->元素内容就是最终效果
                    {1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,0},
            };
            //重新加载图片
            initImage();
        }
    }
}

​

2.测试类:

import com.itheima.ui.GameJFrame;
import com.itheima.ui.LoginJFrame;
import com.itheima.ui.RegisterJFrame;
​
public class App {
    public static void main(String[] args) {
        //表示程序的启动入口
​
        //如果我们想要开启一个界面,就创建谁的对象就可以了
        //new LoginJFrame();//调用了登录界面的空参构造
​
        //new RegisterJFrame();
​
        new GameJFrame();
    }
}

​
​

3.运行结果:

英文输入法下按下W松开后:


六.判断胜利:

七.判断胜利代码实现(注意:胜利后不能再执行移动拼图的代码了)

1.代码:

package com.itheima.ui;
​
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
​
public class GameJFrame extends JFrame implements KeyListener {
    /* 注意一定要继承JFrame类
      因为此时要创建一个窗体,而JFrame就是一个界面,窗体,
      继承JFrame的子类也表示界面,窗体
    */
    //规定:GameJFrame这个界面表示的就是游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中
​
​
    //创建一个二维数组
    //目的:用来管理数据
    //加载图片的时候,会根据二维数组中的数据进行加载
    int[][] data=new int[4][4];
​
    //记录空白方块在二维数组中的位置-->一开始设为0
    int x=0;
    int y=0;
​
​
    //定义一个变量,记录当前展示图片的路径
    String path="..\\PuzzleGame\\image\\animal\\animal3\\";
​
​
    //定义一个二维数组,存储正确的数据
    int[][] win={
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12},
        {13,14,15,0},
    };
​
​
    public GameJFrame(){
        //初始化界面
        initJFrame();
​
        //初始化菜单
        initJMenuBar();
​
        //初始化数据(打乱)
        initData();
​
​
        //初始化图片(根据打乱之后的结果去加载图片)
        initImage();
​
​
​
        //参数为true显示界面,为false隐藏界面-->建议写最后
        this.setVisible(true);//gameJframe.show();也可以显示界面
    }
​
​
    //初始化数据(打乱)的方法
    private void initData() {
        //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++) {
            //a.随机生成一个索引
            int index=r.nextInt(tempArr.length-1);
            //b.与i索引上的元素交换位置
            int temp=tempArr[i];
            tempArr[i]=tempArr[index];
            tempArr[index]=temp;
        }
        //3.给二维数组添加数据
        /*遍历一维数组tempArr得到每一个元素,把每一个元素依次添加到二维数组当中 */
        for (int i = 0; i < tempArr.length; i++) {
            if(tempArr[i]==0){
                //为0时对坐标进行改变
                x=i/4;
                y=i%4;
            } else {
                //不为0时添加到二维数组中
                data[i/4][i%4]=tempArr[i];
            }
​
        }
    }
​
​
    //初始化图片的方法
     //初始化数据(打乱)后,在添加图片时,就需要根据二维数组中管理的数据进行添加图片
    private void initImage() {
        //需要先清空原本已经出现的所有图片
        this.getContentPane().removeAll();//之后重新加载
​
​
        if(victory()){
            //走if说明方法victory返回true,即胜利
            //需要显示胜利的图标
            JLabel winJLabel=new JLabel(new ImageIcon("D:\\Java\\PuzzleGame\\image\\win.png"));
            //设置图标
            winJLabel.setBounds(203,283,197,73);
            this.getContentPane().add(winJLabel);
        }
​
​
​
        /* 路径分为两种:
            1.绝对路径:一定是从盘符开始的,如D:\Java
            2.相对路径:相对路径是相对当前项目而言的,不是从盘符开始的.
                如aaa\\bbb,就是在当前项目下去找aaa文件夹,里面再找bbb文件夹
         */
​
​
        /* 细节:
            先加载的图片在上方,后加载的图片在下方。
            本例中背景图片在下方,应该之后加载
         */
​
        //外循环控制x,内循环控制y----嵌套循环(先看内循环,再看外循环)
        //外循环 --- 把内循环重复执行了四次
        for (int i = 0; i < 4; i++) {
            //内循环 --- 表示在一行添加4张图片
            for (int j = 0; j < 4; j++) {
                //获取当前要加载的图片的序号
                int number=data[i][j];
                //创建一个图片ImageIcon的对象,注:number是整型,要单独写出来
                ImageIcon icon=new ImageIcon(path+number+".jpg");/*这是相对路径,PuzzleGame前有个..\\(..//也行)  */
                //创建一个JLabel的对象(管理容器),本例中没有第16张图片,但也会执行new JLabel,只不过加载了个空白
                JLabel jLabel=new JLabel(icon);//放入icon,代表管理icon
                //指定图片位置(必须是在"把管理容器添加到界面中"前)
                /* 83和134是为了把内容移动到中央偏下(这个数值需要自己测试) */
                jLabel.setBounds(105*j+83,105*i+134,105,105);//第一个参数为横坐标,第二个参数为纵坐标,第三个参数为宽(像素),第四个参数为高(像素)
                //给图片添加边框(new BevelBorder(0)代表让图片凸起来,0是RAISED;new BevelBorder(1)代表让图片凹下去,1是LOWERED)
                jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));//也可以是jLabel.setBorder(new BevelBorder(1));
                //把管理容器添加到界面中
                this.getContentPane().add(jLabel);//getContentPane()用来获取里面隐藏的容器
            }
        }
​
​
        //添加背景图片
        ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
        //创建一个JLabel的对象(管理容器)
        JLabel background=new JLabel(bg);
        //设置JLabel的对象(管理容器)的位置和宽高-->数值需要自己一点一点测试
        background.setBounds(40,40,508,560);
        //把背景图片(管理容器)添加到界面中
        this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
​
​
​
        //刷新一下界面
        this.getContentPane().repaint();
​
    }
​
​
​
​
​
    //初始化菜单的方法
    private void initJMenuBar() {
        //初始化菜单
        //1.创建整个的菜单对象
        JMenuBar jMenuBar=new JMenuBar();
        //2.创建菜单上面的两个选项的对象(功能  关于我们)
        JMenu functionJMenu=new JMenu("功能");
        JMenu aboutJMenu=new JMenu("关于我们");
        //3.创建选项下面的条目对象
        //功能
        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(3);//3代表一种关闭规则,可通过看源码了解
        //还可以this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        //对于关闭模式,必须每个界面都设置一遍才生效。关闭模式2是关了最后一个才结束,关闭模式3是关一个就结束一个
        //本项目这几个界面不会同时出现,因此用关闭模式3即可
        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();
        //本例以A为快捷键,A对应编号为65
        if(code==65){
            //把界面中所有图片全部删除
            this.getContentPane().removeAll();
            //加载第一张完整的图片
            ImageIcon icon=new ImageIcon(path+"all.jpg");
            JLabel all=new JLabel(icon);
            all.setBounds(83,134,420,420);//前两个为坐标,因题而异;后两个为宽高(像素),和图片一致即可
            this.getContentPane().add(all);
            //加载背景图片
            ImageIcon bg=new ImageIcon("..\\PuzzleGame\\image\\background.png");/*这是相对路径,PuzzleGame前有个..\\  */
            JLabel background=new JLabel(bg);
            background.setBounds(40,40,508,560);
            this.getContentPane().add(background);//getContentPane()用来获取里面隐藏的容器
            //刷新界面
            this.getContentPane().repaint();
        }
    }
​
    @Override
    public void keyReleased(KeyEvent e) {
        //需要先判断游戏是否胜利,如果胜利,此方法需要直接结束,不能再执行下面的移动代码了
        if(victory()){
            //走if说明方法victory返回true,即胜利-->结束方法
            return;
        }
​
​
        //对上,下,左,右进行判断(各对应一个编号-->不需要记,用的时候打印一下即可知道编号是几)
        //左:37;上:38;右:39;下:40
        int code=e.getKeyCode();
        if(code==37){
            System.out.println("向左移动");
            /* 逻辑:
                把空白方块右方的数字往左移动
             */
            if(y==3){
                //表示空白方块已经在最右方了,他的右方没有图片再能向左移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块右方的数字赋值给空白方块
            data[x][y]=data[x][y+1]; //x,y表示空白方块
            data[x][y+1]=0;//0代表第0张图片即空白图片
            y++;//空白方块此时向右移动了,y也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==38) {
            System.out.println("向上移动");
            /* 逻辑:
                把空白方块下方的数字往上移动
                x,y表示空白方块
                x+1,y表示空白方块下方的数字
             */
            /* 特例:如果空白块在最下方如一开始x=3,y=0
                  此时x+1就越界了
                因此要做越界判断
             */
            if(x==3){
                //表示空白方块已经在最下方了,他的下方没有图片再能向上移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块下方的数字赋值给空白方块
            data[x][y]=data[x+1][y];
            data[x+1][y]=0;//0代表第0张图片即空白图片
            x++;//空白方块此时向下移动了,x也就自增
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==39) {
            System.out.println("向右移动");
            /* 逻辑:
                把空白方块左方的数字往右移动
             */
            if(y==0){
                //表示空白方块已经在最左方了,他的左方没有图片再能向右移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块左方的数字赋值给空白方块
            data[x][y]=data[x][y-1]; //x,y表示空白方块
            data[x][y-1]=0;//0代表第0张图片即空白图片
            y--;//空白方块此时向左移动了,y也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==40) {
            System.out.println("向下移动");
            /* 逻辑:
                把空白方块上方的数字往下移动
             */
            if(x==0){
                //表示空白方块已经在最上方了,他的上方没有图片再能向下移动了-->直接结束方法即可
                return;
            }
​
            //把空白方块上方的数字赋值给空白方块
            data[x][y]=data[x-1][y];
            data[x-1][y]=0;//0代表第0张图片即空白图片
            x--;//空白方块此时向上移动了,x也就自减
            //调用方法按照最新的数字加载图片
            initImage();
​
        } else if (code==65) {
            //此时是松开了,加载图片即可
            initImage();
​
        } else if (code==87) { //本例以W为作弊码,W对应编码为87
            //直接把二维数组里的数据变为最终效果即可
            data=new int[][]{  //直接添加元素,1到15和0是图片编号-->元素内容就是最终效果
                    {1,2,3,4},
                    {5,6,7,8},
                    {9,10,11,12},
                    {13,14,15,0},
            };
            //重新加载图片
            initImage();
        }
    }
​
​
​
    //定义一个方法,用来判断胜利
    /* 判断data数组中的数据是否跟win数组中相同
          如果全部相同,返回true,否则返回false
     */
    public boolean victory(){
        for (int i = 0; i < data.length; i++) {
            //i:依次表示二维数组data里面的索引
            //data[i]:依次表示每一个一维数组
            for (int j = 0; j < data[i].length; j++) {
                if (data[i][j]!=win[i][j]) {
                    //只要有一个数据不一样就没赢,返回false
                    return false;
                }
            }
        }
        //此时还没有结束方法,循环结束表示数组遍历比较完毕,全部一样返回true
        return true;
    }
}

​

2.测试类:

import com.itheima.ui.GameJFrame;
import com.itheima.ui.LoginJFrame;
import com.itheima.ui.RegisterJFrame;
​
public class App {
    public static void main(String[] args) {
        //表示程序的启动入口
​
        //如果我们想要开启一个界面,就创建谁的对象就可以了
        //new LoginJFrame();//调用了登录界面的空参构造
​
        //new RegisterJFrame();
​
        new GameJFrame();
    }
}

​
​

3.运行结果:


英飞凌AURIX™ Development Studio(ADS)工程调试与烧录实战指南 本文详细介绍了英飞凌AURIX™ Development Studio(ADS)的工程调试与烧录实战指南。从调试环境搭建、硬件连接到断点设置、变量监控等核心调试技巧,帮助开发者快速掌握ADS安装使用教程,提升多核处理器开发效率。 阅读详情

相关推荐

基于Ollama本地大模型的Python自动化翻译工具开发实践

本文详细介绍了如何利用Ollama本地大模型和Python开发自动化批量翻译工具。通过部署本地开源模型、设计精准提示词、处理长文本分割及多种文档格式,构建了一个兼顾隐私安全、可控性与成本效益的翻译流水线,有效解决了文档批量翻译的痛点。

yhn45678901的博客 560

java面向对象---(拼图小游戏)

如果把所有的代码都写在main方法中,那么main方法里面的代码,就包含游戏主界面的代码,登录界面的代码,注册界面的代码,会变得非常臃肿后期维护也是一件非常难的事情,所以我们需要用继承改进,改进之后,代码就可以分类了。JLabel jLabel = new JLabel(new ImageIcon("F:\\JavaSE最新版\\day17-面向对象综合练习(下)\\代码\\" + num + ".jpg"));我们在添加图片的时候,要把添加图片的操作重复15次,才能把所有图片都添加到界面当中。

m0_62388400的博客 1033

day14--多态 接口 抽象类 内部类 Day16-项目-拼图小游戏 组件 断点调试&快捷键

阶段项目-01-项目介绍和界面搭建 阶段项目-02-界面设置和菜单搭建 阶段项目-03-添加图片 阶段项目-04-打乱图片 阶段项目-05-事件 阶段项目-06-美化界面 阶段项目-07-移动图片 阶段项目-08-查看完整图片、作弊码和判断胜利 阶段项目-09-计步和菜单业务实现 阶段项目-10-阶段项目课后练习思路分析 阶段项目-11-游戏打包成exe安装包.........

我亦无他,唯手熟尔 713

川崎机器人 AS语言基础运动指令表

    功能简介 动作方式 参考坐标系 位置特性 X,Y,Z 角度特性 O,A,T 指令格式(距离单位毫米,时间单位秒,角度单位度 示例1 示例2 运 动 指 令 JMOVE 以关节移动到目标点 关节移动方式 基础坐标系 不受控 伪随机动作 JMOVE 目标点 JMOVE #yd JMOVE put1 LMOVE 以直线移动到目标点 直线移动方式

喜欢自学并分享经验的技术宅 9348

HDFView安装及使用教程

简介:直接用记事本打开hdf5文件的话,是一团乱码。HDFView是用来查看hdf5文件的软件,可以免费使用,好多人都有闪退的情况,这是因为没有添加环境变量。

qq_43722079的博客 7万+

Spring AI + GPT-5.5 + Ollama 配置教程:Base URL、超时与流式调用

由于不同 Spring AI、Spring Boot 小版本之间仍可能存在差异,创建项目时应检查 Spring Initializr、Spring AI BOM 和官方兼容矩阵,不要直接复制旧教程中的 Starter 名称和版本号。多人项目最好隔离不同客户端,并在脱敏前提下记录最终 URL、状态码、请求耗时、请求 ID 和模型 ID。Spring AI 接入模型 API,至少要同时确认 Starter、Base URL、请求路径、API Key、模型 ID、连接超时、读取超时和流式客户端这 8 项。

2601_95893075的博客 225

WS2812呼吸灯效果实战:用STM32的PWM+DMA实现流畅渐变(附完整代码)

本文详细介绍了如何使用STM32的PWM+DMA技术实现WS2812呼吸灯效果,提供完整的代码示例和调试技巧。通过PWM波形编码和DMA传输机制,解决了传统IO模拟控制方式的高CPU占用问题,实现了流畅的LED渐变效果,适用于各种嵌入式开发场景。

weixin_30566063的博客 452

【JVM】对象内存布局

HotSpot JVM 中,Java 对象内存布局由对象头(12字节,含Mark Word与压缩Klass Pointer)、实例数据及对齐填充构成,总大小为8字节倍数。对象头支持锁状态动态复用,指针压缩使引用仅4字节,但堆超32GB时失效。实例字段按类型优先级重排序以减少间隙,最小对象大小为16字节。通过JOL工具可精准验证布局,理解锁机制、GC、伪共享等底层行为。

2301_79732484的博客 149

语言大模型之Tokenization的深入理解

Tokenization(分词)是自然语言处理(NLP)中一个非常重要的步骤,它的目标是将文本转换为模型可以理解的格式。对于像GPT、BERT等大型预训练模型来说,tokenization决定了文本如何转化为数字表示,从而影响模型在不同任务中的表现。接下来我会深入介绍tokenization的过程、不同的tokenization方法,以及它与模型微调(fine-tuning)之间的关系。

JustinMars的博客 341

uniapp [全端兼容] - 实现接入集成高德地图搜索地址及选择位置功能,搜索框检索选择地点并返回经纬度及详细省市区县街道地址,用户搜索历史及清空历史记录,选择地址自动获取周边位置列表/地图移动选点

uni-app,高德地图,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,Uniapp高德地图,在地图上选择或搜索指定地点,打开地图选择位置,关联地址搜索,输入地址返回附近地址列表,uniApp高德地图地址搜索,搜索框历史记录,关键字搜索,周边查询,搜索位置,uniapp对接高德实现搜索出现地址以及保存搜索记录,集成高德地图,实现精准位置选点功能,获取当前定位城市,如何实现搜索功能,获取省份城市区街道详细地址经纬度,移动选点标记位置,在地图上进行选择位置选点、搜索

🏆 前端领域优质创作者 1万+

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 330

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring Boot 数据源与 MyBatis(-Plus) 自定义配置详解

本文详解 Spring Boot 中单数据源环境下 HikariCP 与 MyBatis-Plus 的自定义配置。通过手动声明 SqlSessionFactory,实现下划线转驼峰、日志输出、一级缓存策略等精细化控制。结合 HikariCP 核心参数调优(如最大连接数、连接生命周期),确保高性能与稳定性。适用于仅需访问单一数据库的场景,避免多数据源复杂性,兼顾性能与可维护性。

BADAO_LIUMANG_QIZHI的博客 195

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 117

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

LeetCode Hot 100 二叉树专题(二)3 题(Java)

本篇文章共 3 题:543. 二叉树的直径、102. 二叉树的层序遍历、108. 将有序数组转换为二叉搜索树。 每道题都统一按「① 题目分析 & 解题思路 → ② 常见解法(附代码)及讲解 → ③ 知识点总结」的顺序组织;代码使用 Java 编写,节点定义沿用 LeetCode 默认的 TreeNode。

2401_88612756的博客 365

Decorator

TaskDecorator 是异步场景下"跨线程传递上下文"的标准方案,主要用于传递 MDC、用户信息、数据源路由等上下文数据,核心价值是让异步任务的日志链路不中断、业务上下文不丢失。TaskDecorator 是 Spring 提供的一个钩子接口,用于在异步任务执行前对 Runnable 进行包装,常用于跨线程传递上下文。如果你在项目中遇到具体的异步上下文传递问题,可以把代码贴出来,我帮你给出最合适的 Decorator 方案 👍。✅ 核心能力:在线程切换时,把"父线程的上下文"搬到"子线程"

wlwork66的博客 104

JDK 下载安装:装完 Java 提示「不是内部或外部命令」?环境变量没配

JDK 是写 Java 程序必须装的东西。它包含运行 Java 的虚拟机(JRE)和编译 Java 的编译器(javac)——装了它,能跑、.java文件能编译成可执行程序。免费,学习和小规模生产都不花钱。

科小怪的博客 626

数据库乐观锁深度解析:MySQL、PostgreSQL 实战 + Spring Boot 集成指南

Oracle 提供了ORA_ROWSCN伪列(System Change Number),记录最后修改行的 SCN,类似 PostgreSQL 的xmin。实践中通常仍使用 version 字段方案,逻辑与 MySQL 完全相同。-- Oracle:通过 ORA_ROWSCN 实现乐观锁-- 更新时比对 SCN// 自定义注解// AOP 切面@Aspect@Component@Slf4jtry {

yjc_1111的专栏 399

C++ 多态详解:作用、原理与实战用法

多态是C++面向对象的核心特性,通过虚函数实现运行期动态绑定,使同一接口在不同对象上表现出不同行为。其核心作用包括统一接口、提升可扩展性、降低耦合、支持运行时分派与批量处理。实现依赖虚函数表(vtable)和虚指针(vptr),需注意虚析构函数、对象切片等陷阱。相比编译期多态(模板),运行期多态灵活性高但有调用开销。合理结合两者,可兼顾代码的灵活性与性能,是构建可扩展、低耦合系统的关键。

2402_85743155的博客 377

java框架大全

java框架大全

qq_39326137的博客 183

Java 多态 学习笔记

多态是面向对象编程的重要特性,指同一操作作用于不同对象时产生不同行为。其核心在于“父类引用指向子类对象”,结合方法重写实现运行时动态绑定。多态使代码更灵活、可扩展,如用Person p = new Student();统一处理各类人员注册,无需修改调用逻辑。但多态无法直接调用子类特有方法,需通过instanceof判断并强制转换。编译时看左边(类型),运行时看右边(实际对象),实现解耦与维护便利。

AA_AA114514的博客 353

SecureRandom做随机源,这个Java随机字符串工具类有3个方法

本文分享一款JDK17环境下的Java随机字符串工具类,内置3个开箱即用的方法,全部采用SecureRandom加密安全随机源,不存在弱随机、可预测、取模偏差等问题。工具类支持默认62字符集随机串、纯数字随机串、自定义字符集随机串三种生成模式,支持Unicode码点级别的字符集处理,兼容Emoji等增补字符,边界处理严格,异常信息明确,适合验证码、邀请码、盐值、随机口令、短链码等场景,源码可直接复制使用。

Java后端 | AI智能体应用实战派 | 电脑技能行家 295

Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

【代码】Java实现批量线段相交检测(跨积判定+扫描线优化与踩坑复盘)

m0_64476639的博客 319

ubuntu安装hadoop系统

本文详细介绍了基于VMware克隆虚拟机搭建三节点Hadoop分布式集群的全过程:使用同一Ubuntu镜像克隆出master、worker1、worker2三台虚拟机,依次配置主机名、固定IP(如192.168.82.10/11/12)、SSH服务及免密登录,确保节点间网络互通。随后安装Java,下载配置Hadoop并分发至各节点,最终初始化启动集群,验证其存储与计算功能,实现高效的大数据环境部署。

qq_43592674的博客 325

Agent 状态栏在上下文中的具体位置

Agent状态栏以user角色消息形式追加至上下文末尾,而非修改system消息,避免破坏KVCache。此举仅为API技术实现,内容由框架自动生成,非真实用户输入,通过<agent_status>标签标识,确保模型获取最新状态且不影响缓存。该设计遵循“动态信息追加、静态信息固定”原则,实现高效、低延迟的状态传递。

lj1109053360的专栏 72

Spring事务和事务传播机制

3. 可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同⼀事务多次查询的结果⼀致, 但是其他事务新插⼊的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.p1事务可以认为是⽗事务, 嵌套事务是⼦事务. ⽗事务出现异常, ⼦事务也会回滚, ⼦事务出现异常, 如果不进⾏处理, 也会导致⽗事务回滚.

txxzjmzlh的博客 203
上一篇: 05.移动图片
下一篇: 07.计步和菜单业务实现
巧克力拌面
博客等级 码龄3年 1153粉丝 282原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值