Java实现

您所在的位置:网站首页 拼图游戏小程序怎么做的 Java实现

Java实现

2024-07-09 07:33:21| 来源: 网络整理| 查看: 265

目录

一、准备项目结构

1.1 主方法

1.2Jframe界面包

二、代码的实现

2.1 主方法

2.2 GameJframe 

2.2.1 资源包引用

2.2.2 构建GameJframe类

2.2.3 GameJframe的成员变量

完整的实现效果

使用Java实现拼图游戏。界面使用的是JFrame实现。

一、准备项目结构

1.1 主方法

在我们实现代码之前,先把项目结构构建好。我们以一个名为App的类作为运行的主方法,在其中调用游戏界面,我们将所有的游戏业务都实现在名为GameJframe的类中。

1.2Jframe界面包

在这里面,我们实现了三个类,第一个GameJframe是我们的游戏界面,第二个LoginJframe是登陆界面,第三个是RegisterJframe注册界面。我们在这里就不实现注册界面与登陆界面了,我们只讲解游戏界面的实现。

准备好这样的结构之后,我们就可以开始进行代码的书写了。

二、代码的实现

下面的内容,我将逐步分析代码的组成与功能,不能直接看到完整的代码,完整的代码放在了此目录的最后,在目录上点击    2.2.4.6 完整代码    可以查看。

2.1 主方法 import Jframe.GameJframe; //拼图游戏 public class App { public static void main(String[] args) { new GameJframe(); } }

我们调用Jframe中的GameJframe类,来创建一个新的Jframe界面用来实现我们的游戏界面,其余的登录界面与注册界面暂不实现。所以主方法就非常简单,只需这一步即可。

2.2 GameJframe  2.2.1 资源包引用

首先,我们声明一下包,与要引入的资源,在使用idea开发的过程中自动添加,不需要刻意关注,如果使用的编译器没有此功能,自己在开发的过程中搜索添加即可。

package Jframe; import javax.swing.*; import javax.swing.border.BevelBorder; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Arrays; import java.util.Random; 2.2.2 构建GameJframe类

之后呢,我们构建GameJframe类。因为我们要在这里面实现窗体,所以我们继承JFrame类。又因为我们在使用游戏的时候,需要用到鼠标与键盘操作,所以我们再写入KeyListener键盘接听接口,与ActionListener接口,由于我们不需要太复杂的鼠标操作,只需点击即可,所我没有使用MouseListener。

public class GameJframe extends JFrame implements KeyListener, ActionListener { } 2.2.3 GameJframe的成员变量

来思考需要用到的成员变量,很多东西在我们将要实现的方法中会用到,比如存放各块拼图的二维数组,用来计步数的变量。游戏菜单的各项功能。判断是否胜利的数组,这个数组保存着我们图片的正确顺序。

2.2.3.1 计数器 int counter = 0; 2.2.3.2 二维数组

由于我们只实现了4*4的游戏,所以只需要创建一个4*4的二维数组即可,需要别的玩法可自行创建

int[][] data = new int[4][4]; 2.2.3.3 游戏菜单

游戏菜单的具体逻辑是这样的,JMenuBar包含JMenu,JMenu包含着JMenuItem

JMenuBar是整个菜单,所以我们从JMeun开始实现

JMenu functionJMenu = new JMenu("功能"); JMenu aboutJMenu = new JMenu("关于我们");

在功能中,我们要实现更换图片,但是更换图片也需要选项,所以,更换图片也是一个包含JMenuItem的JMenu,再把更换图片的这个JMenu加到功能这个JMenu中即可,所以更换图片JMenu中的JMenu。

JMenu changeImage = new JMenu("更换图片"); //我们这里将崩坏星穹铁道的图标设置在游戏中 //或许我们还可以将其他的关于崩铁的图片设置在里面,所以 //我们直接把“崩铁”做成一个菜单 JMenu Star_rail = new JMenu("崩铁");

接下来,我们实现JMenuItem,也就是上述的各种菜单中的选项。

​ //这些是功能中的选项 JMenuItem replayItem = new JMenuItem("重新游戏"); JMenuItem reLoginItem = new JMenuItem("重新登陆"); JMenuItem closeItem = new JMenuItem("关闭游戏"); JMenu changeImage = new JMenu("更换图片"); //这些是关于我们中的选项 //公众号只是举个例子,你可以是先别的来这里 JMenuItem accountItem = new JMenuItem("公众号"); //这个是更改图片中的崩铁中的选项 //创建崩铁下的选项 JMenuItem March = new JMenuItem("三月七"); JMenuItem FireFly = new JMenuItem("流萤"); ​

用以判断的胜利数组,存放着正确的顺序(最后一项为空,也就是拼图游戏中空白的格子)。

int[][] win = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,0} };  2.2.3.4 图片路径

为了方便代码的书写,我们干脆一劳永逸,直接把路径定义为变量,之后的代码只需要改变这个量即可。

​ //记录16块图片路径 默认为Star_rail 后续可以更改 String path1 = "image/Star_rail/("; //记录完整图片路径 String pathAll = "image/Star_rail/Start Rail.jpg"; ​

这下我们的GameJframe的成员变量就书写完毕了。

2.2.4 GameJframe的方法 2.2.4.1 加载数据方法

写到这里,我们应该加载数据了,其中包括,写一个0-15的数组,将其打乱,将打乱的数组放入我们先前准备好的二维数组。一些必要的注释已经写在里面了。

private void initData(){ //需求:把0-15的数据打乱顺序 //然后再按照4各一组的方式添加到二维数组中 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 :tempArr){ if(tempArr[i]==0){ x = i / 4; y = i % 4; } data[i / 4][i % 4] = tempArr[i]; } } 2.2.4.2 判断胜利的方法

我们在不断的交换图片过程中,其实就是改变data中数据的过程,判断胜利,只需要比较data与我们的win数组是否相同即可。

private boolean check_win(){ return Arrays.deepEquals(data, win); } 2.2.4.3加载图片的方法

写到这里,我们要开始加载图片了,结合了我们先前打乱的二维数组来插入图片,所以没我们的图片也要打乱,那如何建立两者之间的联系呢?做到这里的读者,请务必将分好的16张图片,按照图片顺序,进行1-16的命名,这样的话,我们只需要在路径中,运用数字,将图片添加进来。

再定义一个int num;获取二维数组的值,我们就可以按照num添加照片了。比如,在我的16张图片中,均命名为  (1).jpg…………,(16).jpg,这样我们添加的时候,就可以添加

"image/("+num+").jpg";  那这样,他就会分别添加"image/(1).jpg","image/(2).jpg","image/(3).jpg"…………,最终添加到"image/(15).jpg"。而且,因为数组只添加0-15,空下来的0,由于找不到对应的图片,就会打印空白,正好对应了我们拼图中的空白。接下来的移动,无非就是这个空白图片与相邻图片的交换而已。 

我们还需要做一个胜利图标,我的可能跟你们的不一样,所以你们实现完之后,要根据图片大小,修改位置。

private void initImage() { this.getContentPane().removeAll(); if(check_win()){ //显示胜利图标 JLabel winJLabel = new JLabel(new ImageIcon("image/winJframe.jpg")); winJLabel.setBounds(173,-5,210,80); this.getContentPane().add(winJLabel); } JLabel Stepcounter = new JLabel("步数:"+counter); Stepcounter.setBounds(50,30,100,20); this.getContentPane().add(Stepcounter); for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { //获取打乱二维数组序号 int num = data[j][i]; JLabel jLabel = new JLabel(new ImageIcon(path1+num+").jpg")); jLabel.setBounds(105 * i+83, 105*j+134, 105, 105); //给图片加边框 jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); this.getContentPane().add(jLabel); } } //刷新界面 this.getContentPane().repaint(); } 2.2.4.4 创建菜单界面

很多注意事项都放在了注释中,需要额外注意的是,

private void initJMenuBar() { //创建菜单 JMenuBar jMenuBar = new JMenuBar(); //将Item添加到JMenu中 functionJMenu.add(replayItem); functionJMenu.add(reLoginItem); functionJMenu.add(closeItem); functionJMenu.add(changeImage); aboutJMenu.add(accountItem); //给更改图片加菜单 changeImage.add(Star_rail); //给崩铁加选项 其中March表示的是崩铁的图标,FireFly是流萤的图片 Star_rail.add(March); Star_rail.add(FireFly); //将JMenu添加到JMenuBar中 jMenuBar.add(functionJMenu); jMenuBar.add(aboutJMenu); //给游戏功能绑定事件 replayItem.addActionListener(this); reLoginItem.addActionListener(this); closeItem.addActionListener(this); accountItem.addActionListener(this); //给选项添加监听 FireFly.addActionListener(this); March.addActionListener(this); //将菜单放在界面中 this.setJMenuBar(jMenuBar); } 2.2.4.5 键盘监听重构方法

keyPressed表示按住不动某个键要实现的代码,根据这个逻辑,我们可以设置按住A不动时,我们加载整张图片供玩家查看。这样会方便玩家解出。

我们的逻辑就是,按住A时,删除界面所有图片,添加完整的一张图,刷新界面。A的编号是65,所以我们keyPressed中参数e在按住A的时候等于65。

​ @Override public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); if(code == 65){ //把界面中所有图片删除 this.getContentPane().removeAll(); //加载第一张完整的图片 JLabel all = new JLabel(new ImageIcon(pathAll)); all.setBounds(83,134,420,420); this.getContentPane().add(all); //刷新界面 this.getContentPane().repaint(); } } ​

接下来就是移动图片了keyReleased方法,可以检测我们是否松开了某个键,所以常用来实现功能,键盘上的左,对应的是37,上是38,右是39,下是40,每按下相应的按钮,就交换对应的两张图片,每按一次就判断游戏是否胜利,胜利了就返回方法。

@Override public void keyReleased(KeyEvent e) { //判断游戏游戏是否胜利 if(check_win()){ return; } //对应的编码 左:37 上:38 右:39 下:40 // int code = e.getKeyCode(); if(code == 37){ data[x][y] = data[x][y+1]; data[x][y+1] = 0; y = y+1; counter++; initImage(); }else if(code == 38){ data[x][y] = data[x+1][y]; data[x+1][y] = 0; x = x+1; counter++; initImage(); }else if(code == 39){ data[x][y] =data[x][y-1]; data[x][y-1] = 0; y=y-1; counter++; initImage(); }else if(code == 40){ data[x][y] = data[x-1][y]; data[x-1][y] = 0; x = x-1; counter++; initImage(); }else if(code == 65){ initImage(); }else if(code == 87){ data = new int[][]{ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,0} }; initImage(); } }

2.2.4.6 鼠标监听重构方法

@Override public void actionPerformed(ActionEvent e) { //获取当前被点击的对象 Object obj = e.getSource(); if(obj == replayItem){ //再次打乱 initData(); //计数器清零 counter =0; //重新加载 initImage(); }else if(obj == reLoginItem){ //返回登陆界面 //关闭当前游戏界面 this.setVisible(false); //打开登陆界面 这里由于我们没有实现,所以无法使用 new LoginJframe(); }else if(obj == closeItem){ System.exit(0); }else if(obj == accountItem){ //创建一个弹窗对象 JDialog jDialog = new JDialog(); //管理图片 JLabel jLabel = new JLabel(new ImageIcon("这里放入你公众号,或者别的什么图片路径")); //根据图片大小修改位置,我的不一定适配你的 jLabel.setBounds(0,0,258,258); jDialog.getContentPane().add(jLabel); jDialog.setSize(344,344); jDialog.setAlwaysOnTop(true); //居中 jDialog.setLocationRelativeTo(null); //弹窗不关闭无法操作当前界面 jDialog.setModal(true); //显示弹窗 jDialog.setVisible(true); }else if(obj == March){ pathAll = "image/Star_rail/Start Rail.jpg"; path1 = "image/Star_rail/("; initImage(); }else if(obj == FireFly) { pathAll = "image/Fire fly/Fire Fly.jpg"; path1 = "image/Fire fly/("; initImage(); } 2.2.4.6 完整代码 2.2.4.6.1 主函数 import Jframe.GameJframe; //拼图游戏 public class App { public static void main(String[] args) { new GameJframe(); } } 2.2.4.6.2 游戏界面 package Jframe; import javax.swing.*; import javax.swing.border.BevelBorder; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.Arrays; import java.util.Random; public class GameJframe extends JFrame implements KeyListener, ActionListener { //建立随机二维数组 //加载图片的时候,根据二维数组加载 int[][] data = new int[4][4]; //计数器,用来统计步数 int counter = 0; //记录分散图片路径 String path1 = "image/Star_rail/("; //记录完成图片路径 String pathAll = "image/Star_rail/Start Rail.jpg"; //初始化菜单选项 JMenu functionJMenu = new JMenu("功能"); JMenu aboutJMenu = new JMenu("关于我"); //创建选项下面的条目对象 JMenuItem replayItem = new JMenuItem("重新游戏"); JMenuItem reLoginItem = new JMenuItem("重新登陆"); JMenuItem closeItem = new JMenuItem("关闭游戏"); JMenu changeImage = new JMenu("更换图片"); JMenu Star_rail = new JMenu("崩铁"); //创建更改图片下的菜单 JMenuItem accountItem = new JMenuItem("公众号"); //创建崩铁下的选项 JMenuItem March = new JMenuItem("三月七"); JMenuItem FireFly = new JMenuItem("流萤"); int[][] win = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,0} }; public GameJframe(){ //设置界面大小 initJFrame(); //初始化菜单 initJMenuBar(); //初始化数据 initData(); //初始化图片(根据打乱之后的结果加载图片) initImage(); //展示整个界面 this.setVisible(true); } //初始化数据 //记录空白方块的位置 int x,y; private void initData(){ //需求:把0-15的数据打乱顺序 //然后再按照4各一组的方式添加到二维数组中 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 :tempArr){ if(tempArr[i]==0){ x = i / 4; y = i % 4; } data[i / 4][i % 4] = tempArr[i]; } } //初始化图片 //先加载的图片在上方,后加载的,塞到了先加载的后方 private void initImage() { this.getContentPane().removeAll(); if(check_win()){ //显示胜利图标 JLabel winJLabel = new JLabel(new ImageIcon("image/winJframe.jpg")); winJLabel.setBounds(173,-5,210,80); this.getContentPane().add(winJLabel); } JLabel Stepcounter = new JLabel("步数:"+counter); Stepcounter.setBounds(50,30,100,20); this.getContentPane().add(Stepcounter); for (int j = 0; j < 4; j++) { for (int i = 0; i < 4; i++) { //获取打乱二维数组序号 int num = data[j][i]; JLabel jLabel = new JLabel(new ImageIcon(path1+num+").jpg")); jLabel.setBounds(105 * i+83, 105*j+134, 105, 105); //给图片加边框 jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED)); this.getContentPane().add(jLabel); } } //刷新界面 this.getContentPane().repaint(); } //创建菜单界面 private void initJMenuBar() { JMenuBar jMenuBar = new JMenuBar(); //将Item添加到JMenu中 functionJMenu.add(replayItem); functionJMenu.add(reLoginItem); functionJMenu.add(closeItem); functionJMenu.add(changeImage); aboutJMenu.add(accountItem); //给更改图片加菜单 changeImage.add(Star_rail); //给崩铁加选项 Star_rail.add(March); Star_rail.add(FireFly); //将JMenu添加到JMenuBar中 jMenuBar.add(functionJMenu); jMenuBar.add(aboutJMenu); //给游戏功能绑定事件 replayItem.addActionListener(this); reLoginItem.addActionListener(this); closeItem.addActionListener(this); accountItem.addActionListener(this); //给选项添加监听 March.addActionListener(this); FireFly.addActionListener(this); //将菜单放在界面中 this.setJMenuBar(jMenuBar); } //判断胜利 private boolean check_win(){ return Arrays.deepEquals(data, win); } private void initJFrame() { this.setSize(603,680); //设置界面标题 this.setTitle("拼图单机版"); //设置界面保持上层 this.setAlwaysOnTop(true); //设置界面居中 this.setLocationRelativeTo(null); //设置界面关闭模式 this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); //取消默认居中放置,之后才能按照xy轴放置 this.setLayout(null); //给整个界面添加键盘监听事件 this.addKeyListener(this); } @Override public void keyTyped(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { int code = e.getKeyCode(); if(code == 65){ //把界面中所有图片删除 this.getContentPane().removeAll(); //加载第一张完整的图片 JLabel all = new JLabel(new ImageIcon(pathAll)); all.setBounds(83,134,420,420); this.getContentPane().add(all); //刷新界面 this.getContentPane().repaint(); } } @Override public void keyReleased(KeyEvent e) { //判断游戏游戏是否胜利 if(check_win()){ return; } //左:37 上:38 右:39 下:40 // int code = e.getKeyCode(); if(code == 37){ data[x][y] = data[x][y+1]; data[x][y+1] = 0; y = y+1; counter++; initImage(); }else if(code == 38){ data[x][y] = data[x+1][y]; data[x+1][y] = 0; x = x+1; counter++; initImage(); }else if(code == 39){ data[x][y] =data[x][y-1]; data[x][y-1] = 0; y=y-1; counter++; initImage(); }else if(code == 40){ data[x][y] = data[x-1][y]; data[x-1][y] = 0; x = x-1; counter++; initImage(); }else if(code == 65){ initImage(); }else if(code == 87){ data = new int[][]{ {1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,0} }; initImage(); } } @Override public void actionPerformed(ActionEvent e) { //获取当前被点击的对象 Object obj = e.getSource(); if(obj == replayItem){ //再次打乱 initData(); //计数器清零 counter =0; //重新加载 initImage(); }else if(obj == reLoginItem){ //返回登陆界面 //关闭当前游戏界面 this.setVisible(false); //打开登陆界面 new LoginJframe(); }else if(obj == closeItem){ System.exit(0); }else if(obj == accountItem){ //创建一个弹窗对象 JDialog jDialog = new JDialog(); //管理图片 JLabel jLabel = new JLabel(new ImageIcon("放入你公众号的图片")); jLabel.setBounds(0,0,258,258); jDialog.getContentPane().add(jLabel); jDialog.setSize(344,344); jDialog.setAlwaysOnTop(true); //居中 jDialog.setLocationRelativeTo(null); //弹窗不关闭无法操作当前界面 jDialog.setModal(true); //显示弹窗 jDialog.setVisible(true); }else if(obj == March){ pathAll = "image/Star_rail/Start Rail.jpg"; path1 = "image/Star_rail/("; initImage(); }else if(obj == FireFly) { pathAll = "image/Fire fly/Fire Fly.jpg"; path1 = "image/Fire fly/("; initImage(); } } } 三、注意事项

没什么其他可讲的,如果出现了图片未加载出来,多半是因为你的图片路径不对。我上述的代码涉及到的路径,你可以照着写一个,但是如果你有你的图片路径,一定要找到这个图片路径,再重新写入。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭