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)、当空白块在最右方时,无法再次进行左移。