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

(一)实现功能:

1.基础的成绩排序
2.相同成绩随机排名
3.用户名注册重复

(二)效果视频:

(三)代码实现:

3.1 && 3.2 在FileRead类中新增方法如下:

在这里插入图片描述

具体的代码实现:

package DemoProject.fjm0601.FileWandRSystem;import DemoProject.fjm0601.GameWD;import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Locale;public class FileRead {public static File file = new File("src/DemoProject/fjm0601/ScoreFile.txt");static FileReader fr;static BufferedReader bfr;//获取初始的绘制高度:static int y = 10;//最终画板采取的绘制方法:public static void RankOutCurrentBest(File file,Graphics graphics) throws IOException {try {fr= new FileReader(file);bfr  = new BufferedReader(fr);} catch (FileNotFoundException e) {throw new RuntimeException(e);}//获取字符串形式的成绩名单ArrayList<String> scoreList = getScoreList(bfr);System.out.println("此时的成绩名单为:"+scoreList);//获取先前查询过的最大值数组ArrayList<Integer> BScoreList = new ArrayList<>();int BScore;String [] NameArr;int CurrentNum = 0;while (true){//获取此时的最大成绩(除去先前已检查过的成绩)BScore = getBestScore(BScoreList,scoreList);System.out.println("此时最好成绩为:"+BScore);//获取成绩最大且相同的用户名数组NameArr = viaScoreToNameArr(BScore,scoreList);System.out.println("成绩相同的有"+NameArr.length+"个人");System.out.println("成绩最好的人为:"+NameArr[0]);//将BScore放入查询过的最大数组中:BScoreList.add(BScore);//将此时成绩最大的用户们成绩写出到面板中readFileOnRow(BScore,NameArr,graphics);System.out.println("此人的成绩已被写入");//将被录入成绩的人计入CurrentNum += getTheScoreNum(BScore,scoreList);System.out.println("此时被写入成绩的人有:"+CurrentNum);//当被录入成绩的人等于scoreList的大小,意味着所有人的成绩皆被录入if(CurrentNum == scoreList.size()){System.out.println("成绩已写入完毕");break;}y += 20;}}//将文件里面的成绩存储进入动态数组public static ArrayList<String> getScoreList(BufferedReader bfr) throws IOException {ArrayList<String> scoreList = new ArrayList<>();String strLine;while (true){if((strLine = bfr.readLine()) != null){scoreList.add(strLine);}else{break;}}return scoreList;}//获取此时最大的成绩public static int getBestScore(ArrayList<Integer> BScoreList,ArrayList<String> scoreList){int BScore = 0 ;System.out.println("scoreList的长度为:"+scoreList.size());LabelName:for(String perScore : scoreList){int score = Integer.valueOf(perScore.split(":")[1]);System.out.println("此时找到的成绩为:"+score);//将"这一个"用户的成绩与先前的成绩做对比,一旦发现相同则跳出内循环,进而检查下一个同学的成绩。for(int previousScore : BScoreList){if(score == previousScore){//一旦发现相同,则跳出内部循环并开启下一次循环System.out.println("找到的该成绩与先前一致,因此退出并进入下一次循环");continue LabelName;}}if(BScore < score){BScore = score;}}System.out.println("最终获取的最好成绩为:"+BScore);return BScore;}//获取具有该成绩的人数public static int getTheScoreNum(int Score, ArrayList<String> scoreList){int EachScore;int i = 0;for(String Each : scoreList){String [] EachArr = Each.split(":");EachScore = Integer.valueOf(EachArr[1]);if(EachScore == Score){i++;}}return i;}//将成绩按行写入面板中public static void readFileOnRow(int BScore, String [] NameArr,Graphics graphics){String condition1;int x = 10;int i = 0;graphics.setColor(Color.BLACK);while (true){System.out.println("进入此循环中");if(i < NameArr.length){condition1 = NameArr[i] + ": " +BScore;graphics.drawString(condition1,x,y);if(NameArr.length > 1 && i != NameArr.length-1){y += 20;}i++;}else{break;}}}//整合获取相同成绩的用户名数组public static String[] viaScoreToNameArr(int BScore, ArrayList<String> scoreList){int EachScore;int len = getLen(BScore,scoreList);String [] NameArr = new String[len];int i = 0;for(String Each : scoreList){String [] EachArr = Each.split(":");EachScore = Integer.valueOf(EachArr[1]);if(EachScore == BScore){NameArr[i] = EachArr[0];i++;}}return NameArr;}//获取用户名数组的长度public static int getLen(int BScore, ArrayList<String> scoreList){int EachScore;int len = 0;for(String Each : scoreList){EachScore = Integer.valueOf(Each.split(":")[1]);if(EachScore == BScore){len++;}}return len;}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);}}
由于需要考虑相同成绩的排名,因此不能简单获取成绩再排序,整体的实现思路如下
1.先获得此时的成绩单
2.创建一个死循环,在单次循环中:获取此时的最好成绩->依据最好成绩获取具有相同成绩的用户->按照用户 + 成绩的格式写到面板上。下次排序时,避开此次及先前排好的成绩记录并追加已排好的用户成绩,当排好所有用户后退出循环
3.3 在GameWD中的paint2()方法中修改按钮监听方法
实现提示框的添加

在这里插入图片描述

confirmBtn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {String name = jtf.getText();try {if(name == null){JOptionPane.showMessageDialog(null,"用户名不可为空");return;}if(scoreMap.containsKey(name)){JOptionPane.showMessageDialog(null,"该用户名已注册");return;}writeFile(name,Score);JOptionPane.showMessageDialog(null,"写入成功,祝您下次取得更好成绩");} catch (IOException ex) {throw new RuntimeException(ex);}}});
3.4 在RankPanel中替换成RankOutCurrentBest()方法
public class RankJPanel extends JPanel {public void paint(Graphics graphics){super.paint(graphics);File file = FileRead.file;try {FileRead.RankOutCurrentBest(file,graphics);} catch (IOException e) {throw new RuntimeException(e);}}
}

补充:

1.为排行榜加入柱状图
请添加图片描述
2.加入用户名规范
在这里插入图片描述

实现代码如下:

1.在readFileOnRow的方法的死循环中修改为下:
while (true){System.out.println("进入此循环中");if(i < NameArr.length){condition1 = NameArr[i] + ": ";double pillarLen = 0;graphics.drawString(condition1,x,y);if(BScore > 1000){pillarLen = BScore / 10.0;}else if( BScore < 100){pillarLen = BScore ;}graphics.fillRect(x + 90,y -7 , (int) pillarLen,5);graphics.drawString(BScore + "",x +(int)pillarLen  + 100,y);if(NameArr.length > 1 && i != NameArr.length-1){y += 20;}i++;}else{break;}}
注意:为避免成绩过长画出边界,对超高成绩的柱状图作压缩处理
2.在GameWD的按钮监听方法里面加入:
if(!name.matches("^[\u4e00-\u9fa5]{5}\\d{4}$")){JOptionPane.showMessageDialog(null,"用户名不规范,注册格式为:五个中文字符+四个数字");return;}
括号内的字符就是五个中文字符+四个数字的格式
3.小漏洞修复:反复点击排行榜,整体的成绩图会不断下滑。

原因:单次程序(整个飞机大战)运行后,每次点击排行榜,y值始终在增加
解决方法:在按钮监听器中新增 FileRead.y = 20; :
在这里插入图片描述
确保每次点击排行榜的y的初始值都为20

异常/遗漏修复:

(一)数组越界异常:
异常:每次拼接内容:
原因:用户 + 成绩的时候,数组调用在条件判断之前,
解决方法:将数组调用放在条件判断内
(二)排行榜上重复添加相同成绩用户且该用户成绩为0:
原因:使用新方法LabelName的时候,误用break LabelName,导致没有进入下一次的大循环反而直接掠过了整个循环。使得后续的成绩皆为此次成绩0
解决方法:将break LabelName改为continue LabelName
(三) 排行榜显示完后无法结束程序
原因:一开始简单认为退出死循环的条件为:
遍历到成绩为0的时候(实际上最低成绩可能不为0)
解决方法:修改退出循环条件为:排好序的人数达到成绩数组的长度(也就是所有人都排好序)即退出。
(四)排行榜上相同成绩的信息重叠在一块。
原因:相同成绩的人在写入时,没有改变y值
解决方法:当NameArr(也就是相同成绩的玩家)的长度大于1,且没有遍历到最后一人(防止其他成绩的用户在绘制时出现 ”空行“ 的问题),y += 20.
(五) 绘制的时候所有成绩全部画在一块
原因:绘制的y位置仅在方法调用时创建,每一次调用方法后都会创建新的y,致使y没有实时增加
解决方法:添加静态修饰符static,并将其提到全局变量的位置。

感悟:

在进行排序功能时,曾想过:先用哈希表存储各值,比较完值之后,反推回到键(也就是用户名),再进行拼接,失败。

原因: 哈希表没有通过值返回键的方法,也难以通过手动遍历哈希表获取键。
解决方法:通过使用String[]数组预先存储各人的 “用户:成绩” 信息。再通过split()方法获取[用户,成绩]格式的一维数组,最后比对成绩。间接达到二维数组的效果,实现用户与成绩的关系绑定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/94099.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/94099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React + Antd+TS 动态表单容器组件技术解析与实现

概述在现代前端应用中&#xff0c;表单是用户交互的核心部分。本文将深入分析一个基于 React 和 Ant Design 的高级动态表单容器组件&#xff0c;它提供了强大的可配置性、灵活的布局选项和丰富的功能扩展能力。组件核心特性1. 高度可配置的表单结构interface FormContainerPro…

51c自动驾驶~合集16

自己的原文哦~ https://blog.51cto.com/whaosoft/11739891 #CLIP系列模型如何补短板再升级 CLIP&#xff08;Contrastive Language–Image Pre-training&#xff09;模型自推出以来&#xff0c;在图像-文本跨模态理解和生成领域取得了显著成果。然而&#xff0c;经…

分级设色地图/标注式统计地图-中国地图绘制

分级设色地图/标注式统计地图‌1. 这种图长什么样&#xff1f;‌2. 核心应用场景‌3. 工具3.1 自己找数据3.2 智图小易司3.2 Flourish3.3 镝数图表注意事项当你看到一张中国地图&#xff0c;各省份颜色深浅不一&#xff0c;旁边还标注着具体数值时&#xff0c;这种图就是‌分级…

2025最新华为云国际版注册图文流程-不用绑定海外信用卡注册

说到华为云&#xff0c;很多人第一反应就是“大厂可靠、服务全”。确实&#xff0c;作为全球知名的云计算服务商&#xff0c;华为云在企业级项目和个人开发者中都挺受欢迎。今天我就带你一步一步走一遍华为云国际版的注册流程&#xff0c;让新手也能轻松上手。下面是最简单的注…

Android 人脸识别技术全解析

人脸识别作为生物识别技术的核心分支&#xff0c;已广泛应用于考勤打卡、身份验证、支付安全等场景。在 Android 平台&#xff0c;实现人脸识别需要兼顾准确性、实时性和设备兼容性三大挑战。本文将系统讲解 Android 人脸识别的技术选型、核心实现、性能优化及安全加固&#xf…

STM32项目分享:基于STM32单片机驾驶安全监测系统设计

“我们不做一锤子买卖&#xff0c;只做技术成长的长期伙伴&#xff01;” 目录 一、视频展示 二、项目简介 三、原理图设计 四、PCB硬件设计 五、程序设计 六、资料分享 一、视频展示 基于stm32单片机驾驶行为监测系统设计 -视频分享二、项目简介 题目&#xff1a;基于s…

【GaussDB】使用gdb定位GaussDB编译package报错

【GaussDB】使用gdb定位GaussDB编译package报错 背景 在某次迁移Oracle到GaussDB时&#xff0c;应用开发人员将改好的package在GaussDB里进行创建&#xff0c;没有ERROR也没有WARNING&#xff0c;但是编译无效对象的时候报错了。虽然已经找到了是哪个包编译报错&#xff0c;但…

One Commander:强大的Windows文件管理器

在日常使用电脑的过程中&#xff0c;文件管理和浏览是必不可少的任务。One Commander作为一款功能强大的Windows文件管理器&#xff0c;提供了丰富的功能和便捷的操作方式&#xff0c;帮助用户更高效地管理和浏览文件。它不仅支持多种文件操作&#xff0c;还提供了丰富的自定义…

SPUpDate Application 程序卸载

我安装了 EzvizStudioSetups.exe 软件&#xff0c;卸载后会在电脑遗留 SPUpDate Application 程序&#xff1b;在某一时刻会占用 CPU 资源&#xff1b;应用卸载方法一&#xff1a;在任务管理器搜索 SPUpDate Application&#xff1b;定位到文件位置&#xff1b;我的路径如下C:\…

算法题(187):程序自动分析

审题&#xff1a; 本题需要我们判断是否可以同时满足题目给定的若干等式或不等式&#xff0c;判断出后根据结果输出YES或NO 思路&#xff1a; 方法一&#xff1a;离散化并查集 使用并查集&#xff1a;其实题目中只存在两者相等或不等两种情况&#xff0c;而等于具有传递性&…

strcasecmp函数详解

strcasecmp 是 C 语言中用于不区分大小写比较两个字符串的函数&#xff0c;主要用于忽略字符大小写差异的场景&#xff08;如用户输入验证、不区分大小写的字符串匹配等&#xff09;。它属于 POSIX 标准库&#xff0c;定义在 <string.h> 头文件中。 一、函数原型与参数 函…

Voronoi图

本文将详细解释 Voronoi 图&#xff0c;它在空间分析和插值中非常常用。1. 概念 Voronoi 图是一种空间划分方法&#xff0c;它把平面&#xff08;或空间&#xff09;划分成若干个区域&#xff0c;使得每个区域内的任意一点都比该区域外的任何一点更靠近该区域的“生成点”&…

BioScientist Agent:用于药物重定位和作用机制解析的知识图谱增强型 LLM 生物医学代理技术报告

BioScientist Agent:用于药物重定位和作用机制解析的知识图谱增强型 LLM 生物医学代理技术报告 一、项目概述 药物研发是一个周期长、成本高的过程,平均需要超过 10 年时间和 20 亿美元才能将一种新药推向市场,且 90% 以上的候选药物最终失败(1)。这种低成功率主要归因于对…

5G视频终端详解 无人机图传 无线图传 便携式5G单兵图传

前言单兵图传设备&#xff0c;是一种集视频采集、编码压缩、无线传输等多种功能于一体的便携式通信终端。它以嵌入式系统为基础&#xff0c;搭载高性能 H.265 编解码处理器&#xff0c;能够将现场的音视频信息进行高效处理后&#xff0c;通过无线网络快速稳定地传输至后端指挥中…

【苹果软件】Prism Mac 9.4苹果系统免费安装包英文版 Graphpad Prism for Mac 9.4软件免费下载与详细图文教程!!

软件下载与系统要求 软件&#xff1a;Prism9.4 语言&#xff1a;英文 大小&#xff1a;103.41M 安装环境&#xff1a;MacOS12.0&#xff08;或更高&#xff0c;支持IntelM芯片&#xff09; MacOS苹果系统GraphPad Prism&#xff08;科学数据分析与图形绘制&#xff09;&am…

Redis 奇葩问题

先贴错误码Unexpected exception while processing command这个奇葩的问题查了很久&#xff0c;后面突然顿悟&#xff0c;应该是Redis记住了第一次的数据类型&#xff0c;后面即使换了数据类型也不会改变之前的数据类型。跟代码发现是codec变成了默认的了后续public RedissonBa…

C ++代码学习笔记(一)

1、GetStringUTFChars用于将 Java 字符串&#xff08;jstring&#xff09;转换为 UTF-8 编码的 C 风格字符串&#xff08;const char*&#xff09;。必须在使用完后调用 ReleaseStringUTFChars 释放内存&#xff0c;否则可能导致内存泄漏。std::string data_converter::convert…

【学习嵌入式day-29-网络】

进程和线程的区别&#xff1a;都是系统执行的任务进程是资源分配的基本单位线程是调度执行的最小单位进程的创建和切换的开销大&#xff0c;速度慢&#xff0c;效率低空间独立、----- 安全&#xff0c;稳定进程间通信不方便线程创建和切换的开销小&#xff0c;速度快&#xff0…

Eino 框架组件协作指南 - 以“智能图书馆建设手册”方式理解

Eino 框架组件关系 - 形象比喻指南 &#x1f3d7;️ 项目概览&#xff1a;构建一个智能图书馆 想象一下&#xff0c;你要建设一个现代化的智能图书馆&#xff0c;能够帮助用户快速找到所需信息并提供智能问答服务。Eino 框架就像是这个智能图书馆的建设工具包&#xff0c;每个组…

网络打印机自动化部署脚本

下面是一个全面的、交互式的PowerShell脚本&#xff0c;用于自动化网络打印机部署过程。这个脚本提供了图形化界面&#xff0c;让用户可以轻松地搜索、选择和安装网络打印机。 备注&#xff1a;这个脚本未在生产环境测试过&#xff0c;请大家测试一下&#xff0c;有问题或优化&…