题目集7~8的总结性Blog

前言

家居强电电路模拟程序3

1.知识点总结

先看主要新增内容:

(1)互斥开关:

互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。

互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。

互斥开关的默认状态为1、2引脚接通,1、3引脚断开。

(2)本次迭代模拟一种受控窗帘:

受控窗帘的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。

(3)本次迭代考虑多个并联电路串联在一起的情况。

本题考虑一条串联电路中包含其他串联电路的情况。例如:

T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND]

本例中T1\T2两条串联电路T3的一个部分,本题考虑这种类型的输入。

2.题量方面

家居强电电路模拟程序三相比于二改动并不大,但是如果前面没有设计好就会很麻烦,我就是因为前面正则没有设计好导致几个测试点一直过不去。题量看情况,对于前面设计好的人并不多对于我这种设计差的人来说算挺多了

3.难度情况

难度并不大,但还是很多细节需要考虑

家居强电电路模拟程序4

1.知识点总结

先看题目主要内容:

(1)增加管脚电压的显示

在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。(格式详见输出信息部分)

(2)电流限制

电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。

例如:@B1:190 68-17 exceeding current limit error

本题各类电器的最大限定电流如下:

开关20、分档调速器18、连续调速器18、白炽灯9、日光灯5、吊扇12、落地扇14、互斥开关20、受控窗帘12、二极管8。

(3)短路检测

如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”

(4)并联电路中包含并联

本次迭代考虑并联电路中包含并联电路的情况,即构成并联电路的串联电路可以包含别的并联电路。例如如下输入的电路,并联电路M2的其中一条串联电路T4中包含了另一条并联电路M1:

(5)二极管

增加二极管元件,其电路特性为:正向导通,反向截止;其电器符号如图4所示,当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。

二极管的标识符为’P’,左侧管脚编号为1,右侧管脚编号为2。

二极管如果两端电压相等,没有电流流过,分以下两种情况输出:

1、如果两端电压为0,二极管的导通/截止状态由接入方向决定,1号引脚靠近电源则状态为导通,反之为截止。
2、如果两端电压不为0,二极管导通。

知识点主要有

(1)输入电压和输出电压该如何记录,这又涉及到高中物理,通路和断路电势的处理又不一样

(2)最大电流和总电路短路的情况

(3)对二极管的理解

2.题量方面

难度很大,反正我是没写出来,才拿了35分,迭代了很多很多东西,想要拿满分估计要个一个星期甚至更多,不过题目集结束好像也没人满分

3.难度情况

太难太难了,反正我是被拿下了。

设计与分析

家居强电电路模拟程序3

类图如下

首先分析下互斥开关,由于互斥开关的切换会涉及到两条线路,所以我给互斥开关添加了一个属性connectmap,为treemap类型,主要记录了两个键值对,键和值都是string类型的,键为2和3,值为2号引脚和3号引脚对应的线路line的名字,再添加一个string类型的属性记录此时开关没有联通的线路的名字unConnectLine,这样只需比对开关中记录的unConnectLine和treemap中记录的情况即可知道互斥开关的连接情况,下面展示一下互斥开关的代码

class ExclusiveSwitch extends Element{//互斥开关
private String unConnectLine="3";//未连接的线路,默认为3
private TreeMap<String,String> connectmap=new TreeMap<String,String>();//连接线路

public ExclusiveSwitch(String name) {
    super(name);
    super.setResistance(5);//12引脚电阻默认为5
    connectmap.put("2",null);
    connectmap.put("3",null);
}

public void changeLine(){//更换连接的线路,同时改变电阻
	if(unConnectLine.equals("3")) {
		setUnConnectLine("2");
		super.setResistance(10);
		return;
	}
	if(unConnectLine.equals("2")) {
		setUnConnectLine("3");
		super.setResistance(5);
		return;
	}
}

public boolean ifConnected(String linename) {//判断线路是否联通
	String zhi=connectmap.get(unConnectLine);
	if(zhi!=null){
		if(linename.equals(zhi)) {
			return false;
		}
	}
	return true;
}

public void addConnectLine(String lineid,String linename){//往指定线路2或3中添加Line的名字
	if(lineid.equals("2")||lineid.equals("3")) {
		connectmap.put(lineid, linename);
	}
}

@Override
public void showInformation() {
	if(unConnectLine.equals("2")) {
		System.out.printf("@%s:%s\n",getName(),"turned on");
	}
	else System.out.printf("@%s:%s\n",getName(),"closed");
}

public String getUnConnectLine() {
	return unConnectLine;
}
public void setUnConnectLine(String unConnectLine) {
	this.unConnectLine = unConnectLine;
}
public TreeMap<String, String> getConnectmap() {
	return connectmap;
}
public void setConnectmap(TreeMap<String, String> connectmap) {
	this.connectmap = connectmap;
}

}

接下来就是受控窗帘了,受控窗帘这一部分其实很简单,主要需要改动的地方是通电部分的处理,需要记录总亮度,串联电路和并联电路也要有总亮度,在通电完后还要根据计算出来的总亮度来处理受控窗帘,下面就不展示窗帘代码了,看通电部分的处理

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;//总电流
	double brightness=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);
			brightness+=lamp.getBrightness();
		}
		if(element instanceof Fan) {//风扇工作
			Fan fan=(Fan)element;
			fan.electrifyChange(workvoltage);
		}
		if(element instanceof Line) {//串联电路中的灯泡或风扇工作
			Line line=(Line)element;
			line.electrifyChange(workvoltage);
			brightness+=line.getBrightness();
		}
		if(element instanceof MultipleLine) {//并联电路中的线路工作
			MultipleLine multipleline=(MultipleLine) element;
			multipleline.electrifyChange(workvoltage);
			brightness+=multipleline.getBrightness();
		}
    }
	
	for(Element element:totalline.getLine()){
		double workvoltage= totalI*element.getResistance();//计算每个元件的工作电压
		if(element instanceof Curtain) {//窗帘工作
			Curtain curtain=(Curtain)element;
			curtain.electrifyChange(workvoltage,brightness);
		}
    }
	
}

串联电路中包含多个并联电路这个也好解决,把并联电路也当作用电器处理就行了,稍微改动一下正则就行,这里就不放代码演示了。

最后就是我自己的大问题在这分析一下,之前我将数据的读取,对象的创建,和分析数据都放在一起了,这次互斥开关的出现导致我之前的代码很难改动,很难处理,好几个测试点都过不去,用了几天时间都没解决,最后只能将自己原本的主函数全部推翻重写,先读取数据,再一个一个创建对象,最后再分析数据。改完之后代码少了300多行,测试点也基本都过了,鬼知道我之前写的什么,下面展示一下部分改动后的代码。

    for(String i:list) {//创建对象并添加到元件库中
        Pattern pat=Pattern.compile("#(\\S+):");
        Matcher mat=pat.matcher(i);
        if(mat.find()) {
        	elementlibrary.addElement(mat.group(1), createElement(mat.group(1)));
            if(mat.group(1).charAt(0)=='T') {
                Pattern pat1=Pattern.compile("\\[(\\S+?)(-(\\S+))? (\\S+?)(-(\\S+))?\\]");
                Matcher mat1=pat1.matcher(i);
                while(mat1.find()) {
                	if(mat1.group(1).equals("VCC")||mat1.group(1).equals("IN")) {
                		if(mat1.group(1).equals("VCC")) {
                			totalname=mat.group(1);
                		}
                		elementlibrary.addElement(mat1.group(4), createElement(mat1.group(4)));
                	}
                	if(!(mat1.group(1).equals("VCC")||mat1.group(1).equals("IN"))&&!(mat1.group(4).equals("GND")||mat1.group(4).equals("OUT"))) {
                		elementlibrary.addElement(mat1.group(4), createElement(mat1.group(4)));
                	}
             }
            }
        } 
      }
	
	for(String i:list) {//解析信息
        Pattern pat=Pattern.compile("#(\\S+):");
        Matcher mat=pat.matcher(i);
        if(mat.find()) {
        	 if(mat.group(1).charAt(0)=='T') {
                 Pattern pat1=Pattern.compile("\\[(\\S+?)(-(\\S+))? (\\S+?)(-(\\S+))?\\]");
                 Matcher mat1=pat1.matcher(i);
                 Line line=(Line)elementlibrary.findElement(mat.group(1));
                 while(mat1.find()) {
                 	if(mat1.group(1).equals("VCC")||mat1.group(1).equals("IN")) {
                 		line.addElement(elementlibrary.findElement(mat1.group(4)));
                 		if(mat1.group(4).charAt(0)=='H') {
                 			ExclusiveSwitch child=(ExclusiveSwitch)elementlibrary.findElement(mat1.group(4));
                 			child.addConnectLine(mat1.group(6), mat.group(1));
                 		}
                 	}
                 	if(!(mat1.group(1).equals("VCC")||mat1.group(1).equals("IN"))&&!(mat1.group(4).equals("GND")||mat1.group(4).equals("OUT"))) {
                 		line.addElement(elementlibrary.findElement(mat1.group(4)));
                 		if(mat1.group(1).charAt(0)=='H') {
                 			ExclusiveSwitch child=(ExclusiveSwitch)elementlibrary.findElement(mat1.group(1));
                 			child.addConnectLine(mat1.group(3), mat.group(1));
                 		}
                 		if(mat1.group(4).charAt(0)=='H') {
                 			ExclusiveSwitch child=(ExclusiveSwitch)elementlibrary.findElement(mat1.group(4));
                 			child.addConnectLine(mat1.group(6), mat.group(1));
                 		}
                 	}
                 	if(mat1.group(4).equals("GND")||mat1.group(4).equals("OUT")) {
                 		if(mat1.group(1).charAt(0)=='H') {
                 			ExclusiveSwitch child=(ExclusiveSwitch)elementlibrary.findElement(mat1.group(1));
                 			child.addConnectLine(mat1.group(3), mat.group(1));
                 		}
                 	}
                 }
        	 }
        	 else if(mat.group(1).charAt(0)=='M') {
        		 Pattern pat1=Pattern.compile("(T\\d+)\\s*");
                 Matcher mat1=pat1.matcher(i);
                 MultipleLine multipleline=(MultipleLine)elementlibrary.findElement(mat.group(1));
                 while(mat1.find()) {
                     multipleline.addLine(elementlibrary.findElement(mat1.group(1)));
                 }
        	 }
        	 else if(mat.group(1).charAt(0)=='L') {
        		 Pattern pat1=Pattern.compile("#L\\d+:(\\S+)");
                 Matcher mat1=pat1.matcher(i);
                 Governor_Continuous continuous=(Governor_Continuous)elementlibrary.findElement(mat.group(1));
                 while(mat1.find()) {
                	 continuous.setGearpara(Double.parseDouble(mat1.group(1)));
                 }
        	 }
        }
        
        Pattern pat2=Pattern.compile("#([KHF]\\w+)");
        Matcher mat2=pat2.matcher(i);
        if(mat2.find()) {
        	if(mat2.group(1).charAt(0)=='K'){
        		Switch s=(Switch)elementlibrary.findElement(mat2.group(1));
        		s.change();
        	 }
        	else if(mat2.group(1).charAt(0)=='H'){
        		 ExclusiveSwitch es=(ExclusiveSwitch)elementlibrary.findElement(mat2.group(1));
                 es.changeLine();
        	 }
        	else{
        		 Pattern pat3=Pattern.compile("([+-])");
                 Matcher mat3=pat3.matcher(i);
                 Governor_Grade grade=(Governor_Grade)elementlibrary.findElement(mat2.group(1));
                 while(mat3.find()) {
                	 grade.change(mat3.group(1));
                 }
        	 }
        }
	}

家居强电电路模拟程序4

类图如下

首先是最大限定电流问题,只需在总父类元件类中添加double类型的属性limitCurrent记录各个元件的最大限度电流,再添加boolean类型的属性ifBurnt记录是否烧坏即可,然后修改每一个元件的showinformation方法,根据ifBurnt输出结果,下面放一段代码示例

@Override
public void showInformation() {//输出设备信息
	if(ifopen) {
	System.out.printf("@%s:%s %d-%d",getName(),"turned on",(int)getPin1(),(int)getPin2());
	}
	else System.out.printf("@%s:%s %d-%d",getName(),"closed",(int)getPin1(),(int)getPin2());
	
	if(super.isIfBurnt()) {
		System.out.printf(" %s\n","exceeding current limit error");
	}
	else {
		System.out.printf("\n");
	}
}

然后是串联并联相互包含问题解决的方法还是和之前一样,把它们当成元件就行了,不过我在分析这段时找到了之前代码差3分每满分的原因,我之前的代码是有一个单独的方法计算串联和并联电路的电阻,然而其实没必要这样,只需重写串联和并联电路的getResistance方法就行了、

总电路短路的情况只需加一个异常判断即可,这里不多讲。

最后也是最难的就是如何输出输入电压和输出电压,遇到断路又该如何输出,我是在元件类中添加了引脚1和引脚2属性记录输入电压和输出电压,互斥开关多一个引脚3,同时还要添加一个属性判断开关,互斥开关等是否反接,大致的处理过程为遍历总电路,然后判断它是断路还是通路,如果是通路则从左往右依次遍历,输入引脚电压等于总电压,输出引脚等于总电压-电压差,然后总电压-=电压差。一些特殊情况如互斥开关的反接再特殊处理。如果是断路的话则更加复杂,断路需要记录下第一个断点和最后一个断点,第一个断点左边等于左端电压,右边等于右端电压。然后处理,但我自身代码没写好导致很难处理,展示一下我的代码,存在大量bug,看看就行

public void electrify(double lvoltage, double rvoltage) {//给每个管脚加上电

if(ifConnected()) {
double totalvoltage=lvoltage-rvoltage;
double totalR=getResistance();

		for(Element element : line) {
			if(element instanceof Governor) {
				Governor child=((Governor) element);
				child.setPin1(totalvoltage);
				totalvoltage=child.changevoltage(totalvoltage);
				child.setPin2(totalvoltage);
			}
		}
		
		double totalI=totalvoltage/totalR;
		
		for(Element element : line) {
			if(element instanceof ExclusiveSwitch) {
				ExclusiveSwitch child=(ExclusiveSwitch)element;
				if(child.isIfReverse()) {
					if(child.getUnConnectLine().equals("2")) {
						child.setPin3(totalvoltage);
						child.setPin1(totalvoltage-totalI*child.getResistance());
					}
					else {
						child.setPin2(totalvoltage);
						child.setPin1(totalvoltage-totalI*child.getResistance());
					}
				}
				else {
					if(child.getUnConnectLine().equals("2")) {
						child.setPin1(totalvoltage);
						child.setPin3(totalvoltage-totalI*child.getResistance());
					}
					else {
						child.setPin1(totalvoltage);
						child.setPin2(totalvoltage-totalI*child.getResistance());
					}
				}
				totalvoltage-=totalI*child.getResistance();
			}
			else if(element instanceof Line) {
				Line child=(Line)element;
				child.electrify(totalvoltage,totalvoltage-totalI*element.getResistance());
				totalvoltage-=totalI*element.getResistance();
			}
			else if(element instanceof MultipleLine) {
				MultipleLine child=(MultipleLine) element;
				child.electrify(totalvoltage,totalvoltage-totalI*element.getResistance());
				totalvoltage-=totalI*element.getResistance();
            }
			else if(element instanceof Lamp||element instanceof Fan||element instanceof Curtain) {
				element.setPin1(totalvoltage);
				element.setPin2(totalvoltage-totalI*element.getResistance());
				totalvoltage-=totalI*element.getResistance();
			}
			else {
				element.setPin1(totalvoltage);
				element.setPin2(totalvoltage);
			}
		}
	}
	else {//线路断开
		double leftvoltage=lvoltage;
		double rightvoltage=rvoltage;
		ArrayList<String> breakpointlist=new ArrayList<>();//记录所有断开的连接点
		for(Element element : line) {
			if(	element instanceof Switch) {
				Switch child=(Switch)element;
				if(child.getIfopen()) {
					breakpointlist.add(child.getName());
				}
			}
			if(element instanceof Governor) {
				Governor child=(Governor) element;
				if(!child.ifConnected()) {
					breakpointlist.add(child.getName());
				}
			}
			if(element instanceof ExclusiveSwitch) {
				ExclusiveSwitch child=(ExclusiveSwitch) element;
				if(!child.ifConnected(getName())) {
					breakpointlist.add(child.getName());
				}
			}
			if(element instanceof Diode) {
				if(breakpointlist.size() == 0) {
					Diode child=(Diode) element;
					if(child.isIfReverse()) {
						breakpointlist.add(child.getName());
					}
				}
				else {
					continue;
				}
			}
			if(element instanceof Line) {
				Line child= (Line) element;
				if(!child.ifConnected()) {
					breakpointlist.add(child.getName());
				}
			}
		    if(element instanceof MultipleLine) {
				MultipleLine child=(MultipleLine) element;
				if(!child.ifConnected()) {
					breakpointlist.add(child.getName());
				}
            }
		}
		String firstname=breakpointlist.get(0);
		String lastname=breakpointlist.get(breakpointlist.size()-1);
		for(Element element : line) {
			if(!element.getName().equals(firstname)) {
				if(element instanceof Governor) {
					Governor child=(Governor) element;
					child.setPin1(leftvoltage);
					leftvoltage=child.changevoltage(leftvoltage);
					child.setPin2(leftvoltage);
				}
				else if(element instanceof ExclusiveSwitch) {
					ExclusiveSwitch child=(ExclusiveSwitch)element;
					if(child.getUnConnectLine().equals("2")) {
						child.setPin3(leftvoltage);
					}
					else {
						child.setPin2(leftvoltage);;
					}
					child.setPin1(leftvoltage);
				}
				else if(element instanceof Line) {
					Line child= (Line) element;
					child.electrify(leftvoltage, leftvoltage);
				}
				else if(element instanceof MultipleLine) {
					MultipleLine child=(MultipleLine) element;
					child.electrify(leftvoltage, leftvoltage);
					
	            }
				else {
					element.setPin1(leftvoltage);
                    element.setPin2(leftvoltage);
				}
			}
			else {
				if(element instanceof Governor) {
					element.setPin1(leftvoltage);
					break;
				}
				else if(element instanceof Switch) {
					Switch child=(Switch)element;
					if(child.isIfReverse()) {
                		child.setPin2(leftvoltage);
                	}
                	else {
                		child.setPin1(leftvoltage);
                	}
                	break;
				}
				else if(element instanceof ExclusiveSwitch) {
					ExclusiveSwitch child=(ExclusiveSwitch) element;
					if(child.isIfReverse()) {
						if(child.getUnConnectLine().equals("2")) {
							child.setPin2(leftvoltage);
						}
						else {
							child.setPin3(leftvoltage);;
						}
					}
					else {
						child.setPin1(leftvoltage);
					}
					break;
				}
				else if(element instanceof Diode) {	
					element.setPin2(leftvoltage);
					break;
				}
				else if(element instanceof Line) {
                    Line child= (Line) element;
                    child.electrify(leftvoltage, rightvoltage);
                    break;
                }
				else {
					if(element instanceof MultipleLine) {
						MultipleLine child=(MultipleLine) element;
                        child.electrify(leftvoltage, rightvoltage);
                        break;
					}
				}
			}
		}

踩坑心得

家居强电电路模拟程序3

正则表达式的设计真的很重要很重要,在写之前一定要仔细想好,一个好的代码可以防止后面的很多问题,不要像我一样都写到3了还要来大改。
正则表达式的设计真的很重要很重要!
正则表达式的设计真的很重要很重要!!
正则表达式的设计真的很重要很重要!!!

家居强电电路模拟程序4

思路很关键,动手能力也很关键,需要有足够的耐心

改进建议

家居强电电路模拟程序3

串联和并联电路的电阻计算方式有问题,需要改进,这也是没满分的原因

家居强电电路模拟程序4

好好想想如何设计,争取多拿点分

总结

通过这两次大作业,我深刻认识到了自己在类的设计方面做的还不够好,对正则表达式的理解也不够

好的Java类设计可以为我们写代码带来多方面的好处:

结构清晰、易于理解:良好设计的类会将数据和行为组织成逻辑单元,使得代码结构更加清晰和直观。这样的设计使得理解代码变得更加容易,特别是在大型项目或者需要长期维护的系统中。

代码复用:良好设计的类可以通过继承和组合实现代码的复用。通过定义通用的类和方法,可以避免重复编写相似功能的代码,提高开发效率和代码质量。

可维护性和扩展性:良好设计的类结构使得代码更易于维护和扩展。通过封装和合理的分层设计,可以减少代码耦合,降低修改一个部分对其他部分的影响,从而降低了维护成本。

降低错误和提高稳定性:良好设计的类可以通过封装数据和行为,保证数据的安全性和一致性,避免无效状态和错误操作。这样可以提高程序的稳定性和可靠性。

提高代码的可测试性:良好设计的类通常会定义清晰的接口和行为,使得单元测试和集成测试更加容易进行。这样可以帮助开发人员更早地发现和修复潜在的问题。

综上所述,良好的Java类设计不仅仅是为了实现功能,更是为了提高整体的软件质量和开发效率,使得我们能够更轻松、更有效地编写和维护代码。

好的正则表达式在Java中的应用可以为我们写代码带来多方面的好处:

文本处理和匹配:正则表达式提供了强大的文本模式匹配功能,可以用来识别、查找或替换特定模式的文本。

格式验证和数据提取:通过正则表达式可以验证输入的格式是否符合预期。

文本替换和处理:正则表达式支持灵活的文本替换操作,可以将文本中符合条件的部分进行替换或修改,非常适用于字符串操作和文本处理。

代码简洁和可读性:使用正则表达式可以大大简化某些复杂的字符串操作代码,使得代码更加简洁和可读。合理使用正则表达式可以将一些复杂的逻辑转化为几行简洁的代码片段。

批量处理和数据清洗:在批量处理大量文本数据时,正则表达式可以帮助快速过滤、查找或修改数据,提高处理效率和一致性。

错误处理和异常情况处理:通过正则表达式可以轻松处理各种输入情况下的异常情况,例如不符合预期的格式或数据结构,从而提高程序的健壮性和容错性。

总之,合理使用正则表达式可以在Java编程中提高代码的灵活性、效率和可维护性,是处理文本和字符串操作不可或缺的强大工具

对本学期本门课程的改进建议及意见

我觉得挺好的,虽然压力很大,但自己的代码水平确实肉眼可见的提升了,建议的话就是大作业发布前老师能不能多给点建议,很多时候类都设计完了才发现有更好的,全部推翻重写真的很难受

posted @ 2024-06-30 12:03  蓝垂鸿  阅读(44)  评论(0)    收藏  举报