Java视频来源:B站韩顺平教育
笔者在B站上看韩顺平老师的Java基础教程,到了坦克大战的阶段,基本的架构已经搞好
韩顺平老师这里为了巩固文件流基础,特地使用了文件的形式,保存分数和上局游戏状况
但老师用的是最简单的Fileoutput流来进行写入坦克的坐标,子弹坐标,各种类型等等,笔者看到这里不禁想到:这么复杂,用序列化的方法会不会更好一点呢?
我重新用IDEA的结构看了一下坦克大战的组成,发现其实就只有两大块
TankGame mypanel Recoder而Mypanel保存了坦克,保存了子弹,保存了爆炸情况
既然如此,我们可以使用对象流保存mypanel啊 于是笔者回去复习了下对象流的使用,给mypanel实现了可序列化接口
首先我们需要让Recoder随时随地更新好mypanel,我们给Recoder添加了静态mypanel对象,然后每进行一次repaint,就给该mypanel对象进行一次赋值更新,为了保证Recoder记录的是最新的mypanel
更新好了以后,我们先做保存工作
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
然后第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选择
代码写的不好,还请各位读者不惜赐教,若有代码错误之处,还请指出
感谢您的阅读。