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

拼图小游戏开发日记 | Day3(已完结)

1. 成员变量扩展

// 统计移动步数
int step = 0;
// 胜利时的目标数组(每个方块的“正确位置”)
int[][] win = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 0}};
// 图片资源主路径(后续可切换动物、风景等主题)
String path = "image/animal/animal1/";
// 空白方块在二维数组中的坐标(x行y列)
int x = 0, y = 0;
// 记录当前拼图方块的位置(动态变化)
int[][] arr = new int[4][4];
// 菜单栏的菜单项(用于绑定点击事件)
JMenuItem rePlayItem = new JMenuItem("重置游戏");
JMenuItem reLogo = new JMenuItem("重新登录");
JMenuItem closeGame = new JMenuItem("关闭游戏");
JMenuItem gongZhongHao = new JMenuItem("公众号");
(1)胜利判定:win1()

判断当前拼图数组arr是否与 “目标数组win” 完全一致

private boolean win1() {for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (arr[i][j] != win[i][j]) {return false; // 有一个位置不一致,未胜利}}}return true; // 所有位置一致,判定胜利
}
(2)随机打乱图片:randomPicture(int[][] arr)

用 “洗牌算法” 随机交换数组元素,实现拼图打乱

private void randomPicture(int[][] arr) {int[] temp = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};Random r = new Random();// 第一步:数组元素“洗牌”(随机交换)for (int i = 0; i < temp.length; i++) {int index = r.nextInt(arr.length * arr[0].length); // 生成随机下标int t = temp[i];temp[i] = temp[index];temp[index] = t;}// 第二步:将一维数组转二维,并记录空白方块位置for (int i = 0; i < temp.length; i++) {if (temp[i] == 0) { // 找到空白方块(值为0)x = i / 4; // 计算所在行y = i % 4; // 计算所在列}arr[i / 4][i % 4] = temp[i];}
}
(3)初始化 / 刷新拼图:initPicture(int[][] arr)

根据数组arr的状态,刷新界面上的拼图图

private void initPicture(int[][] arr) {this.getContentPane().removeAll(); // 清空原有组件// 显示步数JLabel stepCount = new JLabel("步数:" + step);stepCount.setBounds(20, 20, 60, 20);this.getContentPane().add(stepCount);// 胜利判定:若拼图完成,显示胜利图片if (win1()) {ImageIcon winPicture = new ImageIcon("image/win.png");JLabel label = new JLabel(winPicture);label.setBounds(100, 100, winPicture.getIconWidth(), winPicture.getIconHeight());this.getContentPane().add(label);}// 绘制拼图方块(根据arr数组)for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {ImageIcon icon = new ImageIcon(path + arr[i][j] + ".jpg");JLabel label = new JLabel(icon);label.setBounds(105 * j + 100, 105 * i + 100, icon.getIconWidth(), icon.getIconHeight());this.getContentPane().add(label);}}// 绘制背景图ImageIcon background = new ImageIcon("image/background.png");JLabel label2 = new JLabel(background);label2.setBounds(56, 8, background.getIconWidth(), background.getIconHeight());this.getContentPane().add(label2);this.getContentPane().repaint(); // 刷新界面
}
(4)键盘事件监听:控制方块移动

通过 方向键(←↑→↓)控制空白方块移动,A键显示全图,W键直接通关

@Override
public void keyPressed(KeyEvent e) {int code = e.getKeyCode();// 按A键:显示完整图片(方便参考拼图)if (code == 65) { this.getContentPane().removeAll();ImageIcon all = new ImageIcon(path + "all.jpg");JLabel label = new JLabel(all);label.setBounds(100, 102, all.getIconWidth(), all.getIconHeight());this.add(label);ImageIcon background = new ImageIcon("image/background.png");JLabel label2 = new JLabel(background);label2.setBounds(56, 8, background.getIconWidth(), background.getIconHeight());this.add(label2);this.getContentPane().repaint();}
}@Override
public void keyReleased(KeyEvent e) {if (win1()) return; // 胜利后,键盘操作无效int code = e.getKeyCode();// ←键:空白方块左移(交换右侧方块)if (code == 37) {if (y == 0) return; // 最左侧,无法左移arr[x][y] = arr[x][y - 1];arr[x][y - 1] = 0;y--;step++; // 步数+1initPicture(arr); // 刷新拼图} // ↑键:空白方块上移(交换下方方块)else if (code == 38) {if (x == 0) return; // 最上方,无法上移arr[x][y] = arr[x - 1][y];arr[x - 1][y] = 0;x--;step++;initPicture(arr);} // →键:空白方块右移(交换左侧方块)else if (code == 39) {if (y == 3) return; // 最右侧,无法右移arr[x][y] = arr[x][y + 1];arr[x][y + 1] = 0;y++;step++;initPicture(arr);} // ↓键:空白方块下移(交换上方方块)else if (code == 40) {if (x == 3) return; // 最下方,无法下移arr[x][y] = arr[x + 1][y];arr[x + 1][y] = 0;x++;step++;initPicture(arr);} // W键:直接胜利(测试用,后续可移除)else if (code == 87) {arr = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 0}};initPicture(arr);}
}
5)菜单栏点击事件:actionPerformed

为 “重置游戏”“重新登录”“关闭游戏”“公众号” 添加具体逻辑

@Override
public void actionPerformed(ActionEvent e) {Object source = e.getSource();// 重置游戏:步数清零 + 重新打乱图片if (source == rePlayItem) {step = 0;randomPicture(arr);initPicture(arr);} // 重新登录:隐藏当前窗口,打开启动页else if (source == reLogo) {this.setVisible(false);new LogoJframe();} // 关闭游戏:退出程序else if (source == closeGame) {System.exit(0);} // 公众号:弹出包含公众号图片的对话框else if (source == gongZhongHao) {JDialog jd = new JDialog();ImageIcon gongZhongPicture = new ImageIcon("image/小韦(小).png");JLabel label = new JLabel(gongZhongPicture);label.setBounds(0, 0, 1800, 1800);jd.getContentPane().add(label);jd.setAlwaysOnTop(true);jd.setSize(600, 600);jd.setLocationRelativeTo(null);jd.setModal(true); // 模态窗口(阻止父窗口交互)jd.setVisible(true);}
}

http://www.dtcms.com/a/442256.html

相关文章:

  • Go 1.25 新特性:正式支持 Git 仓库子目录作为 Go 模块
  • 鸿蒙NEXT Remote Communication Kit:打破设备壁垒,构筑无缝协同体验
  • 那些网站建设的好杭州建站程序
  • 做团购网站企业网站设计调查问卷
  • 基于 RoBERTa + 多策略优化的中文商品名细粒度分类
  • 做翻译兼职的网站是哪个特色的网站建设
  • 山西建设银行招聘网站crm系统的销售管理功能包括
  • 如何在C#中配置ONNX Runtime以确保准确性和目标框位置的正确性?
  • PiscCode使用YOLO识别超大分辨率高清视图实践
  • 力扣2200. 找出数组中的所有 K 近邻下标
  • 文化馆网站建设情况在微信上做彩票网站有哪些
  • 网站301怎么做企业法治建设工作计划
  • list模拟实现(简单版)【C++】
  • 烟台网站建设哪家好呢维护一个网站需要多少钱
  • 什么网站做视频最赚钱wordpress无法使用ajax
  • 对接MCP服务之sse/streamable-http模式
  • springMVC中/*与/**匹配的区别
  • 如何快速学习一个网络协议?
  • 从安装到上手实战——Docker 基础命令全解析
  • 虚拟机怎么做网站昆明seo技术培训
  • 免费dede企业网站模板wordpress qa
  • autodl 安装modelscope OCR 模型 dots_ocr 笔记心得
  • Linux中文件目录结构介绍以及对目录的操作
  • 大庆建设工程交易中心网站唐山建设信息网站
  • 第8章:扩展边界:技术之外的视野(2)
  • Java面向对象练习:Person类继承与排序
  • Day04_刷题niuke20251005
  • 四个字网站 域名网站开发项目进度表
  • 理解C++20的革命特性——协程支持1
  • 【八股】操作系统