问题描述
我目前正在学习 C# 和 WPF,我正在尝试模拟逻辑门和触发器电路,但它不起作用。
有人可以告诉我一种可能的方法来实现这一目标吗? (也许是一个简单的类似应用程序?)
到目前为止我尝试过的:
班级:
public class GateBase
{
public Type Type { get; set; }
public GateBase Input1 { get; set; }
public GateBase Input2 { get; set; }
public List<GateBase> Outputs { get; set; }
public bool Evaluated { get; set; }
public bool Value { get; set; }
public bool FlipFlop { get; set; }
public GateBase(Type type = Type.OFF,Gate input1 = null,Gate input2 = null)
{
Type = type;
Input1 = input1;
Input2 = input2;
Outputs = new List<GateBase>();
Evaluated = false;
Value = false;
FlipFlop = false;
switch (Type)
{
case Type.T:
case Type.D:
case Type.SR:
case Type.JK: FlipFlop = true; break;
}
}
public bool Evaluate()
{
if (!Evaluated)
{
bool input1 = false;
bool input2 = false;
if (Input1 != null)
{
if (Input1.FlipFlop)
input1 = Input1.Value;
else
input1 = Input1.Evaluate();
}
if (Input2 != null)
{
if (Input2.FlipFlop)
input2 = Input2.Value;
else
input2 = Input2.Evaluate();
}
switch (Type)
{
case Type.OFF:
Value = false; break;
case Type.ON:
Value = true; break;
case Type.OUT:
Value = input1; break;
case Type.CON:
Value = input1; break;
case Type.NOT:
Value = input1; break;
case Type.AND:
Value = input1 & input2; break;
case Type.OR:
Value = input1 | input2; break;
case Type.XOR:
Value = input1 ^ input2; break;
case Type.NAND:
Value = !(input1 & input2); break;
case Type.nor:
Value = !(input1 | input2); break;
case Type.Xnor:
Value = !(input1 ^ input2); break;
case Type.D:
Value = input1; break;
case Type.T:
Value = input1 ? Value : !Value; break;
case Type.SR:
Value = (input1 ^ input2) ? Value : Value; break;
case Type.JK:
Value = (input1 ^ input2) ? input1 : (input1 & input2) ? !Value : Value; break;
default: Value = false; break;
}
}
Evaluated = true;
return Value;
}
public void Resetoutputs()
{
Evaluated = false;
foreach (Gate gate in Outputs)
{
if(!gate.FlipFlop)
{
gate.Resetoutputs();
}
}
}
}
循环:
- 更新所有逻辑门
- 更新所有触发器并取消评估每个触发器的输出(如果它们不是触发器)
public List<GateBase> Gates { get; set; }
while (loop)
{
bool evaluating = true;
while (evaluating)
{
evaluating = false;
foreach (Gate gate in Gates)
{
switch (gate.Type)
{
case Model.Type.ON:
case Model.Type.OFF:
gate.Value = gate.Evaluate();
break;
case Model.Type.OUT:
case Model.Type.CON:
case Model.Type.NOT:
if (gate.Input1 != null && (gate.Input1.Evaluated || gate.Input1.FlipFlop))
{
gate.Value = gate.Evaluate();
}
break;
case Model.Type.AND:
case Model.Type.OR:
case Model.Type.XOR:
case Model.Type.NAND:
case Model.Type.nor:
case Model.Type.Xnor:
if (gate.Input1 != null && gate.Input2 != null)
{
if ((gate.Input1.Evaluated || gate.Input1.FlipFlop) && (gate.Input2.Evaluated || gate.Input2.FlipFlop))
{
gate.Value = gate.Evaluate();
}
}
else
{
evaluating = true;
}
break;
}
}
}
evaluating = true;
while (evaluating)
{
evaluating = false;
foreach (Gate gate in Gates)
{
switch (gate.Type)
{
case Model.Type.D:
case Model.Type.T:
if (gate.Input1 != null && (gate.Input1.Evaluated || gate.Input1.FlipFlop))
{
gate.Value = gate.Evaluate();
gate.Resetoutputs();
}
else
{
evaluating = true;
}
break;
case Model.Type.SR:
case Model.Type.JK:
if (gate.Input1 != null && gate.Input2 != null)
{
if ((gate.Input1.Evaluated || gate.Input1.FlipFlop) && (gate.Input2.Evaluated || gate.Input2.FlipFlop))
{
gate.Value = gate.Evaluate();
gate.Resetoutputs();
}
}
else
{
evaluating = true;
}
break;
}
}
}
}
问题:
如果我使用的是 JK 触发器,则结果与预期不同。 (但 T 型触发器工作正常)
这里是解决方案的链接:Solution on GitHub
谢谢!
解决方法
while 循环内的 switch case 没有中断,因此如果 case 是 Model.Type.AND,它将一直下降到 Model.Type.AND em>Model.Type.XNOR 我认为这不是故意的。这可能是您的问题(或至少是其中的一部分)。
只是给你一个想法,这个小例子将输出“no break”。 x = 3 将输出默认字符串。
using System;
public class Program
{
public static void Main()
{
int x = 1;
switch(x){
case 0:
Console.WriteLine("Break");
break;
case 1:
case 2:
Console.WriteLine("no break");
break;
case 3:
default:
Console.WriteLine("End!");
break;
}
}
}
您可以在此处阅读有关传统开关的更多信息: switch C# reference from Micrsoft
,现在我解决了一个问题,它比以前工作得更好。 (我在更新所有触发器之前重置门)
但它仍然没有 100% 正确...
循环中的变化:
// new list
List<Gate> gatesToResetOutputs = new List<Gate>();
while(loop)
{
while(evaluating gates)
{
...
}
while(evaluating flipflops)
{
...
// instead of
gate.ResetOutputs();
// replace with
gatesToResetOutputs.Add(gate);
...
}
// and at the end of the loop
foreach(Gate gate in gatesToResetOutputs)
{
gate.ResetOutputs();
}
}