当前位置: 首页 > news >正文

Java Swing 实战:手把手教你写一个拼图小游戏(二)

3.图片的添加与打乱

3.1图片的添加

3.1.1. 方法作用

initImage () 是拼图游戏的界面初始化核心方法

作用:
遍历 4×4 拼图网格
根据二维数组 data[i][j] 加载对应图片
使用 JLabel 展示图片并定位
将所有图片添加到游戏窗体中

3.1.2核心代码

private void initImage(){ //外循环--- for(int i= 0;i<4;i++){ for(int j = 0;j<4;j++){ //获取图片的序号 int number = data[i][j]; //创建JLabel的对象(管理容器) JLabel jLabel = new JLabel(new ImageIcon("D:\\Java项目\\Java-puzzle-game\\java-puzzle-game\\java_puzzle_game\\src\\puzzle_game\\UI\\image\\animal\\animal3\\" + number + ".jpg")); //指定图片位置 jLabel.setBounds(105*j,105*i,105,105); //把管理器添加到页面中 this.getContentPane().add(jLabel); }

3.1.3 代码详解

(1)嵌套循环:遍历 4×4 网格

//外循环:控制行数 i(垂直方向) for(int i= 0;i<4;i++){ //内循环:控制列数 j(水平方向) for(int j = 0;j<4;j++){ } }

(2)获取当前位置图片编号

int number = data[i][j];

(3)创建图片标签 JLabel

JLabel jLabel = new JLabel(new ImageIcon("图片路径" + number + ".jpg"));

详解:

  • JLabel:Swing 中用来显示文字 / 图片 / 图标的容器
  • ImageIcon:加载本地图片
  • 拼接路径 + 图片编号,动态加载对应图片
  • 这里可以提一句:路径建议使用相对路径,项目移植更方便

(4)设置图片位置与大小

jLabel.setBounds(105*j,105*i,105,105);

详解:

setBounds(x, y, width, height):绝对定位
105 * j:X 坐标,每一列向右偏移 105 像素
105 * i:Y 坐标,每一行向下偏移 105 像素
105,105:图片宽高都是 105px
最终形成整齐的 4×4 网格

(5)将图片添加到界面

this.getContentPane().add(jLabel);

详解:

this:代表当前游戏主界面
获取内容面板,把每个图片 JLabel 添加进去
循环结束后,界面就显示完整拼图

3.2 图片的打乱

3.2.1作用

initdata() 是拼图游戏的数据初始化方法,负责:
1.生成 0~15 连续数字(代表 16 张拼图块)
2.随机打乱顺序(让每次游戏界面都不一样)
3.将打乱后的一维数组 → 转为 4×4 二维数组
4.最终赋值给 data 数组,供界面显示使用

3.2.2核心代码

//初始化数据(打乱版) public 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; } // ✅ 一维数组转二维数组(就这一个循环!) for (int i = 0; i < tempArr.length; i++) { data[i / 4][i % 4] = tempArr[i]; } }

3.2.3代码详解

1.方法定义

public void initdata(){

public:公开的,其他类也能调用这个方法
void:这个方法执行完不返回任何值
initdata:方法名,意思是 初始化数据
{}:方法体,所有代码都写在大括号里

2. 创建一个 0~15 的一维数组

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

int[] tempArr:定义一个整数类型的一维数组,名字叫 tempArr(临时数组)
里面装了 0 到 15 一共 16 个数字
这是还没打乱的原始顺序

3.创建随机对象

Random r = new Random();

Random:Java 自带的随机工具类
r:给随机工具起个名字
作用:后面用来生成随机下标,实现打乱数组

4. 循环打乱数组

for (int i = 0; i < tempArr.length; i++) {

从数组第 0 个位置,一直遍历到最后一个位置
tempArr.length = 16

int index = r.nextInt(tempArr.length);

生成一个 0 ~ 15 之间的随机数
这个随机数就是要交换的数组位置

int temp = tempArr[i]; tempArr[i] = tempArr[index]; tempArr[index] = temp;

这三行是经典交换两个变量的值:
把当前位置 i 的值先存到临时变量 temp
把随机位置 index 的值放到 i
把临时变量里原来的 i 值放到 index

5. 把一维数组 → 装进 4×4 二维数组

for (int i = 0; i < tempArr.length; i++) {

遍历0~15这些数字

data[i / 4][i % 4] = tempArr[i];

4.事件

事件源:按钮 图片 窗体.....

事件:某些操作

如:鼠标单击,鼠标划入...

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

KeyListener 键盘监听

MouseListener 鼠标监听

ActionListener 动作监听

4.1键盘监听

4.1.1详细介绍

1.让类承诺实现键盘监听

public class GameJFrame extends JFrame implements KeyListener {

implements KeyListener意思是我这个界面要监听键盘,我保证实现键盘监听的方法

这叫实现监听器接口

2.必须重写这三个方法,一个都不可以少

@Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { } @Override public void keyReleased(KeyEvent e) { }

这三个方法是系统自动调用的,不用自己调用

3.给键盘绑定键盘监听

this.addKeyListener(this);

位置在 initFrame() 方法里。

给当前这个窗口(JFrame)加上键盘监听,谁来处理?我自己(this)处理。

4.在方法里写按键逻辑

1)keyPressed —— 按键按下瞬间触发

//用A键查看完整图片

@Override public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); // 获取按键编号 if (code == 65) { // 65 = A // 显示全图逻辑 } }

2)keyReleased —— 按键松开时触发

你把所有方向键移动、W 键通关都写在这里:

@Override public void keyReleased(KeyEvent e) { int code = e.getKeyCode(); if (code == 37) { // 左 // 移动逻辑 } else if (code == 38) { // 上 // 移动逻辑 } else if (code == 39) { // 右 } else if (code == 40) { // 下 } else if (code == 87) { // W 一键通关 } }

3)keyTyped
你没用,所以空着。它只监听输入字符,不监听方向键。

4.1.2三个方法的区别

keyPressed:按下去那一刻触发
你用来:A 键看全图
keyReleased:松手那一刻触发
你用来:方向键移动、W 通关
keyTyped:输入字符时触发(a~z、1~9)

4.1.3KeyEvent e 是什么?

int code = e.getKeyCode();

e:代表这次按键事件的所有信息
e.getKeyCode():获取按键编号
A = 65
W = 87
左 = 37
上 = 38
右 = 39
下 = 40

4.2鼠标监听

实现接口:MouseListener
重写 5 个方法
给组件添加监听:addMouseListener(this)

必须重写的五个方法

@Override public void mouseClicked(MouseEvent e) {} // 单击(按下+松开) @Override public void mousePressed(MouseEvent e) {} // 按下瞬间 @Override public void mouseReleased(MouseEvent e) {} // 松开瞬间 @Override public void mouseEntered(MouseEvent e) {} // 鼠标进来 @Override public void mouseExited(MouseEvent e) {} // 鼠标出去

不用全部用,常用的只有 mousePressed

e 记录了这次鼠标事件的所有信息

e.getX() → 鼠标在组件里的 X 坐标
e.getY() → 鼠标在组件里的 Y 坐标
e.getSource() → 你点的是哪个组件
e.getButton() → 点的左键 / 右键 / 滚轮

4.3动作监听

这个不常用,本项目也没有使用该方法,所以不过多介绍。

http://www.cnnetsun.cn/news/1873275.html

相关文章:

  • 【STM32】STM32F103C8T6多串口通信实战:配置与调试技巧
  • 终极SOCD清洁器:彻底解决游戏按键冲突的免费神器
  • Agent的性能瓶颈:延迟与吞吐量的优化
  • 3大创意引擎:用MediaPipe TouchDesigner插件重塑实时交互创作边界
  • Pixel Aurora Engine 环境部署避坑指南:常见错误与解决方案汇总
  • 3分钟搭建KIMI AI免费API:开发者必备的智能对话接口解决方案
  • FOC电流采样实战:从采样电阻到ADC的完整信号链设计
  • 特斯拉工厂同款|C#+YOLOv8实现AGV视觉导航全流程,零硬件改造落地
  • PR与PI双环控制单相PWM整流器 MATLAB仿真模型 simulink (1)基于比例谐振...
  • 从零开始掌握PrismLauncher:打造你的专属Minecraft游戏空间
  • AIAgent异常处理机制深度拆解(生产环境99.99%可用性背后的12层防护网)
  • AI知识库“10倍效率”承诺:如何通过3个核心维度验证与落地?
  • 基于TMS320F28035的汇川变频器源码:MD290、MD380、MD500及SVC3算法...
  • Foldseek:让蛋白质结构分析从数小时缩短到几分钟的智能工具
  • 向量记忆 vs 实体记忆 vs 元认知记忆,深度拆解SITS2026定义的AIAgent长期记忆三维模型
  • MATLAB 2024b实战:用SIMP算法5步搞定材料拓扑优化(附完整代码)
  • Autoware实车部署避坑指南(一)—— 基于Unity MapTool的矢量地图精细化绘制与验证
  • 014、Neck结构改进(二):自适应空间特征金字塔(ASPP)的引入
  • DeOldify真实案例:黑白老照片上色前后对比,效果惊艳
  • VGGT革命:Transformer如何重塑3D视觉几何的未来
  • 04月13日AI每日参考:Anthropic高危模型限流,中国每日处理140万亿Token
  • 决策树核心算法详解与应用,机器学习数据挖掘核心知识点
  • PowerShell高级用法深度解析:那些鲜为人知的技巧,带你领略它的真正实力。
  • 太极重命名软件在办公场景中的应用价值与效率提升
  • 从MCU到SFU:实时音视频架构演进与场景化选型指南
  • 保姆级教程:手把手教你将MOT17数据集转成YOLOv7能用的格式(附完整代码)
  • DoubleQoLMod:让《工业队长》从繁琐操作到流畅体验的智能管理方案
  • OrCAD元器件属性管理进阶技巧:用Description属性打造智能BOM清单
  • SourceTree离线部署实战:绕过注册限制的完整指南
  • 基于Matlab的双温模型:带载流子密度变化与德鲁德模型中电子晶格温度及飞秒激光源模拟的有限元...