韩顺平Java坦克大战-记录上局游戏->使用对象流保存

2022年05月13日 阅读数:9
这篇文章主要向大家介绍韩顺平Java坦克大战-记录上局游戏->使用对象流保存,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

Java视频来源:B站韩顺平教育前端

笔者在B站上看韩顺平老师的Java基础教程,到了坦克大战的阶段,基本的架构已经搞好java

韩顺平老师这里为了巩固文件流基础,特意使用了文件的形式,保存分数和上局游戏情况架构

但老师用的是最简单的Fileoutput流来进行写入坦克的坐标,子弹坐标,各类类型等等,笔者看到这里不由想到:这么复杂,用序列化的方法会不会更好一点呢?ide

我从新用IDEA的结构看了一下坦克大战的组成,发现其实就只有两大块函数

TankGame mypanel Recoder而Mypanel保存了坦克,保存了子弹,保存了爆炸状况idea

既然如此,咱们可使用对象流保存mypanel啊 因而笔者回去复习了下对象流的使用,给mypanel实现了可序列化接口spa

首先咱们须要让Recoder随时随地更新好mypanel,咱们给Recoder添加了静态mypanel对象,而后每进行一次repaint,就给该mypanel对象进行一次赋值更新,为了保证Recoder记录的是最新的mypanel.net

更新好了之后,咱们先作保存工做插件

public static void recoder() throws IOException {
       ObjectOutputStream op=new ObjectOutputStream(new FileOutputStream(path1));
       op.writeObject(all);
       op.close();
    }

为了方便和区分,咱们将游戏信息做为另外一个文件进行存储,创建对象流op进行写入,记住必定要close!(这里的all就是静态对象)线程

那么保存好之后,咱们就要作读取工做了,首先咱们要明白,何时读取?看源码咱们知道,mypanel的建立是在Tankgame,也就是主函数中调用的,咱们若是要进行上一局游戏,就得分不一样状况去建立这个mypanel,因而来到主函数

咱们默认mypanel是null的,若是该对象是null,那就说明还没开始游戏,那就直接new,若是对象不为null,那就说明该对象已是上一局游戏的了!

那咱们就须要读取mypanel了对吧?但读取以前得先让Recoder加载,因此要写一个加载方法

 public static void refunc() throws IOException, ClassNotFoundException {

        mypanel m=null;
        if(new File(path1).exists()) {
            ObjectInputStream oi=new ObjectInputStream(new FileInputStream(path1));
             m= (mypanel) oi.readObject();
        }
        all=m;
    }

将该文件读取出来,若是不存在,那么就直接赋值为null,存在就赋值为文件里的mypanel

主函数中:

public TankGame() throws IOException, ClassNotFoundException {
        Recoder.refunc();
        if(Recoder.getall()==null)
        {
            mp=new mypanel();
        }
        else
        {
            mp=Recoder.getall();
        }

调取函数以后,就正常让这个mp加入到咱们的画框里便可,可是,报错了,显示NotSe什么什么的,意思就是mp这个对象尚未实现序列化,但是不是已经添加了么?随后一看,是tank和shot还没添加,我添加了事后,仍是报错,最后仔细一看,发现咱们的爆炸图片还没序列化,但咱们总不能去源码那里给他加上去吧,这里,咱们能够新建一个Imagefortmp类,,再实行序列化,再将三个image添加到里边,改成静态对象,而后直接在mypanel类里调用便可,能够直接在该类中加载好图片,能解决有时候不出现爆炸图片的现象,在mypanel里添加也能够

这该类的代码

public class Imagefortmp  implements Serializable {
    static Image n1;
    static Image n2;
    static Image n3;

}

最后编译,发现能经过了,第二局游戏也确实是继续游戏,但有个奇怪的事,本身坦克能够动,敌方坦克和子弹却动不了?咱们仔细想一想,能够发现,新游戏的子弹和坦克的线程都是建立事后才开启的,换言之,你若是已经有了这两个了,线程得本身去开启,那么咱们就须要写一个函数,去遍历每个坦克和每个坦克子弹合集,分别给他们开启,固然本身坦克的线程是归属于Keylistener的,在主函数中开启的,这也就是为何咱们能够动的缘由 而后写好后在主函数,开启了mp线程后调用mp线程的该方法,

该方法代码

   public void startgame()
    {
        for(int i=0;i<Enemytanks.size();i++)
        {
            Enemytank e=Enemytanks.get(i);
            new Thread(e).start();
            for(int j=0;j<e.shots.size();j++)
            {
                Shot s=e.shots.get(j);
                new Thread(s).start();
            }
        }
        if(Hero.shot!=null&&Hero.shot.islive)
        {
            new Thread(Hero.shot).start();
        }
    }

而后第N次debug的时候,竟然直接报错了,显示InvalidClassException

我上网查了很久,最终获得缘由和解决方案,每一个对象流在保存的时候和读取的时候的序列号要同样,改变对象属性等操做会致使序列号发生改变,若是序列号不同,解码就解不出来,天然而然就会崩溃,而每一个类都有一个序列号,因为咱们只有一个mypanel对象,因此咱们须要指定好这个序列号,因而在mypanel下边添加这一句便可,可能大体意思解读的不太对,有兴趣的读者能够转到java.io.InvalidClassException异常解决_csdn565973850的博客-CSDN博客_java.io.invalidclassexceptionjava.io.InvalidClassException异常解决1.什么是serialVersionUID2.java.io.InvalidClassException产生缘由?3.java.io.InvalidClassException解决方案4.idea推荐插件1.什么是serialVersionUID       ...https://blog.csdn.net/csdn565973850/article/details/88977061

进行了解,

private static final long serialVersionUID=7981560250804078637l;

这样就能够保证序列号的统一

整体合成之后,再更新就无多大问题了,要想作到新游戏和继续游戏的话,能够在前端新增if语句进行输入判断,由玩家的输入进行选择,也能够新建一个画框,利用画框来让用户使用ASWD选择

代码写的很差,还请各位读者不惜赐教,如有代码错误之处,还请指出

感谢您的阅读。