当前位置: 首页 > news >正文

多线程—飞机大战(加入排行榜功能版本)

读者须知:

飞机大战基本功能代码在项目历程专栏中,这里仅展示排行榜功能如何添加

效果视频:

飞机大战排行榜功能添加

代码实现:

(一)创建文件的读写方法类:

1.1 创建 “写入” 方法类:

package DemoProject.fjm0601.FileWandRSystem;import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;public class FileWrite {public static File file = new File("src/DemoProject/fjm0601/ScoreFile.txt");public static FileWriter fw;public static BufferedWriter bfw;//在方法外使用try-catch结构必须要构造静态代码块static {try {fw = new FileWriter(file,true);bfw = new BufferedWriter(fw);} catch (IOException e) {throw new RuntimeException(e);}}public static void writeName(String name){try {bfw.write(name + ":");bfw.flush();} catch (IOException e) {throw new RuntimeException(e);}}public static void writeScore(int score){try {bfw.write(score + "\n");bfw.flush();} catch (IOException e) {throw new RuntimeException(e);}}public static void readName(){}public static void readScore(){}public static void clear(){}public static void main(String[] args) {writeName("樊佳明");writeScore(100);writeName("樊佳明");writeScore(100);}
}

1.2 创建文件的读取方法类:

实现效果如下:

在调用读取方法时,可在面板上按行将成绩库数据绘制出
package DemoProject.fjm0601.FileWandRSystem;import javax.swing.*;
import java.awt.*;
import java.io.*;public class FileRead {public static File file = new File("src/DemoProject/fjm0601/ScoreFile.txt");public static void readFileOnRow(File file, Graphics graphics){BufferedReader bfr;try {FileReader fr  = new FileReader(file);bfr  = new BufferedReader(fr);} catch (FileNotFoundException e) {throw new RuntimeException(e);}try {String condition1;int x = 10;int y = 10;while (true){if((condition1 = bfr.readLine()) != null){graphics.setColor(Color.BLACK);graphics.drawString(condition1,x,y+=20);}else{break;}}} catch (IOException e) {throw new RuntimeException(e);}}//    public static void main(String[] args) {
//       JFrame jFrame = new JFrame();
//        jFrame.setSize(400,400);
//        jFrame.setLocationRelativeTo(null);
//        JPanel jPanel = new JPanel();
//        jFrame.add(jPanel);
//        jFrame.setVisible(true);//        Graphics graphics = jPanel.getGraphics();
//        readFileOnRow(file,graphics);
//    }}

(二)创建成绩库—txt格式:

2.1 创建ScoreFile.txt文件

在这里插入图片描述

2.2

1.在主函数中将原先的状态2的绘制过程单独封装成一个函数paint2()
2.移除“重新开始游戏”按钮,并添加文本输入框和确定按钮
3.增加绘制“查看排行榜”,并给其添加鼠标监听器。

实现效果如下:

1.玩家死亡后,在输入框中输入名字,点击“确定”,玩家的名字和成绩会被写入成绩库中
2.一旦按下“查看排行榜”,则绘制出附带了成绩排行的窗口
3.如果反复点击“查看排行榜”,则移除先前的排行榜再重新生成,避免反复创建难以去除
    public void showUI(){addMouseMotionListener(ml1);objectList.add(bgObj);objectList.add(planeObj);setTitle("飞机大战");setLayout(new BorderLayout());setSize(600,800);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLocationRelativeTo(null);setVisible(true);while (true){enemyPlanex=(int)(Math.random()*9)*60;if(state == 1){if(flushCount % 20 == 0){createEnemyPlaneObj();}if(bopObj == null){createBossPlaneObj();}if(planeObj != null  && flushCount % n == 0){createShellObj();}if(bopObj != null  && flushCount % 20 == 0){createBossShellObj();}}repaint();try {Thread.sleep(30);} catch (InterruptedException e) {throw new RuntimeException(e);}flushCount++;if(state == 2){break;}}paint2(this);}public void paint(Graphics g){setIgnoreRepaint(true);BaseBoard=createImage(getWidth(),getHeight());//creatImage()这个方法返回的是VolatileImage对象或者是未初始化的Image,很有可能会丢失,所以这不稳定Graphics gImage=BaseBoard.getGraphics();if(state==0){gImage.drawImage(DemoProject.fjm0601.GameWDUtils.bgObj,0,0,null);paint0(gImage,this);}else if(state==1){if(isPlay == false){thBack.start();System.out.println("此处可再次运行");isPlay = true;}objectList.removeAll(removeList);removeList.clear();objectList.addAll(addList);addList.clear();for(GameObj object:objectList){object.paintSelf(gImage);}gImage.setColor(Color.CYAN);gImage.setFont(new Font("幼圆",Font.BOLD,20));gImage.drawString("获得分数"+" "+Score,30,70);}g.drawImage(BaseBoard,0,0,null);}public void createEnemyPlaneObj(){DemoProject.fjm0601.EnemyPlaneObj enemyPlaneObj=new EnemyPlaneObj(DemoProject.fjm0601.GameWDUtils.EnemyPlanetObj,enemyPlanex,0,60,42,5,this);objectList.add(enemyPlaneObj);}public  void createShellObj(){if(AddShellCount==0){DemoProject.fjm0601.ShellObj shellObj=new DemoProject.fjm0601.ShellObj(DemoProject.fjm0601.GameWDUtils.SelfBulletObj,planeObj.x+12,planeObj.y-1,10,9,5,this);objectList.add(shellObj);}else if(AddShellCount==1){DemoProject.fjm0601.ShellObj shellObj=new DemoProject.fjm0601.ShellObj(DemoProject.fjm0601.GameWDUtils.SelfBulletObj,planeObj.x+6,planeObj.y-1,10,9,5,this);objectList.add(shellObj);DemoProject.fjm0601.ShellObj shellObj1=new DemoProject.fjm0601.ShellObj(DemoProject.fjm0601.GameWDUtils.SelfBulletObj,planeObj.x+18,planeObj.y-1,10,9,5,this);objectList.add(shellObj1);}else if(AddShellCount==2){DemoProject.fjm0601.ShellObj shellObj=new DemoProject.fjm0601.ShellObj(DemoProject.fjm0601.GameWDUtils.SelfBulletObj,planeObj.x+1,planeObj.y-1,10,9,5,this);objectList.add(shellObj);DemoProject.fjm0601.ShellObj shellObj1=new DemoProject.fjm0601.ShellObj(DemoProject.fjm0601.GameWDUtils.SelfBulletObj,planeObj.x+12,planeObj.y-1,10,9,5,this);objectList.add(shellObj1);DemoProject.fjm0601.ShellObj shellObj2=new DemoProject.fjm0601.ShellObj(DemoProject.fjm0601.GameWDUtils.SelfBulletObj,planeObj.x+23,planeObj.y-1,10,9,5,this);objectList.add(shellObj2);}}public  void createBossShellObj(){BossShellObj shellObj=new BossShellObj(DemoProject.fjm0601.GameWDUtils.BossBulletObj,bopObj.x+bopObj.width/2,bopObj.y+bopObj.height,13,12,5,this);objectList.add(shellObj);}public  void createBossPlaneObj(){int bossX=(int)(Math.random()*425);if(boss1or2==1){bopObj=new BossPLaneObj(DemoProject.fjm0601.GameWDUtils.bossPlane1Obj,bossX,20,139,104,5,this);objectList.add(bopObj);boss1or2=2;}else if(boss1or2==2){bopObj=new BossPLaneObj(DemoProject.fjm0601.GameWDUtils.bossPlane2Obj,bossX,20,172,129,5,this);objectList.add(bopObj);boss1or2=1;}}public static void paint2(GameWD gm){isPlay = false;//线程在这里死亡,无法重生(start)thBack.interrupt();ThreadMusic.stopBk();//仅仅使用interrupted是无法使用阻断player的play方法的,因为play听不见interrupted方法。//thBack.interrupt();thBack = new Thread() {public void run() {try {ThreadMusic.playerBack = new Player(new FileInputStream(FileMusic.fileBack));ThreadMusic.playerBack.play();//player关闭后不可重置和线程一样都只有一次生命} catch (JavaLayerException e) {throw new RuntimeException(e);} catch (FileNotFoundException e) {throw new RuntimeException(e);}}};Graphics gImage = gm.getGraphics();gImage.setColor(Color.BLACK);gImage.fillRect(0,0,gm.getWidth(),gm.getHeight());gImage.setColor(Color.RED);gImage.setFont(new Font("幼圆",Font.BOLD,40));gImage.drawString("Game Over",200,200);gImage.setColor(Color.CYAN);gImage.drawString("查看排行榜",200,580);//        restartBtn.setBounds(190,230,200,40);
//        restartBtn.addActionListener(new ActionListener() {
//            @Override
//            public void actionPerformed(ActionEvent e) {
//                String str=e.getActionCommand();
//                if(str.equals("重新开始游戏")){
//                    gm.state=1;
//                    gm.remove(restartBtn);
//                }
//            }
//        });
//        gm.add(restartBtn);//创建文本输入框和确定按钮JTextField jtf = new JTextField();gImage.setFont(new Font("幼圆",Font.BOLD,40));gImage.setColor(Color.WHITE);//drawString的y是字符的底部y坐标gImage.drawString("请点击下方,输入您的姓名",50,400);//JTextField的y是文本输入框顶部的y坐标jtf.setBounds(150,400,300,25);JButton confirmBtn = new JButton("确定");confirmBtn.setBounds(240,435,100,40);confirmBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String name = jtf.getText();try {writeFile(name,Score);} catch (IOException ex) {throw new RuntimeException(ex);}}});gm.add(jtf);gm.add(confirmBtn);JFrame[] jFrame = new JFrame[1];int[] currentTimes = {0};int[] previousTimes = {0};gm.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {super.mouseClicked(e);int x = e.getX();int y = e.getY();createRankJf(x,y,currentTimes,previousTimes, jFrame);}});//创建查看排行榜图片://gImage.drawImage(GameWDUtils.RankObj,200,480, null);}public static void writeFile(String name,int score) throws IOException {FileWrite.writeName(name);FileWrite.writeScore(score);}public static void createRankJf(int x,int y,int[] currentTimes,int[] previousTimes,JFrame[] jFrame){if(x > 200 && x < 400 && y > 540 && y < 580){currentTimes[0]++;if(currentTimes[0] > previousTimes[0] && currentTimes[0] != 1){jFrame[0].dispose();}jFrame[0] = new JFrame("排行榜");jFrame[0].setSize(485,600);jFrame[0].setLocation(1055,10);RankJPanel jPanel = new RankJPanel();jFrame[0].add(jPanel);jFrame[0].setVisible(true);previousTimes[0] = currentTimes[0];}}

(三)创建RankJPanel类:

解决:点击“查看排行榜”后,获取面板的画笔但是无法绘制出成绩的问题
解决原理:在可视化的时候就初始化好面板本身(附加好成绩)
package DemoProject.MyTools;import DemoProject.fjm0601.FileWandRSystem.FileRead;import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.Random;public class RankJPanel extends JPanel {public void paint(Graphics graphics){super.paint(graphics);File file = FileRead.file;FileRead.readFileOnRow(file,graphics);}
}

至此,可初步实现在排行榜上绘制出成绩的效果。

异常处理及感悟:

1.尽管通过FileInputStream 、FileOutputStream可以实现一定程度的上的完整读写,但在功能的简便性和丰富性上不如FileWriter 、FileReader。例如读取整形数据和字符串时,分别需要不断右移8位以凑取四个字节,得到字符串的具体长度以用byte数组容纳。以及不能像FileReader那样按行读取数据
2.在方法和主函数外使用try-catch结构时,需要使用静态代码块,在通过类名调用变量或方法时一会一并调用(静态代码块)
3.readLine()方法读取一行后,会把读取位置移到下一行开头
4.调用完write()方法后,必须立即flush(),不然写不进去
5.添加鼠标监听器的时候,在MouseClicked的重写方法中,需要通过数组操作数据,而不能直接操作数据本身
6.为了解决窗口不能正常显示成绩的问题,使用“特制”的面板,使得在可视化的时候就能绘制出成绩,这和先前的AI五子棋预先绘制出棋盘是一样的道理
7.在主函数线程中,在界面可视化后,可以正常绘制的只有drawString()方法,无法添加标签, 以及绘制图片

未解决的异常:

不使用“特制”面板,而在新建的窗口可视化之后,调用面板的画笔,然后将画笔传入readFileOnRow()方法中,进行绘制,结果绘制不出,笔者目前暂未解决。

http://www.dtcms.com/a/336153.html

相关文章:

  • 数字化转型成功案例:赋能供应链运输成本精细化管理
  • 网络编程3(网络层,数据链路层)
  • 批次号规则
  • Vue中v-show与v-if的区别
  • 【AI论文】序曲(PRELUDE):一项旨在考察对长文本语境进行全局理解与推理能力的基准测试
  • C语言私人学习笔记分享
  • STM32单片机学习日记
  • 第四章:大模型(LLM)】06.langchain原理-(7)LangChain 输出解析器(Output Parser)
  • 模型提取的相关经验
  • 库制作与原理(下)
  • 端到端测试:复杂系统的终极体检术
  • 【C2000】德州仪器C2000产品开发板的原理图如何找到?
  • 反向代理、负载均衡器与API网关选型决策
  • 《MutationObserver深度解构:重塑自动化视觉回归测试的底层逻辑》
  • B站 韩顺平 笔记 (Day 21)
  • [python学习记录2]变量
  • 【Unity3D实例-功能-拔枪】角色拔枪(二)分割上身和下身
  • vue封装请求拦截器 响应拦截器
  • 定时器输出PWM波配置(呼吸灯)
  • 平行双目视觉-动手学计算机视觉18
  • C++ Building Blocks 构建块 Or 构件块
  • SVN客户端下载与安装
  • 「数据获取」《中国教育统计年鉴》(1949-2023)(获取方式看绑定的资源)
  • 【嵌入式基础知识梳理#11】Modbus-RTU工业总线协议
  • Spring IOC 学习笔记
  • Canny边缘检测
  • Python异步编程实战:爬虫案例
  • 【Python】-- 机器学习项目 - 基于KNN算法的鸢尾花分类
  • 【自动化运维神器Ansible】Playbook中的when条件判断:精细化控制任务执行
  • 【Linux系列】常见查看服务器 IP 的方法