黑马程序员Java零基础视频教程(2022最新Java)B站视频学习笔记-Day15-阶段项目(拼图小游戏)(上篇)

news/2024/12/22 22:08:18/

1、主界面分析

 1、练习:创建主界面1

到IDEA中创建一个宽603像素,高680像素的游戏主界面

到IDEA中创建一个宽488像素,高430像素的登录界面

到IDEA中创建一个宽488像素,高500像素的注册界面

解题思路分析:因为程序主要分为三块(即游戏界面、登陆界面、注册界面),每一个界面内又有很多操作,需要写很多代码,因此要把三个界面分开写在三个class当中,而不是只写在一个main方法中,这样也有利于以后的代码找错和维护。在以后的开发过程中,main方法通常作为程序的启动入口,里面是不会有逻辑代码的。

创建main方法的操作如下:

在IDEA中右击src--> new --> javaclass --> 新建类名为App --> 在App类中书写main方法

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;
//注意这个继承的操作!!!
public class GameJFrame extends JFrame {//JFrame 界面,窗体//它的子类也是界面,窗体//规定:GameJFrame这个界面表示的就是游戏的主界面(所以需要继承JFrame)//以后跟游戏相关的所有逻辑都写在这个类中public GameJFrame(){//JavaBean类描述界面的属性(宽 高)  行为(是否显示窗口)this.setSize(603,680);    //设置窗口的属性(宽 高)this.setVisible(true);    //设置窗口是否显示 true为显示 false为隐藏}
}
package YouXiUI;/**登录界面的业务逻辑* 获取用户输入的用户名* 获取用户输入的密码* 生成一个验证码* 获取用户输入放入验证码* 比较用户名、密码、验证码等等*/
import javax.swing.*;public class LoginJFrame extends JFrame {//LoginJFrame表示登录界面//以后所有跟登录有关的代码,都写在这里//构造方法的作用,就是给对象设置默认属性值//设置默认属性值的时候,把设置的代码写在构造方法里面public LoginJFrame(){//在创建登陆界面的时候,同时给这些界面设置一些信息//比如:宽、高、直接展示出来this.setSize(488,430);  //this代表当前对象(当前的LoginJFrame对象)this.setVisible(true);}
}
package YouXiUI;/**注册界面业务逻辑* 获取用户输入的用户名* 获取用户输入的密码(两次)* 比较两次的密码是否一致* 判断当前用户是否已经注册等等*/
import javax.swing.*;public class RegisterJFrame extends JFrame {//跟注册界面有关的代码,都写在这个界面中//利用构造方法设置初始化默认值public RegisterJFrame(){this.setSize(488,500);this.setVisible(true);}
}
import YouXiUI.GameJFrame;
import YouXiUI.LoginJFrame;
import YouXiUI.RegisterJFrame;public class App {//开发过程中,main方法为程序的启动入口public static void main(String[] args) {//如果我们想要开启一个界面,就创建谁的对象就可以了new LoginJFrame();  //  创建登录界面对象new RegisterJFrame();   //创建注册界面new GameJFrame();   //创建游戏的主界面}
}

2、练习:创建主界面2和菜单制作

2.1、创建主界面2

用继承改写上述界面,并思考用继承改写的好处

 创建主界面2代码如下:

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;
//注意这个继承的操作!!!
public class GameJFrame extends JFrame {//JFrame 界面,窗体//它的子类也是界面,窗体//规定:GameJFrame这个界面表示的就是游戏的主界面(所以需要继承JFrame)//以后跟游戏相关的所有逻辑都写在这个类中public GameJFrame(){//JavaBean类描述界面的属性(宽 高)  行为(是否显示窗口)this.setSize(603,680);    //设置窗口的属性(宽 高)this.setTitle("拼图单机版 v1.0");    //设置界面标题/**设置界面置顶(即设置页面始终悬浮在其他页面之上)* 为true时该窗口会有“任何情况下都会悬浮在其他窗口之上”的效果* 为false时,点击其他界面时,该窗口就会被其他界面遮挡住*/this.setAlwaysOnTop(true);this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置/**设置关闭模式(设置程序结束运行的方式)* DO_NOTHING_ON_CLOSE = 0   什么都不做的默认窗口关闭工作(任何操作都关不了窗口)* HIDE_ON_CLOSE = 1  windows默认窗口关闭操作,窗口会被关闭,但程序不会结束运行* DISPOSE_ON_CLOSE = 2  开启多个界面之后,只有关闭所有开启的窗口,程序才会结束(用2时,需要所有的界面都做这样的设置,才会有效果)* EXIT_ON_CLOSE = 3    只要关闭一个界面,所有界面都会关闭,且程序会结束运行* 可以用 this.setDefaultCloseOperation(1);   //1可以替换成0、2、3* 也可以利用WindowConstants去调用对应的常量值,如下:(DISPOSE_ON_CLOSE可以替换成其他对应的英文)* this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);*/this.setDefaultCloseOperation(3);this.setVisible(true);    //设置窗口是否显示 true为显示 false为隐藏,建议写在最后}
}
package YouXiUI;/**登录界面的业务逻辑* 获取用户输入的用户名* 获取用户输入的密码* 生成一个验证码* 获取用户输入放入验证码* 比较用户名、密码、验证码等等*/
import javax.swing.*;public class LoginJFrame extends JFrame {//LoginJFrame表示登录界面//以后所有跟登录有关的代码,都写在这里//构造方法的作用,就是给对象设置默认属性值//设置默认属性值的时候,把设置的代码写在构造方法里面public LoginJFrame(){//在创建登陆界面的时候,同时给这些界面设置一些信息//比如:宽、高、直接展示出来this.setSize(488,430);  //this代表当前对象(当前的LoginJFrame对象)this.setTitle("拼图 登录");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
package YouXiUI;/**注册界面业务逻辑* 获取用户输入的用户名* 获取用户输入的密码(两次)* 比较两次的密码是否一致* 判断当前用户是否已经注册等等*/
import javax.swing.*;public class RegisterJFrame extends JFrame {//跟注册界面有关的代码,都写在这个界面中//利用构造方法设置初始化默认值public RegisterJFrame(){this.setSize(488,500);this.setTitle("拼图 注册");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
import YouXiUI.GameJFrame;
import YouXiUI.LoginJFrame;
import YouXiUI.RegisterJFrame;public class App {//开发过程中,main方法为程序的启动入口public static void main(String[] args) {//如果我们想要开启一个界面,就创建谁的对象就可以了new LoginJFrame();  //  创建登录界面对象new RegisterJFrame();   //创建注册界面new GameJFrame();   //创建游戏的主界面}
}

2.2、菜单制作

分析过程图1

 分析过程图2

 分析过程图3

 实现代码如下:

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;public class GameJFrame extends JFrame {//构造方法public GameJFrame(){//Ctrl + Alt + M  提取代码形成方法initJFrame();   //调用initJFrame()方法初始化界面initJMenuBar();     //调用initJMenuBar()方法,初始化菜单this.setVisible(true);    //让界面显示出来,建议写在最后}//创建初始化菜单的方法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("公众号");//4、将每一个选项下面的条目对象添加到选项当中functionJMenu.add(replayItem);functionJMenu.add(reLoginItem);functionJMenu.add(closeItem);aboutJMenu.add(accountItem);//5、将菜单里面的两个选项添加到菜单当中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);   //设置程序关闭的方式}
}
package YouXiUI;/**登录界面的业务逻辑* 获取用户输入的用户名* 获取用户输入的密码* 生成一个验证码* 获取用户输入放入验证码* 比较用户名、密码、验证码等等*/
import javax.swing.*;public class LoginJFrame extends JFrame {public LoginJFrame(){this.setSize(488,430);  //this代表当前对象(当前的LoginJFrame对象)this.setTitle("拼图 登录");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
package YouXiUI;/**注册界面业务逻辑* 获取用户输入的用户名* 获取用户输入的密码(两次)* 比较两次的密码是否一致* 判断当前用户是否已经注册等等*/
import javax.swing.*;public class RegisterJFrame extends JFrame {public RegisterJFrame(){this.setSize(488,500);this.setTitle("拼图 注册");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
import YouXiUI.GameJFrame;
import YouXiUI.LoginJFrame;
import YouXiUI.RegisterJFrame;public class App {//开发过程中,main方法为程序的启动入口public static void main(String[] args) {//如果我们想要开启一个界面,就创建谁的对象就可以了//new LoginJFrame();  //  创建登录界面对象//new RegisterJFrame();   //创建注册界面new GameJFrame();   //创建游戏的主界面}
}

3、添加图片

说明1:

 说明2:

找到下载好的image文件夹,然后ctrl+C,然后打开IDEA,在IDEA中选中模块名(切记:一定要选中模块名,不然会出错),然后ctrl+V,点击OK就可以了。

说明3:

坐标以左上角为原点,向右为X轴正方方向,向下为Y轴正方向,图片的所在位置实际上是指图片左上角的点所在的坐标位置,例如下面图片,如果图片的位置设置为(0,0),则图片就会在左上角显示。

说明4:

窗口一共分为三个部分,如下图所示,JFrame只是一个大的架子,最下面的第三部分才是用来装载所有组件的(组件可以为图片、文字、按钮、进度条),第三部分是一个隐藏的容器,把需要显示的图片添加到隐藏容器中,如果对添加的图片没有特殊要求,图片就会默认添加到中间位置。利用setLayout(null)可以取消该默认方式,达到自由设置位置的效果。如果要取消默认。在创建窗口的时候就要书写setLayout(null)方法。取消隐藏容器中的居中默认方式后,里面添加的组件才会按照XY轴的形式来进行添加。

 添加两个哈士奇拼图小图片代码如下:

(注意:实现此功能的时候,只需要修改主界面的代码,其他代码不需要修改)

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;public class GameJFrame extends JFrame {//构造方法public GameJFrame(){//Ctrl + Alt + M  提取代码形成方法initJFrame();   //调用initJFrame()方法初始化界面initJMenuBar();     //调用initJMenuBar()方法,初始化菜单//初始化图片//直接书写,会报错,然后利用alt+enter,然后选择Create menthod等等的那个选项,点击回车//就会自动生成下面的private void initImage() { }方法initImage();this.setVisible(true);    //让界面显示出来,建议写在最后}//初始化图片private void initImage() {//先创建一个图片ImageIcon的对象/**ImageIcon icon = new ImageIcon("图片路径");   说明* 括号里面的参数是需要添加的图片的地址* 找到IDEA左边的项目下的image,* image -> animal -> animal3 -> 3.jpg -> 右击3.jpg -> Copy -> Copy Path -> 选中Absolute Path并点击即可完成路径复制* 将复制的路径粘贴到括号内即可*/ImageIcon icon = new ImageIcon("D:\\IDEA2020\\IDEAprocejts\\PinTuYouXi\\image\\animal\\animal3\\1.jpg");//然后创建一个JLabel的对象(即管理容器)(我们是需要把图片放到管理容器里面的)JLabel jLabel1 = new JLabel(icon);//指定图片位置  参数分别为(x坐标,y坐标,图片宽度,图片高度)  单位都是像素jLabel1.setBounds(0,0,105,105);//最后把管理容器添加到界面当中//this.add(jLabel);   //图片默认位置为居中正中心//利用getContentPane()获取到隐藏容器,然后用add()把图片添加到JFrame的隐藏容器中this.getContentPane().add(jLabel1);//添加第二张图片ImageIcon icon2 = new ImageIcon("D:\\IDEA2020\\IDEAprocejts\\PinTuYouXi\\image\\animal\\animal3\\2.jpg");JLabel jLabel2 = new JLabel(icon2);jLabel2.setBounds(105,0,105,105);this.getContentPane().add(jLabel2);}//创建初始化菜单的方法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("公众号");//4、将每一个选项下面的条目对象添加到选项当中functionJMenu.add(replayItem);functionJMenu.add(reLoginItem);functionJMenu.add(closeItem);aboutJMenu.add(accountItem);//5、将菜单里面的两个选项添加到菜单当中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);   //设置程序关闭的方式this.setLayout(null);   //取消图片默认的居中防放置,只有取消了才会按照XY轴的形式添加组件}
}

package YouXiUI;/**登录界面的业务逻辑* 获取用户输入的用户名* 获取用户输入的密码* 生成一个验证码* 获取用户输入放入验证码* 比较用户名、密码、验证码等等*/
import javax.swing.*;public class LoginJFrame extends JFrame {public LoginJFrame(){this.setSize(488,430);  //this代表当前对象(当前的LoginJFrame对象)this.setTitle("拼图 登录");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
package YouXiUI;/**注册界面业务逻辑* 获取用户输入的用户名* 获取用户输入的密码(两次)* 比较两次的密码是否一致* 判断当前用户是否已经注册等等*/
import javax.swing.*;public class RegisterJFrame extends JFrame {public RegisterJFrame(){this.setSize(488,500);this.setTitle("拼图 注册");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
import YouXiUI.GameJFrame;
import YouXiUI.LoginJFrame;
import YouXiUI.RegisterJFrame;public class App {//开发过程中,main方法为程序的启动入口public static void main(String[] args) {//如果我们想要开启一个界面,就创建谁的对象就可以了//new LoginJFrame();  //  创建登录界面对象//new RegisterJFrame();   //创建注册界面new GameJFrame();   //创建游戏的主界面}
}

添加了拼图游戏中的15张小图片(一个哈士奇的拼图素材)后的代码如下:

(注意:相比于上一步,只改写了GameJFrame的代码)

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;public class GameJFrame extends JFrame {//构造方法public GameJFrame(){//Ctrl + Alt + M  提取代码形成方法//选中方法 按ctrl+B可以跳转到该方法的代码所在处initJFrame();   //调用initJFrame()方法初始化界面initJMenuBar();     //调用initJMenuBar()方法,初始化菜单initImage();    //初始化图片this.setVisible(true);    //让界面显示出来,建议写在最后}//初始化图片private void initImage() {int number = 1;//外循环--结合内循环的前提下,从上到下依次添加一行,一共添加四行,Y值依次增加105像素,X值不变for (int i = 0; i < 4; i++) {//内循环--在每一行从左到右依次添加一张图片,一共添加四张,X值依次增加105像素,Y值不变for (int j = 0; j < 4; j++) {//然后创建一个JLabel的对象(即管理容器)  注意留意路径中的变量number的书写方法JLabel jLabel = new JLabel(new ImageIcon("D:\\IDEA2020\\IDEAprocejts\\PinTuYouXi\\image\\animal\\animal3\\"+number+".jpg"));//根据坐标,设置图片的位置jLabel.setBounds(105*j,105*i,105,105);//利用getContentPane()获取到隐藏容器,然后用add()把图片添加到JFrame的隐藏容器中this.getContentPane().add(jLabel);//添加一次之后number需要自增,表示下一次加载后面的图片number++;}}}//创建初始化菜单的方法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("公众号");//4、将每一个选项下面的条目对象添加到选项当中functionJMenu.add(replayItem);functionJMenu.add(reLoginItem);functionJMenu.add(closeItem);aboutJMenu.add(accountItem);//5、将菜单里面的两个选项添加到菜单当中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);   //设置程序关闭的方式this.setLayout(null);   //取消图片默认的居中防放置,只有取消了才会按照XY轴的形式添加组件}
}

游戏主界面添加组件小结

 4、打乱图片

每一张小的图片都是跟一个唯一的数字产生对应关系,分别是1~15和0(空白区域为0)如下图

我们可以把1~15和0,放入数组容器中,然后在容器中打乱顺序,然后每4个数放入一个单独的一维数组当中,再把4个一维数组放入一个二维数组当中,方便管理。如下图:

在继续开发这个小游戏之前,需要做一个小练习,来熟悉一下开发这个游戏需要用到的技术

小练习:打乱一维数组中的数据

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

要求:打乱一维数组中的数据,并按照4个一组的方式添加到二维数组中。

package TEST;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++) {//获取到随即索引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++) {System.out.print(tempArr[i] + " ");}System.out.println();//创建一个二维数组int[][] date = new int[4][4];//给二维数组添加数据/*//方法1://遍历一维数组tempArr得到每一个元素,把每一个元素依次添加到二维数组当中for (int i = 0; i < tempArr.length; i++) {//在i依次增加的过程中date的右下标依次为// i为0~3时:[0][0] [0][1] [0][2] [0][3]// i为4~7时:[1][0] [1][1] [1][2] [1][3]// i为8~11时:[2][0] [2][1] [2][2] [2][3]// i为12~15时:[3][0] [3][1] [3][1] [3][3]date[i/4][i%4] = tempArr[i];}*///方法2://遍历二维数组,然后给里面的每一个数据赋值int index02 = 0;for (int i = 0; i < date.length; i++) {for (int j = 0; j < date[i].length; j++) {//等式左边依次为二维数组的每一个元素(由于嵌套循环的存在),等式右边依次为一维数组的每个元素(由于计数器index02的存在)date[i][j] = tempArr[index02];index02++;}}//打印添加到二维数组之后的效果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();}}
}

下面我们继续开发小游戏,对游戏中的图片进行打乱。

(注意:在之前的基础上修改了GameJFrame的代码,其他模块代码不变)

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;
import java.util.Random;public class GameJFrame extends JFrame {//创建一个二维数组//目的:用来管理数据。加载图片的时候,会根据二维数组中的数据进行加载//因为初始化数据时,初始化图片时都会用到这个二维数组,所以把二维数组定义在成员变量的位置int[][] date = new int[4][4];//构造方法public GameJFrame(){//Ctrl + Alt + M  提取代码形成方法//选中方法 按ctrl+B可以跳转到该方法的代码所在处initJFrame();   //调用initJFrame()方法初始化界面initJMenuBar();     //调用initJMenuBar()方法,初始化菜单initDate();     //初始化数据(打乱)initImage();    //初始化图片(根据打乱之后的结果去加载图片)this.setVisible(true);    //让界面显示出来,建议写在最后}//初始化数据(打乱)private void initDate() {//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++) {//获取到随即索引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++) {date[i/4][i%4] = tempArr[i];}}//初始化图片//由于二维数组已经创建好,所以添加图片的时候,就需要按照二维数组中管理的数据进行添加图片了//因此之前的number就不需要了,就u、需要删掉了private void initImage() {//外循环--结合内循环的前提下,从上到下依次添加一行,一共添加四行,Y值依次增加105像素,X值不变for (int i = 0; i < 4; i++) {//内循环--在每一行从左到右依次添加一张图片,一共添加四张,X值依次增加105像素,Y值不变for (int j = 0; j < 4; j++) {//获取当前要加载图片的序号,date[i][j]的结果是这个位置上对应的数据值int num = date[i][j];//然后创建一个JLabel的对象(即管理容器)JLabel jLabel = new JLabel(new ImageIcon("D:\\IDEA2020\\IDEAprocejts\\PinTuYouXi\\image\\animal\\animal3\\"+num+".jpg"));//根据坐标,设置图片的位置jLabel.setBounds(105*j,105*i,105,105);//利用getContentPane()获取到隐藏容器,然后用add()把图片添加到JFrame的隐藏容器中this.getContentPane().add(jLabel);}}}//创建初始化菜单的方法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("公众号");//4、将每一个选项下面的条目对象添加到选项当中functionJMenu.add(replayItem);functionJMenu.add(reLoginItem);functionJMenu.add(closeItem);aboutJMenu.add(accountItem);//5、将菜单里面的两个选项添加到菜单当中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);   //设置程序关闭的方式this.setLayout(null);   //取消图片默认的居中防放置,只有取消了才会按照XY轴的形式添加组件}
}

5、事件

事件是可以被组件识别的操作。当你对组件干了某件事情之后,就会执行对应的代码。

事件源:通常是指产生事件的组件。例如:按钮、图片、窗体等等

事件:对组件进行的操作。例如:鼠标单击、鼠标划入等等

绑定监听:当事件源上发生了某个事件,监听器就会做出相应的处理,执行某段代码。

常用的三个监听如下:

5.1 动作监听

动作监听实现的两种方式:

方式1:匿名内部类的实现方式

package TEST;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class Test01 {public static void main(String[] args) {JFrame jFrame = new JFrame();jFrame.setSize(603,680);//设置界面宽高jFrame.setTitle("事件演示01");jFrame.setAlwaysOnTop(true);//设置界面置顶jFrame.setLocationRelativeTo(null);//设置界面居中jFrame.setDefaultCloseOperation(3);jFrame.setLayout(null);//取消组件居中放置//创建一按钮对象JButton jtb = new JButton("点我啊");//设置位置和宽高jtb.setBounds(0,0,100,50);/**给按钮添加监听动作* jtb:组件对象,表示要给哪个组件添加对象* addActionListener:表示我要给组件添加哪个监听事件(这里添加的是动作监听,包含鼠标左键点击、空格)* 参数:表示事件被触发之后要执行的代码*//*** 在实际开发当中,每一个按钮的业务逻辑不一样,所以我们书写的MyActionListener只能被* 用到一次,只能被这个jtb按钮使用,其他的按钮用不了这个业务逻辑。当一个接口的实现类* 只能被用一次的时候,我们就没必要单独定义这个类了,此时可以用匿名内部类去简化代* 码,省去了定义类的过程。*/jtb.addActionListener(new ActionListener(){@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("达咩~不要点我哟~");}});//不要忘了把按钮添加到界面当中jFrame.getContentPane().add(jtb);jFrame.setVisible(true);}
}

方式2:用本界面继承JFrame,调用ActionListener接口,把重写的方法写在本类当中,然后在传递的时候不用再new了,直接用this表示本类的对象就可以了。代码如下:

package TEST;import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
//继承JFrame是为了创建窗口,调用ActionListener接口是为了给按钮设置监听
public class MyJFrame extends JFrame implements ActionListener {//创建一个按钮对象JButton jtb1 = new JButton("点我啊");//创建一个按钮对象JButton jtb2 = new JButton("再点我啊");//构造方法public MyJFrame(){this.setSize(603,680);    //设置窗口的属性(宽 高)this.setTitle("拼图单机版 v1.0");    //设置界面标题this.setAlwaysOnTop(true);  //设置页面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setLayout(null);jtb1.setBounds(0,0,100,50);//给按钮添加事件//括号中的this表示的是本类的对象,作用是监听后让执行本类(MyJFrame类)中的代码jtb1.addActionListener(this);jtb2.setBounds(100,0,100,50);//给按钮添加事件jtb2.addActionListener(this);//把按钮添加到界面当中this.getContentPane().add(jtb1);this.getContentPane().add(jtb2);//让整个界面显现出来this.setVisible(true);}@Overridepublic 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));}}
}
package TEST;public class Test {public static void main(String[] args) {new MyJFrame();}
}

5.2 鼠标监听

分为四类:划入动作,按下动作、松开动作、划出动作。

按下动作和松开动作归为一组,称为单击动作。

实践代码如下:

package TEST;import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
//继承JFrame是为了创建窗口,调用MouseListener接口是为了给按钮设置鼠标监听
//调用接口的时候,需要重写接口中的所有方法,利用alt+回车的快捷方式书写
public class MyJFrame extends JFrame implements MouseListener {//创建一个按钮对象JButton jtb1 = new JButton("点我啊");//构造方法public MyJFrame(){this.setSize(603,680);    //设置窗口的属性(宽 高)this.setTitle("拼图单机版 v1.0");    //设置界面标题this.setAlwaysOnTop(true);  //设置页面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setLayout(null);jtb1.setBounds(0,0,100,50);//给按钮绑定鼠标事件,参数this表示执行本类中的代码(即执行本类中的重写的方法)jtb1.addMouseListener(this);//把按钮添加到界面当中this.getContentPane().add(jtb1);//让整个界面显现出来this.setVisible(true);}@Overridepublic void mouseClicked(MouseEvent e) {System.out.println("单击");}@Overridepublic void mousePressed(MouseEvent e) {System.out.println("按下不松");}@Overridepublic void mouseReleased(MouseEvent e) {System.out.println("松开");}@Overridepublic void mouseEntered(MouseEvent e) {System.out.println("划入");}@Overridepublic void mouseExited(MouseEvent e) {System.out.println("划出");}
}
package TEST;public class Test {public static void main(String[] args) {new MyJFrame();}
}

鼠标监听机制的方法摘要:

 5.3 键盘监听

 实践代码如下:

package TEST;import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
//继承JFrame是为了创建窗口,调用MouseListener接口是为了给按钮设置鼠标监听
//调用接口的时候,需要重写接口中的所有方法,利用alt+回车的快捷方式书写
public class MyJFrame extends JFrame implements KeyListener {//构造方法public MyJFrame(){this.setSize(603,680);    //设置窗口的属性(宽 高)this.setTitle("拼图单机版 v1.0");    //设置界面标题this.setAlwaysOnTop(true);  //设置页面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setLayout(null);//给整个窗体添加键盘监听//调用者this:本类对象,当前的界面对象,表示我要给当前整个界面添加监听//addKeyListener:表示要给本界面添加键盘监听//参数this:当事件被触发后,会执行本类中的对应代码(即执行本类中重写的方法)this.addKeyListener(this);//让整个界面显现出来this.setVisible(true);}@Overridepublic void keyTyped(KeyEvent e) {}/**小细节* 细节1:如果我们按下一个按键没有松开,那么会重复调用keyPressed方法* 细节2:键盘里面那么多按键,如何进行区分?  答:每一个按键都有一个编号与之对应*/@Overridepublic void keyPressed(KeyEvent e) {System.out.println("按下不松");}@Overridepublic 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");}}
}
package TEST;public class Test {public static void main(String[] args) {new MyJFrame();}
}

6 美化界面

图片美化业务逻辑:

1、让15张随机图片整体在中央偏下方显示。

2、给游戏添加一个背景图片。

3、给每一张小图片添加一个小边框。

实现代码如下:

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.util.Random;public class GameJFrame extends JFrame {//创建一个二维数组//目的:用来管理数据。加载图片的时候,会根据二维数组中的数据进行加载//因为初始化数据时,初始化图片时都会用到这个二维数组,所以把二维数组定义在成员变量的位置int[][] date = new int[4][4];//构造方法public GameJFrame(){//Ctrl + Alt + M  提取代码形成方法//ctrl+alt+左键  可以回到我们刚刚查看的地方//选中方法 按ctrl+B可以跳转到该方法的代码所在处initJFrame();   //调用initJFrame()方法初始化界面initJMenuBar();     //调用initJMenuBar()方法,初始化菜单initDate();     //初始化数据(打乱)initImage();    //初始化图片(根据打乱之后的结果去加载图片)this.setVisible(true);    //让界面显示出来,建议写在最后}//初始化数据(打乱)private void initDate() {//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++) {//获取到随即索引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++) {date[i/4][i%4] = tempArr[i];}}//初始化图片//由于二维数组已经创建好,所以添加图片的时候,就需要按照二维数组中管理的数据进行添加图片了//因此之前的number就不需要了,就u、需要删掉了private void initImage() {//外循环--结合内循环的前提下,从上到下依次添加一行,一共添加四行,Y值依次增加105像素,X值不变for (int i = 0; i < 4; i++) {//内循环--在每一行从左到右依次添加一张图片,一共添加四张,X值依次增加105像素,Y值不变for (int j = 0; j < 4; j++) {//获取当前要加载图片的序号,date[i][j]的结果是这个位置上对应的数据值int num = date[i][j];//然后创建一个JLabel的对象(即管理容器)JLabel jLabel = new JLabel(new ImageIcon("image\\animal\\animal3\\"+num+".jpg"));//根据坐标,设置图片的位置//图片美化1:给每一张小图片分别添加83和134像素的位移,让它们做一个整体的偏移,使15张小图片在中央偏下方显示jLabel.setBounds(105*j + 83,105*i + 134,105,105);//图片美化3:给小图片添加边框//BevelBorder斜面边框对象//0:表示让图片凸起来,英文常量为RAISED        1:表示让图片凹下去,英文常量为LOWEREDjLabel.setBorder(new BevelBorder(1));//利用getContentPane()获取到隐藏容器,然后用add()把图片添加到JFrame的隐藏容器中this.getContentPane().add(jLabel);}}/**路径分为两种:(绝对路径和相对路径)* 绝对路径:一定是从盘符开始的。例如:D:\IDEA2020\IDEAprocejts\PinTuYouXi\image\background.png* 相对路径:不是从盘符开始的。相对路径是相对当前项目而言。例如:aaa\\bbb 表示在当前项*          目下,去找aaa文件夹,里面再找bbb文件夹。下面image\\background.png*  运行之后如果图片消失不显示了,肯定是路径方面有问题,可以各种尝试修改代码中的路径,就可以解决掉这个问题*///图片美化2:添加背景图片//小细节:先加载的图片在上方,后加载的图片在下方,//所以得先加载小图片,再加载背景图片,即添加背景图片的代码添加在添加小图片代码的下面JLabel background = new JLabel(new ImageIcon("image\\background.png"));//利用相对路径优化了图片的路径background.setBounds(40,40,508,560);//把背景图片添加到界面当中this.getContentPane().add(background);}//创建初始化菜单的方法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("公众号");//4、将每一个选项下面的条目对象添加到选项当中functionJMenu.add(replayItem);functionJMenu.add(reLoginItem);functionJMenu.add(closeItem);aboutJMenu.add(accountItem);//5、将菜单里面的两个选项添加到菜单当中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);   //设置程序关闭的方式this.setLayout(null);   //取消图片默认的居中防放置,只有取消了才会按照XY轴的形式添加组件}
}
package YouXiUI;/**注册界面业务逻辑* 获取用户输入的用户名* 获取用户输入的密码(两次)* 比较两次的密码是否一致* 判断当前用户是否已经注册等等*/
import javax.swing.*;public class RegisterJFrame extends JFrame {public RegisterJFrame(){this.setSize(488,500);this.setTitle("拼图 注册");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
package YouXiUI;/**登录界面的业务逻辑* 获取用户输入的用户名* 获取用户输入的密码* 生成一个验证码* 获取用户输入放入验证码* 比较用户名、密码、验证码等等*/
import javax.swing.*;public class LoginJFrame extends JFrame {public LoginJFrame(){this.setSize(488,430);  //this代表当前对象(当前的LoginJFrame对象)this.setTitle("拼图 登录");    //设置界面标题this.setAlwaysOnTop(true);  //设置界面置顶this.setLocationRelativeTo(null);   //设置界面居中,默认情况下页面是在左上角的位置this.setDefaultCloseOperation(3);   //设置程序关闭的方式this.setVisible(true);  //设置窗口为显示}
}
import YouXiUI.GameJFrame;
import YouXiUI.LoginJFrame;
import YouXiUI.RegisterJFrame;public class App {//开发过程中,main方法为程序的启动入口public static void main(String[] args) {//如果我们想要开启一个界面,就创建谁的对象就可以了//new LoginJFrame();  //  创建登录界面对象//new RegisterJFrame();   //创建注册界面new GameJFrame();   //创建游戏的主界面}
}

7 上下左右移动

向上移动实际上就是把空白方块下方的图片上移。

逻辑分析:每一张小图片其实都是跟一个唯一的数字对应,而这些数字都放在了二维数组当中,我们只需要找两个数字在二维数组中的位置,然后做一下数据交换,交换完之后。根据最新的数字加载相应的图片就可以实现图片的移动了。

 首先我们要实现的不是上下左右移动。而是需要先给整个界面添加键盘监听事件。因此要让GameJFrame调用键盘监听接口(调用一个接口时,记得要重写里面所有的抽象方法)

代码实现如下:(相比于上一步的代码,只修改了GameJFrame部分的代码)

package YouXiUI;/**主界面业务逻辑* 上下左右移动的代码逻辑* 统计步数的代码逻辑* 一键通关、查看最终效果、恶搞好友等等*/
import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;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 {int[][] date = new int[4][4];//记录空白方块在二维数组中的位置int x = 0;int y = 0;//构造方法public GameJFrame(){initJFrame();   //调用initJFrame()方法初始化界面initJMenuBar();     //调用initJMenuBar()方法,初始化菜单initDate();     //初始化数据(打乱)initImage();    //初始化图片(根据打乱之后的结果去加载图片)this.setVisible(true);    //让界面显示出来,建议写在最后}//初始化数据(打乱)private void initDate() {//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++) {//获取到随即索引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++) {if(tempArr[i] == 0){    //找到0的时候,用x和y记录0的位置x = i / 4;y = i % 4;} else  {date[i/4][i%4] = tempArr[i];}}}//初始化图片//根据二维数组中的数字进行图片加载private void initImage() {//清空已经出现的所有图片,然后再运行循环,让图片进行重新加载this.getContentPane().removeAll();for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {//获取当前要加载图片的序号,date[i][j]的结果是这个位置上对应的数据值int num = date[i][j];//然后创建一个JLabel的对象(即管理容器)JLabel jLabel = new JLabel(new ImageIcon("image\\animal\\animal3\\"+num+".jpg"));jLabel.setBounds(105*j + 83,105*i + 134,105,105);jLabel.setBorder(new BevelBorder(1));   //图片美化3:给小图片添加边框//利用getContentPane()获取到隐藏容器,然后用add()把图片添加到JFrame的隐藏容器中this.getContentPane().add(jLabel);}}JLabel background = new JLabel(new ImageIcon("image\\background.png"));//图片美化2:添加背景图片background.setBounds(40,40,508,560);//把背景图片添加到界面当中this.getContentPane().add(background);//刷新一下加载图片后的界面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("公众号");//4、将每一个选项下面的条目对象添加到选项当中functionJMenu.add(replayItem);functionJMenu.add(reLoginItem);functionJMenu.add(closeItem);aboutJMenu.add(accountItem);//5、将菜单里面的两个选项添加到菜单当中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);   //设置程序关闭的方式this.setLayout(null);   //取消图片默认的居中防放置,只有取消了才会按照XY轴的形式添加组件//给整个界面添加监听事件this.addKeyListener(this);}@Overridepublic void keyTyped(KeyEvent e) {}@Overridepublic void keyPressed(KeyEvent e) {}@Overridepublic void keyReleased(KeyEvent e) {//对上、下、左、右进行判断//左:37  上:38  右:39  下:40//用code记录用户按下的键盘int code = e.getKeyCode();//对code的值进行判断,然后执行对应的操作if(code == 37){if(y == 3){//表示空白方块右面已经没有图片了,空白块就在最右面的一列return;}/**向左移动逻辑:[空白][数字]--->[数字][空白]* x,y 表示空白方块        x,y+1 表示空白块右边的数字* 把右边的数字赋值给空白方块,然后让右边的数值为0,* 交换数据之后,更新一下当前空白块对应的x,y值*/date[x][y] = date[x][y+1];date[x][y+1] = 0;y++;//空白方块相当于向右移动了,更新一下y的值//调用方法按照最新的数字加载图片initImage();} else if(code == 38){if(x == 3){//表示空白方块下面已经没有图片了,空白块就在最下面一行return;}/**向上移动逻辑:[空白]    [数字]*             [数字]--->[空白]* x,y 表示空白方块        x+1,y 表示空白方块下的数字* 把下边的数字赋值给空白方块,然后让下边的数值为0,* 交换数据之后,更新一下当前空白块对应的x,y值*/date[x][y] = date[x+1][y];date[x+1][y] = 0;x++;//空白方块相当于向下移动了,更新一下x的值//调用方法按照最新的数字加载图片initImage();} else if(code == 39){if(y == 0){//表示空白方块左面已经没有图片了,空白块就在最左面的一列return;}/**向右移动逻辑:[数字][空白]--->[空白][数字]* x,y 表示空白方块        x,y-1 表示空白块左边的数字* 把左边的数字赋值给空白方块,然后让左边的数值为0,* 交换数据之后,更新一下当前空白块对应的x,y值*/date[x][y] = date[x][y-1];date[x][y-1] = 0;y--;//空白方块相当于向左移动了,更新一下y的值//调用方法按照最新的数字加载图片initImage();}else if(code == 40){if(x == 0){//表示空白方块上面已经没有图片了,空白块就在最上面一行return;}/**向下移动逻辑:[数字]    [空白]*             [空白]--->[数字]* x,y 表示空白方块        x-1,y 表示空白方块上方的数字* 把上边的数字赋值给空白方块,然后让上边的数值为0,* 交换数据之后,更新一下当前空白块对应的x,y值*/date[x][y] = date[x-1][y];date[x-1][y] = 0;x--;//空白方块相当于向上移动了,更新一下x的值//调用方法按照最新的数字加载图片initImage();}}
}

上下左右移动业务小结:

1、给本类实现KeyListener接口,并重写所有抽象方法。

2、给整个界面添加键盘监听事件。(因为我们是在游戏界面中按上下左右键去移动的)

3、统计一下空白方块对应的数字0在二维数组中的位置,因为移动方块的本质就是让空白方块对应的数字0跟自己上下左右的数字进行数值交换。

4、在KeyReleased方法当中实现移动的逻辑。(如果用按下按键的方法去写,则如果按住键盘不送,则会一直移动,不符合游戏逻辑,所以用的抬起按键的方法)

5、Bug修复:

(1)、当空白块在最下方时,无法再次进行上移

(2)、当空白块在最上方时,无法再次进行下移。

(3)、当空白块在最左方时,无法再次进行右移。

(4)、当空白块在最右方时,无法再次进行左移。


http://www.ppmy.cn/news/576449.html

相关文章

ImageNet决定给人脸打码,却让哈士奇图片识别率猛增

晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI 315晚会让大家意识到人脸识别有多可怕。在大洋彼岸&#xff0c;全球最具影响力的AI数据集也开始行动了。 近日&#xff0c;ImageNet数据集决定&#xff1a;给所有人脸打码&#xff0c;保护被收录者隐私。 ImageNet管理者之一Olga…

电脑、笔记本网络提速解决方案

我们用电脑或者笔记本连接网络有时候会发现网速始终上不去&#xff0c;打开浏览器浏览页面都要转圈圈&#xff0c;那么我们可以按照下面的步骤进行设置&#xff1a; 一、使用windows徽标键R打开运行 输入 gpedit.msc 二、打开本地组策略编辑器 三、按照下面这个依次点击&#x…

电脑管家加速

问题描述&#xff1a; 之前使用电脑管家满30min后&#xff0c;qq会自动加速0.2天&#xff0c;现在不加速了如下图&#xff1a; 解决办法&#xff1a;由于版本问题现在需要手动加速。 1、进入到个人中心&#xff1a;登陆电脑管家后&#xff0c;点击左上角自己的头像进入即可&am…

加速电脑浏览器下载和加载网页速度

昨天用电脑时发现一个很大的问题&#xff0c;就是自己的笔记本网页加载和文件下载速度极其的缓慢&#xff0c;网速有一部分原因之外还有应该就是自己电脑配置和浏览器设置问题了&#xff0c;今早研究了一下&#xff0c;按照一个大佬的操作方式果然有所提升&#xff0c;故借此博…

window加速设置,让电脑运行速度大幅提升

1.关闭优化传递 2.增加引导处理器个数 winR输入msconfig 3.提升网速 winR输入gpedit.msc,管理模板->网络->Qos数据包计划程序->限制可保留宽带&#xff0c;启用它&&设置为0 4.关闭SysMain winR输入services.msc,点击禁用 5.加速磁盘 设备管理器->选中自…

什么是GPU加速

1、什么是GPU加速计算 GPU&#xff0c;又称显示核心、视觉处理器、显示芯片&#xff0c;是一种专门在个人电脑、工作站、游戏机和一些移动设备&#xff08;如平板电脑、智能手机等&#xff09;上图像运算工作的微处理器&#xff0c;与CPU类似&#xff0c;只不过GPU是专为执行复…

启动计算机的程序方法单击,7种方法,让你的Windows计算机加速起来!

原标题&#xff1a;7种方法&#xff0c;让你的Windows计算机加速起来&#xff01; 电脑用久了&#xff0c;会发现开机时间越来越长&#xff0c;打开软件速度越来越慢&#xff0c;动不动就出现系统无响应。是否厌倦了越来越缓慢的计算机&#xff1f;是否在寻找加快计算机速度的方…

教你如何处理加速电脑速度(转载)

第一招&#xff1a;清除系统垃圾——你也可以做的到&#xff01;在每天使用电脑的工作、学习和娱乐中&#xff0c;你是否注意到你的电脑系统磁盘的可用空间正在一天天的减少呢&#xff1f;系统是不是也像老去的猴王一样&#xff0c;动作一天比一天迟缓呢&#xff1f;终于有一天…