【进阶篇-Day4:使用JAVA编写石头迷阵游戏】

目录
- 1、绘制界面
- 2、打乱石头方块
- 3、移动业务
- 4、游戏判定胜利
- 5、统计步数
- 6、重新游戏
- 7、完整代码:
1、绘制界面





上述思路是:使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。


代码如下:
package com.itheima.stonepuzzle;
import javax.swing.*;public class MainFrame extends JFrame {//data使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。int[][] data = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};/*** 因为初始化窗体 和 绘制游戏界面,是在进入游戏就要执行的,* 因此只需要在new对象时执行即可,而new对象时构造方法一定会执行,* 所以在构造方法里调用即可*/public MainFrame(){//初始化窗体initFrame();//绘制游戏界面paintView();//设置窗体可见setVisible(true);}/*** 此方法用于窗体初始化*/public void initFrame(){
// JFrame jf = new JFrame(); --因为此类继承了JFrame,因此下面的方法可以直接调用//设置窗体大小setSize(514, 595);//设置窗体关闭模式:关闭窗口时,结束程序setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);//设置窗体标题setTitle("石头迷阵单机版V1.0");//设置窗体永在最上层setAlwaysOnTop(true);//设置窗体居中setLocationRelativeTo(null);//设置取消默认布局setLayout(null);}/*** 此方法用于绘制游戏的界面*/public void paintView(){for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {JLabel jl = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\" + data[i][j] + ".jpg"));//设置图片对象大小jl.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);//将图片对象塞进窗体getContentPane().add(jl);}}JLabel background = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\background.jpg"));//设置图片对象大小background.setBounds(26, 30, 450, 484);//将图片对象塞进窗体super.getContentPane().add(background);}
}
运行代码,绘制界面的结果如下:
2、打乱石头方块

代码:
/*** 初始化数据(随机打乱石头)*/
public void initData(){Random r = new Random();//1、遍历二维数组,获取每一个元素for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {//2、随机获取 (x坐, y坐标),找到其中一个数int x = r.nextInt(4);//x坐标int y = r.nextInt(4);//y坐标//3、将当前遍历到的元素,和随机获取到的元素做交换int temp = data[i][j];data[i][j] = data[x][y];data[x][y] = temp;}}
}
3、移动业务

/*** 按下键盘时出发事件* @param e*/@Overridepublic void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();move(keyCode);}/*** 此方法用于处理移动业务* @param keyCode*/private static void move(int keyCode) {if (keyCode == 37){System.out.println("左移动业务...");} else if (keyCode == 38) {System.out.println("上移动业务...");} else if (keyCode == 39) {System.out.println("右移动业务...");} else if (keyCode == 40) {System.out.println("下移动业务...");}}

移动石头块,实际上只需要交换二维数组中的两个数即可,然后再刷新就实现了移动业务。
做法:
//寻找0号元素的位置
lo:
for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {if (data[i][j] == 0) {row = i;col = j;break lo;}}
}
下面看下上、下、左、右移动:
注意:
/*** 此方法用于处理移动业务** @param keyCode*/
private void move(int keyCode) {int temp = data[row][col];//0号元素if (keyCode == 37 && col < 3) {System.out.println("左移动业务...");//左移动时,空白块和右边的数做交换data[row][col] = data[row][col + 1];data[row][col + 1] = temp;//记录0号元素的列坐标也要随之改变col++;} else if (keyCode == 38 && row < 3) {System.out.println("上移动业务...");//上移动时,空白块和下边的数做交换data[row][col] = data[row + 1][col];data[row + 1][col] = temp;//记录0号元素的列坐标也要随之改变row++;} else if (keyCode == 39 && col > 0) {System.out.println("右移动业务...");//右移动时,空白块和左边的数做交换data[row][col] = data[row][col - 1];data[row][col - 1] = temp;//记录0号元素的列坐标也要随之改变col--;} else if (keyCode == 40 && row > 0) {System.out.println("下移动业务...");//下移动时,空白块和上边的数做交换data[row][col] = data[row - 1][col];data[row - 1][col] = temp;//记录0号元素的列坐标也要随之改变row--;}else if (keyCode == 90){//z键//触发作弊器data = new int[][]{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};}System.out.println(row + "," + col);
}
4、游戏判定胜利

/*** 判断游戏是否胜利* @return*/
public boolean victory(){for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {if(data[i][j] != win[i][j]){return false;}}}//运行到这里,表明游戏胜利了return true;}

5、统计步数

6、重新游戏

7、完整代码:
package com.itheima.stonepuzzle;public class Test {public static void main(String[] args) {//启动器new MainFrame();}
}
package com.itheima.stonepuzzle;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;public class MainFrame extends JFrame implements KeyListener {//data使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。int[][] data = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};//胜利的结果int[][] win = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};int row; //0号元素的行坐标int col; //0号元素的列坐标int count = 0;//记录操作的次数/*** 因为初始化窗体 和 绘制游戏界面,是在进入游戏就要执行的,* 因此只需要在new对象时执行即可,而new对象时构造方法一定会执行,* 所以在构造方法里调用即可*/public MainFrame() {//键盘监听://窗体对象.addKeyListener(KeyListener实现类对象)//this:当前对象,两个身份//1)窗体对象//2)KeyListener实现类对象this.addKeyListener(this);//初始化窗体initFrame();//初始化数据(随机打乱石头)initData();//绘制游戏界面paintView();//设置窗体可见setVisible(true);}/*** 此方法用于窗体初始化*/public void initFrame() {
// JFrame jf = new JFrame(); --因为此类继承了JFrame,因此下面的方法可以直接调用//设置窗体大小setSize(514, 595);//设置窗体关闭模式:关闭窗口时,结束程序setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);//设置窗体标题setTitle("石头迷阵单机版V1.0");//设置窗体永在最上层setAlwaysOnTop(true);//设置窗体居中setLocationRelativeTo(null);//设置取消默认布局setLayout(null);}/*** 初始化数据(随机打乱石头)*/public void initData() {Random r = new Random();//1、遍历二维数组,获取每一个元素for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {//2、随机获取 (x坐, y坐标),找到其中一个数int x = r.nextInt(4);//x坐标int y = r.nextInt(4);//y坐标//3、将当前遍历到的元素,和随机获取到的元素做交换int temp = data[i][j];data[i][j] = data[x][y];data[x][y] = temp;}}//寻找0号元素的位置lo:for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {if (data[i][j] == 0) {row = i;col = j;break lo;}}}}/*** 此方法用于绘制游戏的界面*/public void paintView() {//每次绘制之前,都清空之前绘制的界面super.getContentPane().removeAll();//加载胜利图片资源,添加到窗体中if (victory()){JLabel victoryJl = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\victory.jpg"));victoryJl.setBounds(124, 230, 266, 100);getContentPane().add(victoryJl);}//加载重新开始按钮if (count > 0){JButton jb = new JButton("重新开始");jb.setBounds(350, 10, 100, 20);jb.setFocusable(false);//取消焦点jb.addActionListener(new AbstractAction() {@Overridepublic void actionPerformed(ActionEvent e) {//统计步数归0count = 0;//重新初始化数据initData();//重新绘制游戏界面paintView();}});getContentPane().add(jb);}//加载记录步数组件JLabel stepJl = new JLabel("步数:" + count);stepJl.setBounds(50, 10, 100, 20);getContentPane().add(stepJl);for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {JLabel jl = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\" + data[i][j] + ".jpg"));//设置图片对象大小jl.setBounds(50 + 100 * j, 90 + 100 * i, 100, 100);//将图片对象塞进窗体getContentPane().add(jl);}}//加载背景图JLabel background = new JLabel(new ImageIcon("C:\\Users\\MSZ\\Desktop\\java_test\\dev\\image\\background.jpg"));//设置图片对象大小background.setBounds(26, 30, 450, 484);//将图片对象塞进窗体super.getContentPane().add(background);//刷新super.getContentPane().repaint();}/*** 按下键盘时出发事件** @param e*/@Overridepublic void keyPressed(KeyEvent e) {int keyCode = e.getKeyCode();move(keyCode);//判断是否胜利victory();//每次移动之后,都重新绘制游戏界面paintView();}/*** 此方法用于处理移动业务** @param keyCode*/private void move(int keyCode) {//如果游戏胜利了,则不允许操作if (victory()){return;}int temp = data[row][col];//0号元素if (keyCode == 37 && col < 3) {
// System.out.println("左移动业务...");//左移动时,空白块和右边的数做交换data[row][col] = data[row][col + 1];data[row][col + 1] = temp;//记录0号元素的列坐标也要随之改变col++;count++;} else if (keyCode == 38 && row < 3) {
// System.out.println("上移动业务...");//上移动时,空白块和下边的数做交换data[row][col] = data[row + 1][col];data[row + 1][col] = temp;//记录0号元素的列坐标也要随之改变row++;count++;} else if (keyCode == 39 && col > 0) {
// System.out.println("右移动业务...");//右移动时,空白块和左边的数做交换data[row][col] = data[row][col - 1];data[row][col - 1] = temp;//记录0号元素的列坐标也要随之改变col--;count++;} else if (keyCode == 40 && row > 0) {
// System.out.println("下移动业务...");//下移动时,空白块和上边的数做交换data[row][col] = data[row - 1][col];data[row - 1][col] = temp;//记录0号元素的列坐标也要随之改变row--;count++;}else if (keyCode == 90){//z键//触发作弊器data = new int[][]{{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12},{13, 14, 15, 0}};count++;}
// System.out.println(row + "," + col);}/*** 判断游戏是否胜利* @return*/public boolean victory(){for (int i = 0; i < data.length; i++) {for (int j = 0; j < data[i].length; j++) {if(data[i][j] != win[i][j]){return false;}}}//运行到这里,表明游戏胜利了return true;}//-------------------------------------@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyReleased(KeyEvent e) {}//-------------------------------------
}
界面图片已放在资源里,可下载。
相关文章:
【进阶篇-Day4:使用JAVA编写石头迷阵游戏】
目录 1、绘制界面2、打乱石头方块3、移动业务4、游戏判定胜利5、统计步数6、重新游戏7、完整代码: 1、绘制界面 上述思路是:使用一个二维数组存放图片的编号,然后在后持遍历即可获取对应的图片。 代码如下: package com.itheima.s…...
探索 LLamaWorker:基于LLamaSharp的.NET本地大模型服务
LLamaWorker 是一个基于 LLamaSharp 项目开发的 HTTP API 服务器。它提供与 OpenAI 兼容的 API,使得开发者可以轻松地将大型语言模型(LLM)集成到自己的应用程序中。 1. 背景 在人工智能领域,大型语言模型(LLM…...
Qt开发 | Qt控件 | QTabWidget基本用法 | QListWidget应用详解 | QScrollArea应用详解
文章目录 一、QTabWidget基本用法二、QListWidget应用详解1.列表模式1.1 基本操作1.2 添加自定义item1.3 如何添加右键菜单1.4 QListWidget如何删除item 2.图标模式 三、QScrollArea应用详解 一、QTabWidget基本用法 QTabWidget 是 Qt 框架中的一个类,它提供了一个选…...
2023年 AI APT可持续攻击的调查研究报告
总览 随着网络技术的不断发展,网络安全威胁也日益严峻。高级持续性威胁(APT)攻击以其目标明确、手段多样、隐蔽性强等特点,成为网络安全领域的重要挑战。本文分析2023年当前 APT 攻击的主要特点、活跃组织、攻击趋势以及漏洞利用…...
Leetcode 102.目标和
给定一个正整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 ‘’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 : 例如,nums [2, 1] ,可以在 2 之前添加 ‘’ ,在 1 之前添加 ‘-’ &…...
LLM AI工具和Delphi名称的起源
LLM AI工具和Delphi名称的起源 使用ChatGPT,直接或通过微软工具,以及其他基于llm的引擎。我很欣赏他们提供好的总结和比较的能力,并且还编写了一些样板代码。与此同时,当你问一些重要的问题时,你会得到一些令人惊讶的好…...
打破数据分析壁垒:SPSS复习必备(十一)
一、方差分析 方差分析的应用条件如下: (1)独立,各组数据相互独立,互不相关; (2)正态:即各组数据符合正态分布; (3)方差齐性&…...
【十六】【QT开发应用】Menu菜单,contextMenuEvent,setContextMenuPolicy,addAction
在 Qt 框架中,QMenu 类用于创建和管理菜单。菜单是用户界面的一部分,可以包含多个选项或动作,用户可以选择这些选项来执行特定的功能。菜单通常显示在菜单栏、上下文菜单(右键菜单)或工具栏中。 基本用法 创建菜单对象…...
华为DCN技术:M-LAG
M-LAG(Multichassis Link Aggregation Group)即跨设备链路聚合组,是一种实现跨设备链路聚合的机制。M-LAG主要应用于普通以太网络、VXLAN和IP网络的双归接入,可以起到负载分担或备份保护的作用。相较于另一种常见的可靠性接入技术…...
k8s持久化之emptyDir使用
目录 概述实践代码 概述 理解emptyDir使用,是后续k8s持久化进阶,高阶使用的基础。 实践 代码 详细说明在代码中 # 缓存数据,可以让多个容器共享数据 # 删除 Pod 时,emptyDir 数据同步消失 # 定义 initContainer -> 下载数据…...
Java露营基地预约小程序预约下单系统源码
轻松开启户外探险之旅 🌟 露营热潮来袭,你准备好了吗? 随着人们对户外生活的热爱日益增加,露营已成为许多人周末和假期的首选活动。但你是否曾因找不到合适的露营基地而烦恼?或是因为繁琐的预约流程而错失心仪的营地…...
七天速通javaSE:第四天 java方法
文章目录 前言一、什么是方法?二、方法的定义与调用1. 方法的定义2. 方法的调用3. 练习:定义比大小方法并调用 三、方法的重载四、递归五、可变参数拓展:命令行传递参数 前言 本章将学习java方法。 一、什么是方法? java方法是用…...
jupyter notebook的markdown语法不起作用
在这个界面编辑,发现markdown你编辑的是什么就是什么,不起作用,然而点一下: 右上角“Notebook转发”,就会单独跳出一个jupyter notebook的界面,此时就会奏效:...
Redis 学习笔记(2)
目录 1 Redis的持久化1.1 RDB持久化方案1.2 AOF持久化方案 2 Redis架构2.1 主从复制架构2.2 哨兵集群设计2.3 哨兵集群设计 3 Redis事务机制4 Redis过期策略与内存淘汰机制4.1 过期策略4.2 内存淘汰机制 5 Redis高频面试题4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩 1 Redis的持久化…...
快慢指针:删除有序数组中的重复项
题目链接:. - 力扣(LeetCode) 思路好想,代码实现不好想 class Solution {public int removeDuplicates(int[] nums) {int fast 1,slow 1;while(fast < nums.length){if(nums[fast] ! nums[fast-1]){nums[slow] nums[fast]…...
用户登录错误次数太多锁定账号
当用户登录验证码错误次数太多时,需要限制用户在10分钟之内不能再次登录。 限制方案: 1.通过Redis ZSet key可以设置为用户名,value可以设置为UUID,score设置为当前时间戳 每次用户登录时,通过 rangeByScore 查询对…...
tedsign vue3 web-端框架中封装一个验证码组件 以及对应node 接口逻辑说明
一个这样的组件 我直接上代码了 <template><t-loading size"small" :loading"loading" show-overlay><div class"container" click"refresh"><div v-if"svg" class"svg" v-html"svg&…...
探索Scala并发编程之巅:高效并行处理的艺术
标题:探索Scala并发编程之巅:高效并行处理的艺术 引言 在现代软件开发中,随着多核处理器的普及,编写能够充分利用硬件能力的并发程序变得至关重要。Scala,这门结合了面向对象和函数式编程特性的语言,提供…...
AudioLM: 音频生成的革命性模型
AudioLM: 音频生成的革命性模型 AudioLM是一种革命性的音频生成模型,它结合了深度学习和自然语言处理的先进技术,能够生成高质量、逼真的音频内容。本文将探讨AudioLM的基本原理、工作机制、应用场景以及对音频生成领域的影响和未来发展方向。 一、Aud…...
C++ Vector的模拟实现
vector的介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
Linux --进程控制
本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...









