一、前言
關於7,8兩次傢俱強電電路模擬程式,我認為是比較困難且綜合的程式題,我們需要處理複雜的電路結構,如包含多個並聯電路的串聯電路,以及並聯電路之間的包含關係還要精確地處理輸入和輸出格式,確保所有的計算和輸出都符合題目要求,這些設計程式整體的方面都屬於較為困難的,而關於類和物件的關係,以及如何透過方法來類比電路的工作原理,這種在動手編寫時具體補充的程式碼部分難度偏向中等,知識點我個人認為偏向基礎的物件導向程式設計(如需要設計多個類物件、方法、變數、資料型別、控制結構等。),資料結構/陣列與集合(選擇合適的資料結構去儲存裝置資訊和連線資訊)和字串處理。至於題目題量則是單一題目,但涉及多個類和複雜邏輯。總之是個複雜的Java程式模擬題。
二、設計與分析
首先是粗略的分析即如何完成程式
1,設計電路裝置類:設計一個通用的電路裝置類,包含所有電路裝置的公共屬性和方法。
2,受控裝置與控制裝置類:分別設計受控裝置類和控制裝置類,並實現具體的裝置如開關、調速器、燈、風扇等。
3,串聯電路與並聯電路類:設計串聯電路和並聯電路類,實現電路的串聯和並聯邏輯。
4,輸入處理:解析輸入資訊,構建電路裝置物件,並建立裝置之間的連線關係。
5,計算電路狀態:根據輸入的控制資訊,計算電路的狀態,包括開關狀態、調速器的檔位、燈的亮度、風扇的轉速等。
6,輸出結果:按照題目要求的格式輸出所有裝置的狀態或引數。
由於都是傢俱強電電路模擬程式所以大致思路如此,但重點還是在於迭代的改變和怎麼合理的設計並完成程式。
第七次題目集
點選檢視程式碼
import java.util.*;
public class Main {
private static Map<String, Device> devices = new HashMap<>();
private static Map<String, Connection> connections = new HashMap<>();
private static Map<String, Circuit> circuits = new HashMap<>();
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input;
while (!(input = scanner.nextLine()).equals("end")) {
processInput(input);
}
scanner.close();
simulateCircuit();
printDeviceStatus();
}
private static void processInput(String input) {
if (input.startsWith("#T")) {
processSeriesCircuit(input);
} else if (input.startsWith("#M")) {
processParallelCircuit(input);
} else if (input.startsWith("#")) {
processDeviceControl(input);
}
}
private static void processSeriesCircuit(String input) {
String[] parts = input.split(":");
String circuitId = generateUniqueId();
String[] connections = parts[1].split(" ");
Circuit circuit = new Circuit(circuitId);
for (String connection : connections) {
circuit.addConnection(connection);
}
circuits.put(circuitId, circuit);
}
private static void processParallelCircuit(String input) {
String[] parts = input.split(":");
String circuitId = generateUniqueId();
String[] seriesCircuits = parts[1].substring(1, parts[1].length() - 1).split(" ");
Circuit parallelCircuit = new Circuit(circuitId);
for (String seriesCircuit : seriesCircuits) {
parallelCircuit.addSeriesCircuit(circuits.get(seriesCircuit));
}
circuits.put(circuitId, parallelCircuit);
}
private static void processDeviceControl(String input) {
String[] parts = input.split(":");
String deviceId = parts[0].substring(1);
Device device = devices.get(deviceId);
if (device != null) {
device.control(parts[1]);
}
}
private static void simulateCircuit() {
for (Circuit circuit : circuits.values()) {
circuit.simulate();
}
}
private static void printDeviceStatus() {
devices.values().forEach(Device::printStatus);
}
private static String generateUniqueId() {
String id = UUID.randomUUID().toString();
while (circuits.containsKey(id) || devices.containsKey(id)) {
id = UUID.randomUUID().toString();
}
return id;
}
private static abstract class Device {
protected String id;
public Device(String id) {
this.id = id;
}
public abstract void control(String command);
public abstract void printStatus();
public abstract void updateState();
}
private static class Switch extends Device {
private boolean state = false;
public Switch(String id) {
super(id);
}
@Override
public void control(String command) {
state = !state;
}
@Override
public void printStatus() {
System.out.println("@" + id + ":" + (state ? "closed" : "turned on"));
}
@Override
public void updateState() {
if (this.state==false) {
this.state=true;
}else if(this.state==true) {
this.state=false;
}
}
public boolean isState() {
return state;
}
}
private static class Dimmer extends Device {
private double level = 0.0;
public Dimmer(String id) {
super(id);
}
@Override
public void control(String command) {
if (command.equals("+")) {
level += 0.1;
} else if (command.equals("-")) {
level -= 0.1;
}
}
@Override
public void printStatus() {
System.out.printf("@%s:%.2f\\\\\\\\n", id, level);
}
@Override
public void updateState() {
// Update dimmer state based on current circuit conditions
}
}
private static class Bulb extends Device {
private int brightness = 0;
public Bulb(String id) {
super(id);
}
@Override
public void control(String command) {
// No control needed for bulbs in this simulation
}
@Override
public void printStatus() {
System.out.println("@" + id + ":" + brightness);
}
@Override
public void updateState() {
// Update bulb state based on current circuit conditions
}
public void setBrightness(int brightness) {
this.brightness = brightness;
}
}
private static class Fan extends Device {
private int speed = 0;
public Fan(String id) {
super(id);
}
@Override
public void control(String command) {
// No control needed for fans in this simulation
}
@Override
public void printStatus() {
System.out.println("@" + id + ":" + speed);
}
@Override
public void updateState() {
// Update fan state based on current circuit conditions
}
public void setSpeed(int speed) {
this.speed = speed;
}
}
private static class Circuit {
private String id;
private List<Connection> connections = new ArrayList<>();
private List<Circuit> seriesCircuits = new ArrayList<>();
public Circuit(String id) {
this.id = id;
}
public void addConnection(String connection) {
connections.add(new Connection(connection));
}
public void addSeriesCircuit(Circuit circuit) {
seriesCircuits.add(circuit);
}
public void simulate() {
for (Connection connection : connections) {
Device controlDevice = devices.get(getDeviceIdFromPin(connection.getInputPin()));
if (controlDevice instanceof Switch && ((Switch) controlDevice).isState()) {
updateConnectedDevice(connection.getOutputPin(), true);
} else {
updateConnectedDevice(connection.getOutputPin(), false);
}
}
}
private String getDeviceIdFromPin(String pin) {
return pin.split("-")[0];
}
private void updateConnectedDevice(String outputPin, boolean isOn) {
Device device = devices.get(getDeviceIdFromPin(outputPin));
if (device instanceof Bulb) {
((Bulb) device).setBrightness(isOn ? 200 : 0);
} else if (device instanceof Fan) {
((Fan) device).setSpeed(isOn ? 360 : 0);
}
}
}
private static class Connection {
private String inputPin;
private String outputPin;
private boolean connectedDeviceState;
public Connection(String connection) {
String[] parts = connection.split("-");
inputPin = parts[0];
outputPin = parts[1];
connectedDeviceState = false;
}
public String getInputPin() {
return inputPin;
}
public String getOutputPin() {
return outputPin;
}
}}
點選檢視程式碼
class Device {
protected double v1;
protected double v2;
public Device() {}
public Device(double v1,double v2) {
this.v1=0;
this.v2=0;
}
public double getV1() {
return v1;
}
public void setV1(double v1) {
this.v1 = v1;
}
public double getV2() {
return v2;
}
public void setV2(double v2) {
this.v2 = v2;
}
public void display() {
}
}
import java.util.*;
class Circuit {
protected static LinkedHashMap<String,Device> deviceMap = new LinkedHashMap<>();
public Circuit() {
}
public void update() {
Device previous =null;
for(Device device : deviceMap.values()) {
if(previous!=null) {
device.setV1(previous.getV2());
}
if(device instanceof Switch) {
((Switch) device).update();
}else if(device instanceof Gearspeed) {
((Gearspeed) device).update();
}else if(device instanceof Unitgear) {
((Unitgear) device).update();
}else if(device instanceof Light1) {
((Light1) device).update();
}else if(device instanceof Light2) {
((Light2) device).update();
}else if(device instanceof Fan) {
((Fan) device).update();
}else if(device instanceof Fan2){
((Fan2)device).update();
}
previous=device;
}
}
public void getDeviceStates() {
for (Map.Entry<String, Device> entry : deviceMap.entrySet()) {
System.out.print("@" + entry.getKey() + ":");
entry.getValue().display();
}
}
class device1 extends Device {
public device1(double v1,double v2) {
this.v1=v1;
this.v2=v2;
}
public device1() {
}
}class device2 extends Device{
protected double v;
public device2() {
}
public device2(double v1,double v2,double v) {
this.v1=v1;
this.v2=v2;
this.v=v;
}
}
class Fan extends device2{
private double lux=0;
public Fan(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Fan() {
}
public double getLux() {
return lux;
}
public void setlux(double lux) {
this.lux=lux;
}
public void update() {
if(this.v1<80) {
this.lux=0;
}
if(this.v1>=80&&this.v1<=150) {
this.lux=4*this.v1-240;
}
if(this.v1>=150) {
this.lux=360;
}
}
public void display() {
System.out.println(Math.round(this.lux));
}
}class Fan2 extends device2{
private double lux=0;
public Fan2(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Fan2() {
}
public double getLux() {
return lux;
}
public void setlux(double lux) {
this.lux=lux;
}
public void update() {
if(this.v1<80) {
this.lux=0;
}
if(this.v1>=80&&this.v1<=100) {
this.lux=80;
}
if(this.v1>=100&&this.v1<120) {
this.lux=160;
}
if(this.v1>=120&&this.v1<140){
this.lux=260;
}
if(this.v1>=140){
this.lux=360;
}
}
public void display() {
System.out.println(Math.round(this.lux));
}
}class Gearspeed extends device1{
private double v1 = 220;
private int gear=0;
public Gearspeed() {
}
public Gearspeed(int gear,double v1,double v2) {
super(v1,v2);
this.gear=gear;
this.gear=0;
}
public int getGear() {
return gear;
}
public void up() {
if(this.gear<3)
this.gear++;
}
public void down() {
if(this.gear>0)
this.gear--;
}
public void update() {
if (this.v1 == 0) {
this.v2 = 0;
} else {
switch (this.gear) {
case 0:
this.v2 = 0;
break;
case 1:
this.v2 = 0.3 *this.v1;
break;
case 2:
this.v2 = 0.6 *this.v1;
break;
case 3:
this.v2 = 0.9 * this.v1;
break;
default:
this.v2 = 0;
break;
}
}
}
public void display() {
System.out.println(this.gear);
}
}class Light1 extends device2{
private double v2 = 0;
private double lux=0;
public Light1(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Light1() {
}
public double getLux() {
return lux;
}
public void update() {
if(this.v1>=0&&this.v1<=9) {
this.lux=0;
}else if(this.v1>9&&this.v1<=220) {
this.lux=(5.0/7.0)*v1+(300.0/7.0);
}else if(this.v1>220) {
this.lux=200;
}
}
public void display() {
System.out.println((int)(this.lux));
}
}class Light2 extends device2{
private double v2 = 0;
private double lux=0;
public Light2(double v,double v1,double v2,double lux) {
super(v,v1,v2);
this.lux=0;
}
public Light2() {
}
public double getLux() {
return lux;
}
public void update() {
if(this.v1>0) {
this.lux=180;
}
else if(this.v1==0) {
this.lux=0;
}
}
public void display() {
System.out.println((int)this.lux);
}
}import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Circuit circuit = new Circuit();
Device device = new Device();
while(true) {
String input = scanner.next();
if(input.startsWith("[")) {
String regex = "[A-Z]\\d+-2";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while(matcher.find()) {
String inputs = input.substring(1,3);
if(inputs.startsWith("K")) {
Device switchs = new Switch();
Circuit.deviceMap.put(inputs, switchs);
}else if(inputs.startsWith("F")) {
Device gears = new Gearspeed();
circuit.deviceMap.put(inputs, gears);
}else if(inputs.startsWith("L")) {
Device unit = new Unitgear();
circuit.deviceMap.put(inputs, unit);
}else if(inputs.startsWith("B")) {
Device light1 = new Light1();
circuit.deviceMap.put(inputs, light1);
}else if(inputs.startsWith("R")) {
Device light2 = new Light2();
circuit.deviceMap.put(inputs, light2);
}else if(inputs.startsWith("D")) {
Device fan = new Fan();
Circuit.deviceMap.put(inputs, fan);
}else if(inputs.startsWith("A")){
Device fan2=new Fan2();
Circuit.deviceMap.put(inputs, fan2);
}
if(Circuit.deviceMap.size()==1){Circuit.deviceMap.get(inputs).setV1(220);}
}
}else if(input.startsWith("#K")) {
for(Map.Entry<String,Device>entry : circuit.deviceMap.entrySet()) {
if(entry.getKey().startsWith("K")) {
((Switch) entry.getValue()).setState();
break;
}
}
}else if(input.startsWith("#F")) {
for(Map.Entry<String,Device>entry : circuit.deviceMap.entrySet()) {
if(entry.getKey().startsWith("F")) {
if(input.substring(3,4).equals("+")) {
((Gearspeed) entry.getValue()).up();
}else if(input.substring(3,4).equals("-")) {
((Gearspeed) entry.getValue()).down();
}
break;
}
}
}else if(input.startsWith("#L")) {
for(Map.Entry<String,Device>entry : circuit.deviceMap.entrySet()) {
if(entry.getKey().startsWith("L")) {
double input1 = Double.parseDouble(input.substring(4));
((Unitgear) entry.getValue()).setGear(input1);
break;
}
}
}else if(input.equals("end")) {
break;
}
}
circuit.update();
circuit.getDeviceStates();
}
}
class Switch extends device1{
private int state;
public Switch() {
}
public Switch(double v1,double v2,int state) {
super(v1,v2);
this.state=0;
}
public int getState() {
return this.state;
}
public void setState() {
if (this.state==1) {
this.state=0;
}else if(this.state==0) {
this.state=1;
}
}
public void update() {
if(this.state==1) {
this.v2=this.v1;
}else if(this.state==0) {
this.v2=0;
}
}
public void display() {
if(this.state==0) {
System.out.println("tuened on");
}else if(this.state==1) {
System.out.println("closed");
}
}
}import java.text.DecimalFormat;
class Unitgear extends device1{
private double v1 = 220;
private double gear=0;
public Unitgear() {
}
public Unitgear(double gear,double v1,double v2) {
super(v1,v2);
if(gear>=0&&gear<=1)
this.gear=gear;
this.gear=0;
}
public double getGear() {
return gear;
}
public void setGear(double gear) {
if(gear>=0&&gear<=1)
this.gear = gear;
}
public void update() {
this.v2=((double)this.v1*this.gear);
}
public void display() {
DecimalFormat decimalFormat = new DecimalFormat("#0.00");
String format = decimalFormat.format(this.gear);
System.out.println(format);
}
}
關於程式碼的分析
首先是定義Device抽象類(裝置)透過此來控制所有裝置的基礎行為,其子類分為兩種,一是控制設施二是受控裝置,接下來是電路類,首先是串聯電路進行類比電路,其次是並聯電路由多個串聯電路構成模擬多個分支電路,然後再單獨設計一個連線類,去處理字串的問題並且將輸入,輸出引腳連線而主類則負責處理輸入,解析輸入資訊,建立裝置、電路和連線。類比電路呼叫電路的模擬方法來更新裝置狀態,輸出所有裝置的狀態。
關於程式/題目的分析
1,儲存資料
建立一個類來表示電路中的每個裝置,包含裝置型別、編號、狀態、引腳電壓等資訊,再從基礎裝置類繼承出具體的裝置類。建立一個類來表示電路,包含所有裝置的集合以及連線資訊,串聯電路直接按順序連線引腳,並聯電路則需要將多個串聯電路的輸入和輸出引腳短接。
2,update(更新狀態,處理輸入)
具體分為裝置狀態和電路狀態,一裝置狀態根據輸入的控制資訊更新裝置狀態,二電路狀態在類比電路時,根據裝置的狀態計算每個引腳的電壓,並更新裝置的工作狀態(如燈泡亮度、風扇轉速等)。
3,輸入(字串解析)
解析輸入資訊,包括裝置資訊、連線資訊、控制裝置調節資訊等。
4,電路檢測(第八次)
檢測電路中是否存在短路及在電流計算過程中,檢查是否有裝置電流超過其最大限制,並作出相應處理。
5,輸出模組
按照指定格式輸出每個裝置的狀態和引腳電壓和錯誤提示在檢測到短路或電流超限時,輸出相應的錯誤提示。
具體實現分析
裝置類設計:
Device 抽象類:包含所有裝置的基本屬性和方法。
ControlDevice 和 ControlledDevice 類:分別繼承自 Device,實現具體的裝置邏輯。
電路類設計:
SeriesCircuit 和 ParallelCircuit 類:分別表示串聯和並聯電路,實現電路的模擬邏輯。
輸入處理:
InputHandler 類:負責解析輸入資訊,構建裝置物件,並建立裝置之間的連線關係。
計算電路狀態:
CircuitSimulator 類:根據輸入的控制資訊,計算電路的狀態,包括開關狀態、調速器的檔位、燈的亮度、風扇的轉速等。
輸出結果:
OutputHandler 類:按照題目要求的格式輸出所有裝置的狀態或引數。
在設計過程中,我的最大的挑戰在於如何合理地組織類和方法,透過定義清晰的介面和繼承關係,可以有效地減少程式碼冗餘並提高複用性。同時,對於複雜的邏輯處理(如短路檢測、電流限制等),需要仔細設計並多次測試以確保正確性(是的根本不知道錯在哪裡反覆除錯是最崩潰的)。
三、採坑心得
首先就是短路檢測不準確,在執行實現短路檢測時,由於未考慮到所有可能的短路情況(如透過互斥開關的間接短路還有間接短路可能涉及多個裝置和連線,除了直接檢查電源到地的路徑外,還需要考慮透過中間裝置(如開關、互斥開關)的間接連線以及動態電路變化在電路模擬過程中,裝置的狀態(如開關的開合)可能會發生變化,這會影響短路路徑的存在與否。),導致檢測結果不準確。這就導致只能遍歷電路或除錯檢視電路,檢查是否存在從電源到地的低電阻路徑。之後則是電流計算錯誤在計算裝置電流時,未考慮到裝置電阻隨狀態變化(如二極體導通時電阻為0,這點使我困擾了很久因為各部分電阻不同,而我把電路裝置寫進電路,各路電流還是要分各種情況計算),導致計算結果不準確。所以只能在電流計算過程中,根據裝置的當前狀態動態調整其電阻值,並重新計算電流。還有裝置狀態更新邏輯錯誤,裝置的更新邏輯複雜,容易遺漏某些情況。只能用每部分檢視來驗證每個裝置的狀態更新邏輯。最後是輸入解析錯誤(也是我出現的最為頻繁的問題,但我看到一大堆報錯或者啥也沒有的時候,我就知道又需要我坐牢了)在解析輸入資訊時,由於輸入格式複雜且多樣,容易出現解析錯誤導致程式崩潰這裡面最常見的還是字串解析錯誤,輸入資訊的格式複雜,解析時容易出錯。。所以只能增加輸入驗證邏輯,確保輸入資訊符合預定格式。同時,使用異常處理機制捕獲並處理可能的輸入錯誤。
四、改進建議
全面考慮短路路徑:在短路檢測演算法中,不僅要檢查從電源到地的直接路徑,還要遍歷整個電路圖,考慮透過中間裝置(如開關、互斥開關)的間接短路路徑。
動態檢測:由於電路中的裝置狀態可能會隨著模擬的進行而發生變化(如開關的開合),因此短路檢測不應該是靜態的,而應該在每次裝置狀態更新後都重新執行。
動態電阻模型:為電路中的每個裝置建立一個動態電阻模型,該模型能夠根據裝置的當前狀態(如二極體的導通與截止)動態地調整其電阻值。在電流計算過程中,根據這些動態電阻值來求解電路方程。
迭代求解:由於電路中的電流和電壓是相互依賴的,可能需要採用迭代方法來求解電路方程。在每次迭代中,根據當前的電壓分佈計算電流,然後根據計算出的電流更新電壓分佈,直到電壓和電流都收斂到穩定值。
完善裝置狀態更新邏輯:對裝置狀態更新邏輯進行詳細的審查和測試,確保覆蓋所有可能的場景。
程式碼重構和最佳化:對程式碼進行重構,確保類和方法的職責清晰,減少程式碼冗餘,提高程式碼的可讀性和可維護性。
增強輸入處理能力:嚴格的輸入驗證,在解析輸入資訊之前,增加嚴格的輸入驗證步驟,確保輸入資料符合預定的格式和規範。
模組化設計:將程式劃分為多個模組,每個模組負責特定的功能。透過清晰的介面和繼承關係來組織類和方法,減少程式碼冗餘並提高複用性。
五、總結
總結
在本次傢俱強電電路模擬程式的編寫過程中,是一個複雜且綜合的程式設計挑戰。該程式不僅需要處理複雜的電路結構(包括串聯、並聯以及它們之間的巢狀關係),還需要精確地解析輸入資訊、計算電路狀態,並按照特定格式輸出裝置狀態及引數。透過深入分析和設計,需要逐步構建了包括裝置類、電路類、輸入處理、狀態計算和輸出模組在內的完整程式框架。
在設計和實現過程中,我深刻體會到了物件導向程式設計(OOP)的強大之處,透過定義清晰的介面和繼承關係,可以有效地減少了程式碼冗餘,提高了程式碼的複用性和可維護性。同時,我們也面臨了諸多挑戰,如短路檢測的複雜性、電流計算的動態性、裝置狀態更新的多樣性以及輸入解析的易錯性等。
透過不斷的除錯和最佳化,逐步解決了這些問題。在短路檢測方面,意識到需要全面考慮所有可能的短路路徑,包括透過中間裝置的間接短路,並在每次裝置狀態更新後重新執行短路檢測。在電流計算方面,引入了動態電阻模型,根據裝置的當前狀態動態調整電阻值,並採用迭代方法求解電路方程。在裝置狀態更新和輸入解析方面,增加了詳細的審查和測試步驟,以確保邏輯的正確性和輸入的有效性。
此外,我還提出了多項改進建議,旨在進一步提高程式的健壯性、可維護性和可擴充套件性。這些建議包括完善短路檢測演算法、最佳化電流計算方法、重構和最佳化程式碼結構、增強輸入處理能力以及採用模組化設計等。
總之,傢俱強電電路模擬程式的開發過程不僅考驗了我的程式設計技能,也讓我深刻理解了物件導向程式設計和資料結構在實際應用中的重要性。