前言
答题判题程序4
1.知识点总结
先看主要新增内容:
(1)输入选择题题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
新增约束:标准答案中如果包含多个正确答案(多选题),正确答案之间用英文空格分隔。
输出格式与一般答卷题目的输出一致,判断结果除了true、false,增加一项”partially correct”表示部分正确。
多选题给分方式:
答案包含所有正确答案且不含错误答案给满分;包含一个错误答案或完全没有答案给0分;包含部分正确答案且不含错误答案给一半分,如果一半分值为小数,按截尾规则只保留整数部分。
(2)输入填空题题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
输出格式与一般答卷题目的输出一致,判断结果除了true、false,增加一项”partially correct”表示部分正确。
填空题给分方式:
答案与标准答案内容完全匹配给满分,包含一个错误字符或完全没有答案给0分,包含部分正确答案且不含错误字符给一半分,如果一半分值为小数,按截尾规则只保留整数部分。
(3)输出顺序变化
只要是正确格式的信息,可以以任意的先后顺序输入各类不同的信息。比如试卷可以出现在题目之前,删除题目的信息可以出现在题目之前等。
(4)多张试卷信息
本题考虑多个同学有多张不同试卷的答卷的情况。输出顺序优先级为学号、试卷号,按从小到大的顺序先按学号排序,再按试卷号。
根据新增内容,首先,要解决单选题,多选题和填空题的问题我们可以用继承方面的知识,为它们定义同一个父类题目类,并在父类中定义一个判题方法,根据子类各自的判题方式重写它,实现多态。
然后是乱序输入问题我们可以先将所有数据读入进一个arraylist中,然后根据需求,先读哪些信息,避免出现题目还未被创建就删除或者加到试卷中了。
然后就是输出顺序,可以利用implements Comparable
2.题量方面
答题判题程序4是在3的基础上迭代的,这次题量并不多,主要是为了让我们理解继承和多态方面的知识并熟练使用它。
3.难度情况
相比于前几次迭代的东西并不多,难度偏低,差不多两个小时可以完成。
家居强电电路模拟程序1
1.知识点总结
先看题目主要内容:
控制设备模拟
本题模拟的控制设备包括:开关、分档调速器、连续调速器。
受控设备模拟
本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。
输入信息:
设备信息
连接信息
控制设备调节信息
电源接地标识:VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。
输出信息:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。
知识点主要有
(1)大量使用了继承方面的知识,所有家具和控制器都继承自同一个父类Element元件类,这样便于后面的连接和通电处理过程
(2)使用了treemap存储所有元件,treemap由键和值组成,键为每一个元件的名字,是String类型,如K1,D2等等,值为元件对象,是Element类型,treemap的好处就是可以实现自动按照自然顺序排序,不需要我们后期再单独排序。
(3)运用合适的正则表达式处理读取进来的信息,在之前的答题判题程序中已经熟练掌握正则表达式的用法。
2.题量方面
由于是第一次迭代,代码量并不多,最多500行
3.难度情况
难度中等,主要难在类的设计上,怎样设计合适的类使得后续的处理更加方便
家居强电电路模拟程序2
1.知识点总结
新增内容方面:
(1)串联电路信息
一条串联电路占一行,串联电路由按从靠电源端到接地端顺序依次输入的 n 个连接 信息组成,连接信息之间用英文空格" "分隔。
串联电路信息格式:
"#T"+电路编号+":"+连接信息+" "+连接信息+...+" "+连接信息
例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] 一个串联电路的第一个引脚是 IN,代表起始端,靠电源。最后一个引脚是 OUT,代表结尾端, 靠接地。
约束条件:
不同的串联电路信息编号不同。
输入的最后一条电路信息必定是总电路信息,总电路信息的起始引脚是 VCC,结束引脚是 GND。
连接信息中的引脚可能是一条串联或并联电路的 IN 或者 OUT。例如:
T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT OUT]
T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT]
(2)并联电路信息
一条并联电路占一行,并联电路由其包含的几条串联电路组成,串联电路标识之间用英文空格" "分隔。
格式:
"#M"+电路编号+":"+”[”+串联电路信息+" "+....+" "+串联电路信息+”]”
例如:#M1:[T1 T2 T3]
该例声明了一个并联电路,由 T1、T2、T3 三条串联电路并联而成,三条串联电路的 IN 短 接在一起构成 M1 的 IN,三条串联电路的 OUT 短接在一起构成 M1 的 OUT。
(3)落地扇
工作电压区间为 [80V,150V],对应转速区间为 80-360 转/分钟。电压在[80,100)V 区间对应转速为 80 转/分 钟,[100-120)V 区间对应转速为 160 转/分钟,[120-140)V 区间对应转速为 260 转/分钟,超过 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)
知识点相比于上次没有太大变化,主要是难在并联电路和串联电路的处理方面。
2.题量方面
代码行数明显增多,所需时间比之前多5个小时
3.难度情况
难度偏高,如何设计串联类和并联类以及其中的方法非常关键,因为串联电路中可以有并联,并联电路中也可能有串联还要计算电阻电压。
设计与分析
答题判题程序4
类图如下
先分析下题目类,从类图中可以看到我创建了题目类Topic用作所有题目类型的父类,这里也可以设置为抽象类
class Topic{
private String id=null;
private String content=null;
private Boolean effective=true;
public Topic(String id,String content){
this.id=id;
this.content=content;
}
public Boolean getEffective() {
return effective;
}
public void setEffective(Boolean effective) {
this.effective = effective;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String judge(String studentAnswer){
return null;
}
}
可以看到题目类中有一个judge方法,但它返回的是String类型,因为填空题和多选题可能出现部分正确,所以没有定义成Boolean型,后续会重写该方法,再调用该方法就可以实现不同题目的判题了。
再看Topic的子类单选题,多选题和填空题,TopicSingle,TopicMultiple,TopicFill代码如下
class TopicFill extends Topic{
private String standardAnswer=null;
public TopicFill(String id,String content,String standardAnswer) {
super(id,content);
this.standardAnswer=standardAnswer;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
@Override
public String judge(String studentAnswer) {
if(!standardAnswer.contains(studentAnswer)||studentAnswer.equals("")) {
return "false";
}
if(!studentAnswer.contains(standardAnswer)) {
return "partially correct";
}
return "true";
}
}
class TopicMultiple extends Topic{
private ArrayList<String> MultipleStandardAnswers;
public TopicMultiple(String id,String content,ArrayList<String> multipleStandardAnswers) {
super(id,content);
this.MultipleStandardAnswers=multipleStandardAnswers;
}
public ArrayList<String> getMultipleStandardAnswers() {
return MultipleStandardAnswers;
}
public void setMultipleStandardAnswers(ArrayList<String> multipleStandardAnswers) {
MultipleStandardAnswers = multipleStandardAnswers;
}
@Override
public String judge(String studentAnswer){
String[] answers=studentAnswer.split("\\s+");
ArrayList<String> studentAnswersList = new ArrayList<>(Arrays.asList(answers));
for (String studentAnswers : studentAnswersList) {//检查是否有错误答案被选中
if (!MultipleStandardAnswers.contains(studentAnswers)||studentAnswer.equals("")) {
return "false";
}
}
for(String multipleStandardAnswer:MultipleStandardAnswers) {//检查是否有遗漏答案
if(!studentAnswersList.contains(multipleStandardAnswer)) {
return "partially correct";
}
}
return "true";//答案正确
}
}
class TopicSingle extends Topic{
private String standardAnwser=null;
public TopicSingle(String id,String content,String standardAnwser) {
super(id,content);
this.standardAnwser=standardAnwser;
}
public String getStandardAnwser() {
return standardAnwser;
}
public void setStandardAnwser(String standardAnwser) {
this.standardAnwser = standardAnwser;
}
@Override
public String judge(String studentAnser) {
if(studentAnser.equals(standardAnwser)) {
return "true";
}
else return "false";
}
}
可以看到其中的judge方法已经被重写了
再分析下排序问题
看下面这段答卷类Answerpaper的代码,它有一个接口Comparable
class Answerpaper implements Comparable
private String id;//答卷编号
private String studentid;//答卷所对应学生学号
private ArrayList
private ArrayList
private ArrayList
public Testpaper findTestpaper(ArrayList<Testpaper> testpaperlist){//为该答卷找对应的试卷并返回
Testpaper testpaper = null;
for (int i = 0; i < testpaperlist.size(); i++) {
Testpaper paper = testpaperlist.get(i);
if (paper.getId().equals(id)) {
testpaper = paper;
break;
}
}
return testpaper;
}
public Boolean findAnswer(int i){//判断某一题是否有对应的答案,若没有则返回false
Boolean findanswer=false;
for(int j=0;j<answeridlist.size();j++){
if(Integer.parseInt(answeridlist.get(j))==(i+1)){
findanswer=true;
break;
}
}
return findanswer;
}
public String getStudentAnswer(int i){//用findAnswer确保某一题有对应答案后,调用此方法获取对应学生答案
String studentAnswer=null;
for(int j=0;j<answeridlist.size();j++){
if(Integer.parseInt(answeridlist.get(j))==(i+1)){
studentAnswer=answerlist.get(j);
}
}
return studentAnswer;
}
public void outputScoreSituation(ArrayList<Student> studentlist){//确保学生存在的情况下,输出学生的得分情况
System.out.print(studentid+" ");
Boolean found=false;
for(int i=0;i<studentlist.size();i++){
if(studentlist.get(i).getId().equals(studentid)){
System.out.print(studentlist.get(i).getName()+": ");
found=true;
break;
}
}
if(!found){
System.out.println("not found");
}
else{
int totalScore=0;
for(int i=0;i<score.size();i++){
if(i==this.score.size()-1){
System.out.printf("%d",score.get(i));
totalScore+=score.get(i);
break;
}
System.out.printf("%d ",score.get(i));
totalScore+=score.get(i);
}
System.out.println("~"+totalScore);
}
}
@Override
public int compareTo(Answerpaper o){
if(!this.studentid.equals(o.studentid))
return this.studentid.compareTo(o.studentid);
return this.id.compareTo(o.id);
}
其它方面在前几次博客中已经分析了,在此不再分析
家居强电电路模拟程序1
类图如下
这题主要难在如何存储元件,如何让设备之间连接起来,如何通电处理。我们接下来一个个分析
首先是如何存储元件,这部分代码是参考了老师的代码,定义了一个元件库类Elementlibrary,里面每个元件都有一个对应的treemap,然后再定义一个集合存储这些treemap,以实现整体管理,后面再定义添加元件,检查元件的方法,以及show出各个元件信息的方法,元件库代码示例如下
class Elementlibrary {//元件库
private TreeMap<String,Element> ceilingfanmap=new TreeMap<String,Element>(Comparator.naturalOrder());//吊扇
private TreeMap<String,Element> continuousgovernormap=new TreeMap<String,Element>(Comparator.naturalOrder());//连续调速器
private TreeMap<String,Element> gradegovernormap=new TreeMap<String,Element>(Comparator.naturalOrder());//分档调速器
private TreeMap<String,Element> sunlampmap=new TreeMap<String,Element>(Comparator.naturalOrder());//日光灯
private TreeMap<String,Element> switchmap=new TreeMap<String,Element>(Comparator.naturalOrder());//开关
private TreeMap<String,Element> whitelampmap=new TreeMap<String,Element>(Comparator.naturalOrder());//白炽灯
public Elementlibrary() {
}
private char[] elementmarks={'K','F','L','B','R','D'};
@SuppressWarnings("rawtypes")
private TreeMap[] elementcollections= {switchmap,gradegovernormap,continuousgovernormap,whitelampmap,sunlampmap,ceilingfanmap};
@SuppressWarnings("unchecked")
public void addElement(String elementname,Element element) {//添加元件
char c=elementname.charAt(0);
for(int i=0;i<elementmarks.length;i++) {
if(elementmarks[i]==c) {
elementcollections[i].put(elementname, element);
}
}
}
public Element findElement(String elementname) {//根据元件名找元件
for(int i=0;i<elementcollections.length;i++) {
if(elementcollections[i].containsKey(elementname)) {
Element element=(Element) elementcollections[i].get(elementname);
return element;
}
}
return null;//没找到
}
@SuppressWarnings("unchecked")
public void changeElement(String elementname,Element element) {//更新元件信息
for(int i=0;i<elementcollections.length;i++) {
if(elementcollections[i].containsKey(elementname)) {
elementcollections[i].put(elementname, element);
}
}
}
public boolean checkElement(String elementname) {//检查元件库中是否有某个元件
boolean checkelement=false;
for(int i=0;i<elementcollections.length;i++) {
if(elementcollections[i].containsKey(elementname)) {
checkelement=true;
}
}
return checkelement;
}
}
然后是连接方面的问题,这一次的连接处理和下一次不一样,处理方法比较复杂,后面会更改,这里还是提一下,主要是在每一个元件里存储与它连接的下一个元件,读取信息的时候记录下起始元件和结束元件,这种方法过于
复杂,而且到后面串联并联混合时也会很难处理。
这里提供一段根据起始元件找到其它元件的代码示例
public void gainline() {//将所有线路上元件添加到line中
Element startelement=elementlibrary.findElement(startname);
while(true) {
line.add(startelement);
if(!startelement.getOutputpin().isEmpty()){
String firstKey = startelement.getOutputpin().firstKey();
startelement=elementlibrary.findElement(firstKey);
if(startelement.getName().equals(endname)) {
line.add(startelement);
break;
}
}
else break;
}
}
最后就是连接以及通电方面的问题,我创建了一个连接类Connection用于处理连接信息,里面有ifConnected()方法判断电路是否联通,如开关是否连接,调速器是否为0等,确认连接成功后用gainline()方法获取到整条电
路,最后在调用electrify()方法通电处理即可,然后调用show方法就行了。
示例代码
public boolean ifConnected() {
Element startelement=elementlibrary.findElement(startname);
while(true) {
if (startelement instanceof Switch) {
Switch child = (Switch) startelement;
if(child.getIfopen())return false;
}
if (startelement instanceof Gradegovernor) {
Gradegovernor child = (Gradegovernor) startelement;
if(child.getGears()0)return false;
}
if (startelement instanceof Continuousgovernor) {
Continuousgovernor child = (Continuousgovernor) startelement;
if(child.getGearpara()0)return false;
}
if(startelement.getName().equals(endname)) {
return true;
}
else {
if (! startelement.getOutputpin().isEmpty()) {
String firstKey = startelement.getOutputpin().firstKey();
startelement=elementlibrary.findElement(firstKey);
}
}
}
}
家居强电电路模拟程序2
类图如下:
1.首先讲一下这次相比于上次家居强电电路模拟程序1优化了哪些方面
(1)首先类的设计上,之前是一个父类Element,其它的都是子类,现在是父类的子类还有子类,例如白炽灯和日光灯有同一个父类灯,这样处理时就只用向下转型到灯就行,不用分成两种情况了。
(2)连接方法改成将元件放在同一个ArrayList里面了,这个ArrayList就是串联电路的属性,并联电路里也有一个ArrayList,里面存储串联电路对象,这样就实现了并联。
(3)showInformation方法从放在连接类Connection中改成了放在元件库类Elementlibrary中。
2.接下来主要讲一下这次迭代的难点(串联电路和并联电路都当成元件处理)
(1)这次迭代新增了电阻,首先电阻可以作为所有元件的属性放到Element类中,那么串联电路和并联电路电阻的计算就很麻烦,计算串联电路电阻时,我选择在往串联电路中添加元件时给电路总电阻加上这个元件的电阻。并
联电路就不太一样,因为并联电路有些线路可能是断的,影响总电阻,所以要在确定并联电路中没有断路时再计算电阻。
示例代码
public void removeBreak(String totalname, Elementlibrary elementlibrary) {//若总电路中存在并联电路且该电路中有某些串联电路断路了,将其从并联电路中删去
Element total = elementlibrary.findElement(totalname);
Line totalline = (Line) total;
for (Element element : totalline.getLine()) {//删除并联电路中未联通的电路
if (element instanceof MultipleLine) {
MultipleLine child = (MultipleLine) element;
for(int i=0;i<child.getLines().size();) {
Line line=(Line)child.getLines().get(i);
if(!line.ifConnected()) {
child.getLines().remove(i);
}
else {
i++;
}
}
}
}
for(Element element:totalline.getLine()){//计算并联电路总电阻
if(element instanceof MultipleLine) {
MultipleLine child=(MultipleLine)element;
child.calculateResistance();
}
}
}
(2)接下来就是电压计算的问题了,我选择先计算总电路的电流,再用电流乘电阻计算每个元件的分压。
(3)计算完分压后在通电时调用每个元件的electrifyChange(workvoltage)方法即可。
public void electrify(String totalname,Elementlibrary elementlibrary) {//给电路通电
Element total=elementlibrary.findElement(totalname);
Line totalline=(Line)total;
double totalvoltage=220;//总电压
double totalR=0;//总电阻
double totalI=0;//总电流
for(Element element:totalline.getLine()){//计算总电路电阻
totalR+=element.getResistance();
}
for(Element element:totalline.getLine()){//被调速器改变后的总电压
if(element instanceof Governor) {
Governor child3=(Governor)element;
totalvoltage= child3.changevoltage(totalvoltage);
}
}
totalI=totalvoltage/totalR;//计算电路总电流
for(Element element:totalline.getLine()){
double workvoltage= totalI*element.getResistance();//计算每个元件的工作电压
if(element instanceof Lamp) {//灯泡工作
Lamp lamp=(Lamp)element;
lamp.electrifyChange(workvoltage);
}
if(element instanceof Fan) {//风扇工作
Fan fan=(Fan)element;
fan.electrifyChange(workvoltage);
}
if(element instanceof Line) {//串联电路中的灯泡或风扇工作
Line line=(Line)element;
line.electrifyChange(workvoltage);
}
if(element instanceof MultipleLine) {//并联电路中的线路工作
MultipleLine multipleline=(MultipleLine) element;
multipleline.electrifyChange(workvoltage);
}
}
}
}
踩坑心得
答题判题程序4
主要踩的坑就是填空题的正则表达式有点不一样,在获取填空题信息时我们不能随便去掉空格,这会影响最终的判题
家居强电电路模拟程序1
正则表达式很关键,读取信息出问题的话后续处理很麻烦,也很难处理。
家居强电电路模拟程序2
并联电路的短路情况没有考虑到,电阻计算的方法没选好
改进建议
答题判题程序4
读取信息并分析信息方面代码行数过多,用了多次for循环使得时间和空间复杂度过高,然后输入和输出可以做成一个类,这样主函数不会过于冗长。
家居强电电路模拟程序1
电路连接的方法太过麻烦,后续不好处理也不好改进,所以需要换别的方法,然后就是读取信息的方式太麻烦,代码行数太多
家居强电电路模拟程序2
大部分结构以及完善,但信息读取所用代码还是太长了,需要优化
总结
这三次作业都体现了类设计的重要性,一个合理的类设计可以使我们在编写程序时更加流畅,bug更少。
然后就是继承的好处
代码重用:继承允许子类从父类中继承已有的属性和方法,避免了重复编写相同的代码。这样可以提高代码的可维护性和可扩展性,减少了开发时间和工作量。
类层次结构:通过继承,可以建立起类之间的层次结构,形成更加有组织和易于理解的代码结构。父类定义了通用的属性和方法,而子类可以在此基础上进行扩展和特化。
多态性:继承与多态性密切相关。多态性指的是基于基类的引用,可以调用子类的方法。这样可以实现接口的统一性,并且能够根据实际情况动态选择具体的实现。
代码扩展和修改:当需要对现有的类进行修改或扩展时,通过继承可以方便地添加新的功能或修改现有的功能,而无需修改父类的代码。这符合开放封闭原则,即对扩展开放,对修改封闭。
代码组织和管理:使用继承可以帮助开发者更好地组织和管理代码。通过将共享的属性和方法放在父类中,可以使代码更具有结构性和可读性,便于团队协作和代码维护。
总之,继承提供了一种有效的代码复用机制,并且能够建立起类之间的层次结构,使代码更具有灵活性和可扩展性。通过合理应用继承,可以提高代码的质量和效率,同时减少错误和冗余的代码量。
标签:串联,return,模拟程序,private,电路,判题,强电,public,String From: https://www.cnblogs.com/lch1873316779/p/18228324