首页 > 其他分享 >题目集4-1-2总结

题目集4-1-2总结

时间:2024-06-06 21:00:53浏览次数:15  
标签:总结 题目 get 适配器 answer0 电路 line LinkedHashMap

  1. 前言

  2. 设计与分析
    2.1 第四次迭代设计与分析
    2.2 第一次电路程序
    2.3 第二次电路程序

  3. 踩坑心得

  4. 踩坑心得

  5. 改进建议

  6. 总结

前言

这三次程序的编写与之前的略有不同,第四次程序编写是由前三次程序迭代而来,在拥有两次编写迭代程序的经历后,第四次的程序编写并没有耗费我太多时间。其新增加的知识点,如继承,多态等较容易理解并使用。在有两个晚上的设计后,于第三天晚上完成了第四次题目集的新需求。之后的题目集是更换了新的题目类型,不过并没有从头开始,其知识点依然延续着原本的知识框架。
下面简单介绍我在这三次程序编写中所用的知识点。包括:
数据结构 ,字符串处理 , 控制流程 , 异常处理 , 分数计算与判断逻辑 , 排序算法 , 模块化编程 , 正则表达式 , 继承与多态,接口实现等。这些知识说起来简单但真正用在题目数据中学生信息的提取,标准答案与学生答案的对比,匹配错误的判断却需要脑中有一个完整的设计思路以及能真正实现想法的编程能力。各次迭代的题目具有相当的难度,包括完成数据处理的准确等是真正需要花时间来完成的,当然题量与时间也控制的很好,以至于我不得不去花大量的课下时间去完成。




设计与分析

第四次迭代设计与分析

对于题目集四其中的多选题以及填空题,其原本与普通的题目没啥不同,只是对于答案的判断对错的判断要求有所改变而已,因此在此泛化题目类,并各自构造他们的得分判断方法。


1.多选题判断方法:

点击查看代码
public  void judge_Z(Question_Z q,Answer answer0){
        String[] q_standers = q.getStander_answer().split(" ");
        String[] studentAnswers = answer0.An_information.split(" ");
        int correctCount = 0;
        int incorrectCount = 0;
        for(String s:studentAnswers){
            if(q.getStander_answer().contains(s)){
                correctCount++;
            }
            else{
                incorrectCount++;
            }
        }
        if (incorrectCount == 0 && correctCount == q_standers.length) {
            answer0.setScore(q.getScores());
            answer0.setCondition("true");
        }// if all correct set full
        else if(incorrectCount==0&&correctCount>0){
            answer0.setScore(q.getScores()/2);
            answer0.setCondition("partially correct");
        }
        else {
            answer0.setScore(0);
            answer0.setCondition("false");
        }

    }
2.填空题判断方法:
点击查看代码
 public  void judge_K(Question q,Answer answer0){
        String[] q_standers = q.getStander_answer().split("或");
        String[] studentAnswers = answer0.An_information.split("或");
        int correctCount = 0;
        int incorrectCount = 0;
        for(String s:studentAnswers){
            if(q.getStander_answer().contains(s)){
                correctCount++;
            }
            else{
                incorrectCount++;
            }
        }
        if (incorrectCount == 0 && correctCount == q_standers.length) {
            answer0.setScore(q.getScores());
            answer0.setCondition("true");
        }// if all correct set full
        else if(incorrectCount==0&&correctCount>0){
            answer0.setScore(q.getScores()/2);
            answer0.setCondition("partially correct");
        }
        else {
            answer0.setScore(0);
            answer0.setCondition("false");
        }

    }
3.对于输入顺序的变化,了解到各数据其实都有编号相对应,所以将每一行(代表一类数据)存入列表中最后根据编号相对应匹配处理数据。
点击查看代码
 while (true) {
            line_get = scan.nextLine();
            if(!inter_face.check_format(line_get)){continue;}

            if (Objects.equals(line_get, "end")) {
                break;
            } else if (line_get.contains("#N:")||line_get.contains("#Z:")||line_get.contains("#K:")) {
                Controller.input_queslist(depot0, line_get,paper_list);//题库

            } else if (line_get.contains("#T:")) {
                Controller.input_text(paper0, line_get, depot0);
                Paper paper_new = (Paper) paper0.clone();
                paper_list.add(paper_new);
                paper0 = new Paper();
            } else if (line_get.contains("#S:")) {
                Controller.input_script(script0, line_get);

                Script script_new = (Script) script0.clone();
                script_list.add(script_new);
                script0 = new Script();
            } else if (line_get.contains("#X:")) {
                Controller.input_X(student0, line_get, student_list);
            } else if (line_get.contains("#D:")) {
                Pattern pattern = Pattern.compile("N-(-?\\d+)");
                Matcher f = pattern.matcher(line_get);
                if (f.find()) {
                    delete.setX(Integer.parseInt(f.group(1)));
                    delete.delete_q(depot0, paper_list);
                }
            }

        }
以下是对题目集四的设计初级思路,于草稿纸上呈现

试卷程序迭代4类图:

第一次电路程序

  1. 程序的初始设计首先是对实体对象的设计,比较各实体对象的性质很清楚的发现所有对象都有相似的属性,而往下又可分为控制类,受控类,二者又可往下细分,可以看出这是一个十分明显的继承结构,以下是设计的初稿:

2.完成实体类的编写之后就需要了解其运行逻辑,此次计算各用电器电压时是运用了电位的相关知识,但这样的计算并没有很好的表现出电路,电器的性质,在整体看来兼容性依旧不强。以至于的迭代二时,基本的迭代而我却需要去修改程序的基础处理逻辑,导致迭代二的改变较大,十分消耗时间。以此看来,一个好的程序结构,不仅要很好的实现七大原则,包括单一职责,更重要的是职责的正确表现,能够准确,正确的编写模拟对象的各个性质,能有一个兼容性较强的处理逻辑。
数据的输入格式最后完成数据的输出,这里用一个电路类模拟电路并存储各个实体对象及依赖所有电器,整个的程序结构为输入,处理,输出。我总结前面迭代的经验,对程序的各部分功能尽力执行单一职责,为此实现代码的模块化L:

以下是对整个电路程序的基本设计思路分析:
类结构设计:
Electric 类作为基类,定义了所有电子元件共有的属性和方法,如电位、状态、日期等,并实现了Comparable接口用于排序。
Control 类继承自 Electric,代表具有控制功能的元件。
具体元件类(如 Switches, Bin_governor, Con_governor, Lamp_R, Lamp_B, Fan_D)继承自 Electric 或 Control,实现各自的特有属性和行为,如开关状态、亮度计算、速度调整等。
Appliance 类代表受控装置,如灯、风扇等,继承自 Electric。
电路构建与管理:
Circuit 类代表一条串联电路,使用 LinkedHashMap 存储电路中的元件,实现了元件之间的连接逻辑,以及检查电路中开关状态对其他元件的影响。
Controller 类负责解析输入,根据输入创建并添加电子元件到电路中,同时处理控制指令,如开关切换、调节器档位调整等。
用户界面:
Interface 类提供了打印电路中各类型元件状态的功能,通过遍历电路中的元件并按类型分类后输出。
主逻辑:
Main 类中包含了程序的主入口,通过 Scanner 获取用户输入,逐步构建电路、设置控制指令,最后输出电路中所有元件的状态。
输入处理:
用户通过特定格式的字符串输入来定义电路结构(如元件连接关系)和控制指令(如调节器的增减档、设定灯泡亮度等)。
输入解析逻辑在 Controller 类的 factor 和 set_controlling 方法中实现,分别处理元件初始化和控制指令。
输出展示:
程序根据电路中元件的实际状态,通过 Interface 类的方法组织并打印输出,展示了每种类型元件的状态信息。
整体上,该程序通过面向对象的设计方法,将复杂的电路系统抽象为一系列相互关联的对象,通过输入解析、逻辑处理、状态更新和结果输出几个关键步骤,实现了对电子电路的模拟和控制。

第二次电路程序:

此前的依靠电位来计算各个用电器电压的方法较为复杂,在经过一定的思考以及提前设计假设的情况下,我改变了电压的计算思路,通过整体到局部再到整体的思路,采用嵌套的对象存储格式,当然这也是题目中提示的,电路中包含用电器,控制器 ,电路。


1.首先应对输入格式的更改,由于这几次的任务并没有明显的可以用到课堂上学到的各种模式,因此想在这里将课堂上学到的适配器模式运用进去,发现通过对输入数据存储类Contraller使用适配器模式十分贴合,能很好的简化迭代的更新操作,这里运用的是将原Contraller类作为新的数据存储适配器类的里的引用即关联关系 ,以此达到调用原数据输入存储类中方法的作用。当然总的来说是通过对需要适配方法的抽象及重写。
相关操作:

点击查看代码
  interface Target {//适配目标
   void factor(LinkedHashMap<String,Electric> Ele_Map,String line,LinkedHashMap<String,Circuit> circuit_all);
   void set_controlling(LinkedHashMap<String,Electric> Ele_Map,String line);
   void set_controls(LinkedHashMap<String,Electric> Ele_Map,LinkedHashMap<String,Electric> controls );
   }

class Controller_Adapter  implements  Target{//适配的输入类
       public  Controller_Adapter(){}
       private Controller  controller = new Controller();

    public Circuit the_last(LinkedHashMap<String,Circuit> circuit_all){
        Circuit circuit = null;
        for(Map.Entry<String,Circuit> entry:circuit_all.entrySet()){
            circuit = entry.getValue();
        }
        return  circuit;
    }
       @Override
       public void set_controls(LinkedHashMap<String,Electric> Ele_Map,LinkedHashMap<String,Electric> controls ){
            for(Map.Entry<String,Electric> entry:Ele_Map.entrySet()){
                if(entry.getValue() instanceof Control){
                    controls.put(entry.getKey(),entry.getValue());
                }
            }
       }// 存储所有的控制设备 并且形成双向绑定 controls 与 circuit_whole中的控制设备
       @Override
    public  void factor(LinkedHashMap<String,Electric> Ele_Map,String line,LinkedHashMap<String,Circuit> circuit_all){
           Pattern pattern = Pattern.compile("\\[.*?]");
           Matcher m = pattern.matcher(line);
           while(m.find()){
               controller.factor(Ele_Map,m.group(),circuit_all);
           }
    }//创建对象
另外的是对计算逻辑的更改,因为此程序模拟的对象更为具体且十分贴合实际的物理模型,所以,我首先绘制了某种情况的电路图作为参考:

其中对所有控制器另外存储于一个列表以便之后的控制器信息输入,
// 第二次目前改动:
// 1 添加了Fan_A类
// 2 泛化Circuit 分为 1并联电路 2串联电路 Circuit :父类中的属性 Map 可存储包含 控制装置 受控装置 电路等 对象
// 3 转移电路类中的linking(连接) check_circuit_K(检查电路开关)方法 至 Controller 类中
// 4 添加适配器 Controller_Adapter 对应接口 Target 其中已对factor方法适配
// 5 Main 中原本的电路变量 circuit 改为 circuit_all
// 6 更改电压计算方法 ,明白对于断路的电路整个电路的电阻是无穷大,就此对电路对象的电阻进行计算
电路第二次迭代的类图


代码细节雷达图:

踩坑心得

1.对于构造父类的引用以及子类的实例

多态性和类型转换: 使用子类对象作为父类类型的引用时,如果尝试调用只有子类才有的方法,会导致运行时错误。 ——在使用子类特有的方法而在列表存储,构造对象,传参,使用增强for循环时,都会使该对象的类型被视为父类从而在调用子类特有的方法时调用错误: 如果将父类对象强制转换为子类类型,可能会触发未检查的转换异常。 对此有两种应对方法保证调用的是子类的方法; 1.在父类中编写该方法并且在子类中进行重写,但是这是针对各子类有部分相似部分不同的方法从而由父类构造而在子类中重写。 2.运用instanceof进行对象实例的判断,但是这样较繁琐。 对此,可以调整以下我们的属性的结构,因为所有的对象最终都要输出参数,并且可将参数统一为字符串,所以单独写一个获取数据的方法作为获取对象需要输出的参数,这样只需要在子类中重写getDate:并且在子类中调用子类特殊的方法,就可以实现多态性:

2.实型数转换成字符串类型并将其化整有不同情况


对于return String.format("%.0f",getSpeed()); 其会将6.66转化为7
对于return Integer.toString((int) getSpeed());其会将6.66转化为6

改进建议

1.各方法的功能未实现单一职责,导致结构不够清晰,各个类之间的耦合性较强,对此,我将在之后的迭代中将相关方法进行分解,以达到实现代码的模块化。


2.其中有大量方法具有相似且重复的功能,例如其中对于数据的存储以及输出,因局限于类型的转换中而无法简化,其后会将相应的判断转化为整体的判断,并且以各个对象的属性作为输出数据,而不是像现在这样根据判断自行输出编写好的数据,这样会使程序的健壮性以及兼容性大大受损。



3.对数据的处理不局限于特定的字符判断而升为对一类的字符判断,比如对空格之间的分割,采用\s+作为替代单个空格,由于我的输入是在原有的基础上进行适配的,所以原方法的改动较少,
这里因该减少对数据的破坏,以尽量一个字符串代表一种的数据的方式去提取。

总结

理解事先设计并且清晰需求(题目要求)的重要性
编程能力一定是建立在具有优秀的判断和理解需求的基础上的,如果无法正确的理解客户(甲方)的需求,再好的设计,再好的编程思想的体现都是做无用之功,此次对于电路程序的基础逻辑的判断,我一开始仅仅局限于对各个对象的操作而不去注重于他们之间的联系。一开始接触这样的题型,自己的思路无疑是一片混乱,但经历过这么多次的迭代程序的编写,我已经了解到,这不是一个小的所谓题目,更多的应该把它当作一个项目,工程一样去看待。而工程从来都不是一蹴而就的,应该一遍一遍的去了解要求,去解析各处的细节,去考虑各种的情况,先完成最基础的部分,比如实体类的编写。完成这些之后,我所要做的也逐步清晰起来,这时在脑中形成一个较完整的框架,这样的框架不是细致复杂的,而是有体系,各处结构分明的。我的基本体系很简单:输入->处理 ->输出.有了基本的框架与设计,在写代码时才不会混乱,才知道自己写的是什么,在整个程序中承担了什么作用.

------------------------- **适配器模式的使用**

适配器模式在进行代码功能的增加,修改,有着很大的用处,在此处使用适配器模式我竟觉得十分贴合.关于适配器模式的定义是这样的:
适配器模式(Adapter Pattern)是一种结构型设计模式,用于使原本不兼容的接口能够协同工作。适配器模式通常用于以下情况:
1.当系统中的一个类需要与另一个类(接口)协作,但是它们的接口不兼容时可以使用适配器模式。适配器模式允许两者能够协同工作。
2.当想要在不修改现有类的情况下使用一个类时,可以创建一个适配器,将新类的接口转换成现有类的接口。
此前我的代码还没有运用太多的接口,对于这次的适配是为a.原控制类抽象一个接口,再将构造适配器去关联原类作为其成员变量,进而适配接口中的抽象方法.
另一种使用方法是b.继承原来的方法,可采用super来调用原(父类的方法).
使用步骤:

  • 定义目标接口(Target Interface): 创建一个客户端期望的接口,这个接口声明了客户端需要使用的操作。
  • 创建适配者类(Adaptee Class): 这是已存在的类,拥有特定的功能,但是接口不符合客户端的需要。
  • 创建适配器类(Adapter Class):
  • 类适配器方式:通过继承适配者类,并实现目标接口。
  • 对象适配器方式:持有适配者类的实例,同时实现目标接口,通过委托调用适配者类的方法。
  • 客户端代码调用: 客户端不再直接调用适配者类,而是通过适配器来调用,这样就实现了接口的转换,使得原本不兼容的接口可以协同工作。
-------------------------

** LinkedHashMap列表的使用以及性质: **
LinkedHashMap 是 Java 中的一个 Map 实现,它继承自 HashMap 并实现了 Map 接口。LinkedHashMap 有以下主要特点和性质:

  • 插入顺序保持:
    默认情况下,LinkedHashMap 会按照元素的插入顺序来维护其内部的顺序。当你遍历这个映射时,元素会被按照它们被插入到映射中的顺序返回。
  • 访问顺序保持:
    如果在构造 LinkedHashMap 时设置 accessOrder 参数为 true,那么它将按照元素的访问顺序(即最近被访问过的元素会被移动到链表尾部)来维护顺序。这可以用于实现 LRU(Least Recently Used)缓存策略。
  • 遍历性能:
    由于内部使用了双向链表,LinkedHashMap 在遍历时比标准的 HashMap 更具有一致性,因为顺序是确定的。
在之后的学习之中我更需要脚踏实地,慢慢的去理解算法,结合实际,运用物理知识,生活常识去完善项目工程. 希望以后课程能更多的把体系呈现出来,能介绍前沿的,跟进时代的知识.

标签:总结,题目,get,适配器,answer0,电路,line,LinkedHashMap
From: https://www.cnblogs.com/harbor-0/p/18229796

相关文章

  • 题目集4-6次总结
    一、前言从大一下学期开始学习Java,到现在接近尾声,已经过去了差不多有三个月,我学习到了很多,对于利用Java语言进行程序的编写也更加熟练,但经过六次的pta大作业,仍让我意识到了我还有许多不足,需要进行改进,以下是我对于题目集4到6次的作业的总结。知识点:三次题目集考察的知识点主......
  • 第二次blog总结
    一、前言:第四次pta作业:1.知识点:考察类的继承,抽象类的使用。2.题量:3道简单题,1道迭代难题。3.难度:这次最后一道题在上次的基础上添加了题目的种类(eg:选择题、填空题)等,难度增加的还行,不算太难也不算太容易。第五次pta作业:1.知识点:考察类实现Comparable接口,重写compareTo......
  • LVGL(二)切换页面,同时清理内存,异常总结之动画删除
    项目场景:LVGL切换页面时,出现异常问题的总结。这里假设有2个页面,一个页面是启动页面,一个是密码盘页面。都有几十个部件,包含样式,动画,事件等。使用squareline生成代码。两个页面中都有一个按钮可以互相切换到另外一个页面。作者已经运行测试过了,切换页面,同时清除内存,再也没有......
  • 题目集4~6的总结性Blog
    4~6次大作业总结前言在题目的开始设计好类和结构真的很重要,之前一直上来就开始写,后来就变得吃力,这样不能很好的一次性完成代码,发现应该先设计,在着手编写代码之前,可以先绘制类图,明确每个类的属性和方法,以及它们之间的关系。这有助于构建清晰的代码结构和逻辑,避免在编码过程中陷入......
  • 前端开发者必备的缓存知识总结
     在前端开发中,缓存是一个至关重要的概念,它能够显著提升网站性能和用户体验。了解各种类型的缓存以及如何有效地利用它们对于前端开发者来说至关重要。在本文中,我们将总结前端开发者需要知道的缓存知识,帮助他们更好地优化网站性能和提升用户体验。1.浏览器缓存HTTP缓存控制......
  • 2024最新华为OD算法题目
    在一个机房中,服务器的位置标识在 n*m 的整数矩阵网格中,1表示单元格上有服务器,0 表示没有。如果两台服务器位于同一行或者同一列中紧邻的位置,则认为它们之间可以组成一个局域网。请你统计机房中最大的局域网包含的服务器个数。输入描述第一行输入两个正整数,n和m,0<n,m<=......
  • 6.6每日总结
    可视化第二版本代码留存<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge,chrome=1"><metaname="renderer&q......
  • 2道寻找回文子串的题目
    题目题目1题目2题目1是将字符串分隔,使得分隔后得到的每个字符串都是回文子串题目2是从字符串里面找到回文子串两道题都可以利用递归来解决//利用双指针判断是否是回文子串boolisre(string&s){ intleft=0; intright-s.size()-1; while(left<=right) {......
  • oop-PTA题目集4~6总结
    一、前言   相比于前三次的题目集,题目集4~6需要用到的新的知识点主要是面向对象程序设计中继承和多态这两个特性的使用。第四次题目集中的答题判题程序-4是在前三次程序的基础上增加新的内容,新增了选择题和填空题两种题型,这一变化的处理需要用到前三次未使用的继承,即将题目......
  • 2种方法解决需要clik点击数的题目——[HNCTF 2022 WEEK2]getflag 137分 MFC patch RE
    题目   DIEIDA找到判断点击数的if,我们修改一下汇编指令让点击数<99999999就成立这个程序没有要求我们输入,说明flag是程序打印的IDA动调 下一个断点修改 得到flag  还有一种更快的方法——CheatEngine 随便点击几次 在CE中修改点击次数 Getf......