Java项目 拼图游戏

2024-03-21 02:30
文章标签 java 项目 拼图游戏

本文主要是介绍Java项目 拼图游戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        目录

1 项目基本信息

1.1 项目名称

1.2 实训环境

2 实训内容简介

2.1 拼图游戏

3 项目开发过程

3.1 拼图游戏

3.1.1 核心类

3.1.2开发步骤

4 实训总结及心得

1 项目基本信息

1.1 项目名称

拼图游戏

1.2 实训环境

JDK1.8 、eclipse 、 mysql 、navicat、Windows

2 实训内容简介

2.1 拼图游戏

        拼图游戏内容由若干小图像块组成的,其中有一个空白的小图像块,该图像块是来与别的图像块交换的,以此来实现大图像的拼凑。在Java标准环境下运行,通过鼠标点击图像块上下左右移动,完成大图像的拼凑。通过所创建的窗体类、菜单、中间面板和左右面板完成设计拼图的交互界面,实现游戏登录、开始游戏、退出游戏、选择图片、图片缩放、图片分割、调整难易度、计数计时、打乱图片、判断拼图成功等功能。游戏可以通过对图片文件的读取和加载,从多张图片中选择来进行拼图游戏,通过设置图像块的个数来实现对游戏难易度的调整,最后将游戏完成后所用时间和步数记录到游戏记录中,方便用户查看游戏记录。

3 项目开发过程

3.1 拼图游戏

3.1.1 核心类

        1.MainJFrame类:继承JFrame类,实现Runnable接口,窗体用于存放发左右面板,添加组件等等。知识点有:

a.实现游戏关卡等级
itemeasy.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {rp.hs=2; //第一,传递2*2到右面板rp.ls=2;rp.init(url); //调用右面板组件初始化的方法}});
b. 游戏记录
itemchange.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {
//显示一个打开对话框,选择一个图片文件,将文件转换为url对象,调用左右面板的相应方法JFileChooser jfc=new JFileChooser();
//设置文件的扩展名jfc.setFileFilter(new FileNameExtensionFilter("图片格式(jpg|png|jif)", "jpg","png","gif"));
//弹出打开对话框int sd=jfc.showOpenDialog(MainJFrame.this);//null表示父容器是谁if(sd==jfc.APPROVE_OPTION)//如果用户选择打开了按钮{
//获取用户选择的文件完整名称String file=jfc.getSelectedFile().getAbsolutePath();try {url=new URL("file:\\"+file);lp.init(url);rp.init(url);} catch (MalformedURLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}});
c. //记录清空itemclear.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {File f=new File("c://a");if(f.exists()){f.delete();}}});
d. 实现计时并显示步数@Overridepublic void run() {//死循环,使得代码一直在执行while (true) {endTime = System.currentTimeMillis();total_time.setText("用时:"+(endTime - startTime) / 1000 );total_count.setText("步数:"+rp.times);try {Thread.sleep(500);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

        2.LeftJPanel类:左面板,将完整图片展示在左面板。知识点:

实现图片的缩放:
public void init(URL url){ImageIcon icon=new ImageIcon(url);//使用链式编程方式实现图片缩放jl.setIcon(new ImageIcon(icon.getImage().getScaledInstance(width, height, 1)));//将标签添加到面板中this.add(jl);}

        3.RightJPanel类:右面板实现ActionListener接口,右面板成为了监听器,实现拼图。重要知识点:

a.确定按钮的位置和大小
bs=new JButton[hs*ls]; //创建按钮数组
widthbut=width/ls;// 计算按钮的宽度高度heightbut=height/hs;
for(int i=0;i<jbs.length;i++){//为每一个按钮实现初始化操作jbs[i]=new JButton();jbs[i].setSize(widthbut, heightbut);jbs[i].setLocation(i%ls*widthbut,i/ls*heightbut);// 添加按钮前要确定坐标位置
b. //图片的获取
BufferedImage subimage=buf.getSubimage(i%ls*widthxt,i/ls*heightxt, widthxt, heightxt); //小图的获取
c. //图片的缩放
Image image=subimage.getScaledInstance(widthbut, heightbut, 1);
d. //将小图图片放到按钮上
jbs[i].setIcon(new ImageIcon(image));
e. //设置按钮变色,不可用
jbs[i].setEnabled(false);
f. //设置按钮的监听,当按钮被单击,找ActionListener方法执行
jbs[i].addActionListener(this);
g. //设置最后一个按钮图片为空jbs[hs*ls-1].setIcon(null);kb=jbs[hs*ls-1];
h. //打乱按钮在面板中的顺序Random rand=new Random();//创建随机数对象for(int i=0;i<hs*ls;i++){ //打乱多次 for//生成两个随机数表示数组下标,互换两个数组元素的位置int index1 = rand.nextInt(hs * ls);int index2 = rand.nextInt(hs * ls);// getX 和getY 可以获取按钮的坐标位置int x1 = jbs[index1].getX();int y1 = jbs[index1].getY();int x2 = jbs[index2].getX();int y2 = jbs[index2].getY();jbs[index1].setLocation(x2, y2);jbs[index2].setLocation(x1, y1);jbs[i].setEnabled(true);}
i. //获取用户单击的按钮,通过ActionEvent e的方法getSource获取事件源,需要将得到的object类型中转换为按钮类型
JButton jb=(JButton)e.getSource();
j. //获取单击按钮和空白按钮的坐标int x1=jb.getX();int y1=jb.getY();int x2=kb.getX();int y2=kb.getY();
k. //判断单击按钮和空白按钮是否相邻,相邻则位置互换
if(Math.abs((x1-x2)/widthbut)+Math.abs((y1-y2)/heightbut)==1){jb.setLocation(x2, y2);// 用Math.abs取绝对值kb.setLocation(x1, y1);times++;}
l. //判断是否拼图成功if(isWin()){JOptionPane.showMessageDialog(null, "恭喜,拼图成功,总共步数:"+times);//使得按钮不可用for(int i=0;i<jbs.length;i++){jbs[i].setEnabled(false);}
m. //创建文件字符输出流对象,指向c盘,追加数据到文件
String info=hs+"*"+ls+"拼图的记录:"+name+"步数是:"+times+"\r\n";
FileWriter fw=new FileWriter("c://a//1.dat",true);fw.write(info);fw.close();
n. //获取每个按钮的坐标for(int i=0 ; i<jbs.length;i++){int x=jbs[i].getX()/widthbut;int y=jbs[i].getY()/heightbut;//方法二:通过下标值,也可获取按钮坐标  横坐标:i%ls  纵坐标 i/lsif(i%ls!=x || i/ls!=y){return false;}}

        4.TpJFrame类:实现图片分割功能。知识点有:

a. //显示一个打开对话框,选择一个图片文件,将文件转换为url对象, JFileChooser jfc=new JFileChooser();
b. //设置文件的扩展名jfc.setFileFilter(new FileNameExtensionFilter("图片文件", "jpg","bmp","jpeg"));
c. //获取用户选择的文件完整名称
jfc.getSelectedFile().getAbsolutePath()d.//获取图片后,将图片转换成Image类型的对象,进行缩放,然后再将Image类型对象转换成ImageIcon类型的对象,将图片放到jlb中
jlb.setIcon(new ImageIcon(new ImageIcon (jtf.getText()).getImage().getScaledInstance(100,100, 1)));
e. //从本地文本读取图片BufferedImage buf=ImageIO.read(new File(jtf.getText()));
f. //设置该面板标题
jp3.setBorder(BorderFactory.createTitledBorder("选择保存位置"));

3.1.2开发步骤

        1.配置开发环境,进行环境变量的配置:JAVA_HOME,path。

        2.创建窗体类MainJFrame,设置窗体大小、标题、窗体大小是否可变、窗体位置等等。在窗体内设置菜单、菜单项、单选菜单项等信息,并添加到窗体内。明确左面板、右面板、中间面板和窗体的关系:在窗体中设置一个中间面板,中间面板包括左面板和右面板。

        3.中间面板布局方式为网格布局。添加左面板和右面板:左面板(LeftJPanel)为自定义面板,继承JPanel;右面板(RightJPanel)为自定义面板,继承JPanel。

        4.左面板的设计:首先在主窗体中定义,将左面板添加到中间面板,再将中间面板添加到窗体,并进行初始化。然后在左面板类中添加一个标签,并在标签上显示图片,并实现图片缩放。

        在标签上显示图片的方法为:

ImageIcon(URL location)根据指定的 URL 创建一个 ImageIcon。相对路径:url=this.getClass().getResource("s4.jpg");绝对路径:url=new URL(“file:\\”+”d:\\abc\\1.jpg”);

        实现图片缩放的方法:图片放置在标签中,使用的类是ImageIcon,这个类没有缩放功能,Image类有缩放功能。所以要实现ImageIcon类和Image类相互转换。转换方法:

a.将ImageIcon的对象转换成Image类型的对象:public Image getImage()icon.getImage().getScaledInstance(700,700,1)b.将Image类型对象转换成ImageIcon类型的对象:ImageIcon的构造方法 ImageIcon(Image image)

        5.右面板的设计:首先在主窗体中定义,将右面板添加到中间面板,再将中间面板添加到窗体,并进行初始化。然后在右面板定义按钮数组、按钮大小及位置。然后进行图片分割,使图片显示在按钮上,在未点击开始按钮时使所有按钮变灰,不可用。设置最后一个按钮为空白按钮,方便单击按钮和空白按钮的相互转换。具体分析为:

a.首先分析按钮的大小和位置的关系,定义按钮的宽度和高度、按钮数组、行数和列数,在游戏未开始时,设置按钮不可见。bs=new JButton[hs*ls]; //创建按钮数组
widthbut=width/ls;// 计算按钮的宽度高度heightbut=height/hs;
for(int i=0;i<jbs.length;i++){//为每一个按钮实现初始化操作jbs[i]=new JButton();jbs[i].setSize(widthbut, heightbut);jbs[i].setLocation(i%ls*widthbut,i/ls*heightbut);// 添加按钮前要确定坐标位置add(jbs[i]); //添加按钮到右面板jbs[i].setEnabled(false);// 使得按钮变灰色不可用
b.实现图片分割:使用ImageIO类对图片进行读写,然后使用BufferedImage类获取BufferedImage类的对象对图片进行分割,使用到的方法为:
读图片文件:public static BufferedImage read(URL input) throws IOException
写图片文件:public static boolean write(RenderedImage im, String formatName, File output) throws IOException
分割方法:public BufferedImage getSubimage(int x, int y, int w, int h)
代码:BufferedImage subimage=buf.getSubimage(i%ls*widthxt, i/ls*heightxt, widthxt, heightxt); //小图的获取
c.分割图片后,要对图片进行缩放。使用Image类中的getScaledInstance()方法对图片进行缩放。方法为:
public Image getScaledInstance(int width, int height,int hints)
代码: Image image=subimage.getScaledInstance(widthbut, heightbut, 1); //小图的缩放
d.最后添加一个空白按钮在右下角,为实现按钮的移动提供条件。
JButton kb; //空白按钮
jbs[hs*ls-1].setIcon(null); //设置最后一个按钮图片为空
kb=jbs[hs*ls-1];

        6.拼图完成后与左面板的原图比较进行判赢。设置不同游戏等级,可分为简单、一般、困难。若想更换图片,可进行图片的更换。

        a. 开始菜单单击时,执行具体操作只与右面板的组件相关,代码放到右面板类中

        通过改变按钮的坐标位置打乱按钮的顺序。方法是:生成两个随机数表示数组下标,互换两个数组元素的位置,按钮的方法getX和getY可以获取按钮的坐标。

相关代码:

 Random rand=new Random();//创建随机数对象int index1 = rand.nextInt(hs * ls); /生成两个随机数表示数组下标,互换两个数组元素的位置int index2 = rand.nextInt(hs * ls);

        b. 当对右面板中的按钮单击的时候,移动按钮。通过按钮的单击事件的处理,设置按钮的监听事件ActionListener,将代码写在监听事件中。代码为:

jbs[i].addActionListener(this); //设置按钮的监听,当按钮被单击,找ActionListener方法执行

        c.当用户拼图完成后,与原图进行比较判断是否拼图成功。判断拼图是否成功,主要取决于每一个按钮通过索引下标获取的位置值,与当前按钮的位置值是否相同。相关代码:

for(int i=0 ; i<jbs.length;i++){//获取每个按钮的坐标int x=jbs[i].getX()/widthbut;int y=jbs[i].getY()/heightbut;if(i%ls!=x || i/ls!=y){return false;}}return true;

        d.设置游戏等级,即游戏的难易度。而游戏的难易度主要与右面板的行数和列数有关。可将行数hs和列数ls的值传给右面板,并对菜单进行监听和使用removeAll方法来清除所有组件来实现难易度。相关代码为:

rp.hs=2; //等级为简单时,传递2*2到右面板rp.ls=2;rp.init(url); //调用右面板组件初始化的方法

        e.在菜单项中有更换图片选项,用户可单击该菜单项,选择当前电脑中的图片文件,替换游戏中已有的图片。通过使用url数据的传递替换选择的图片,在两个面板中都起作用,即左面板的标签的背景图要换,右面板中的分割原图也要变。可通过监听事件实现,涉及的类有涉及到的类JFileChooser、FileNameExtendsionFilter,具体实现如下:

//显示一个打开对话框,选择一个图片文件,将文件转换为url对象,调用左右面板的相应方法
JFileChooser jfc=new JFileChooser();
//设置文件的扩展名
jfc.setFileFilter(new FileNameExtensionFilter("图片格式(jpg|png|jif)", "jpg","png","gif")); 
//null表示父容器是谁
int sd=jfc.showOpenDialog(MainJFrame.this); 
if(sd==jfc.APPROVE_OPTION)//如果用户选择打开了按钮
{  String file=jfc.getSelectedFile().getAbsolutePath();
//获取用户选择的文件完整名称
url=new URL("file:\\"+file);lp.init(url);rp.init(url);	}

        f.整个框架实现完成后,可设置计时和计数功能。

        计时:从单击开始菜单时计时开始,拼图成功计时结束。通过System类的currentTimeMillis ()方法,获取当前系统时间的毫秒值;通过线程的run()方法中,定时获取当前系统的时间点,线程的定义方法有两种:继承Thread类;实现Runnable接口,创建带实现接口的子类对象的Thread对象,重写run方法。通过公式(endTime-startTime)/1000计算出以秒为单位的时间段。

        计数:设置一个标签 total_count,使计数显示在菜单栏中,在设置一个计数功能 int times,判断按钮是否可以移动使times加1来实现计数功能。

        g.如果拼图成功,将信息记录到文件中,即菜单项中的游戏记录:显示用户之前的记录结果,读取文件并显示。通过FileWriter记录当前信息到文件中,FileReader读取文件。

        h.如果不想保留之前的记录,可将文件删除,即实现菜单项中的清空记录。相关代码为:

File f=new File("c://a");if(f.exists()){f.delete();

        7.可增加一个功能在菜单项中添加图片分割,新建一个TPJFrame类实现图片分割。

        a.新建窗口,在新窗口中设置组件四个面板,三个按钮,四个文本框和标题等等。

        b.首先通过单击选择图片按钮获取图片文件,将文件转换为url对象,获取用户选择的文件完整名称,获取图片后,将图片转换成Image类型的对象,进行缩放,然后再将Image类型对象转换成ImageIcon类型的对象,将图片放到jlb中。

4 实训总结及心得

见文档。

这篇关于Java项目 拼图游戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/831505

相关文章

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

基于SpringBoot+Mybatis实现Mysql分表

《基于SpringBoot+Mybatis实现Mysql分表》这篇文章主要为大家详细介绍了基于SpringBoot+Mybatis实现Mysql分表的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录基本思路定义注解创建ThreadLocal创建拦截器业务处理基本思路1.根据创建时间字段按年进

Java编译生成多个.class文件的原理和作用

《Java编译生成多个.class文件的原理和作用》作为一名经验丰富的开发者,在Java项目中执行编译后,可能会发现一个.java源文件有时会产生多个.class文件,从技术实现层面详细剖析这一现象... 目录一、内部类机制与.class文件生成成员内部类(常规内部类)局部内部类(方法内部类)匿名内部类二、

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

Java中的String.valueOf()和toString()方法区别小结

《Java中的String.valueOf()和toString()方法区别小结》字符串操作是开发者日常编程任务中不可或缺的一部分,转换为字符串是一种常见需求,其中最常见的就是String.value... 目录String.valueOf()方法方法定义方法实现使用示例使用场景toString()方法方法