我一直在寻找几个小时,并且找不到与此问题类似的任何东西,即使我确定它必须在之前完成:(
用户首先输入数字和+/-符号的组合。例如: 5 +(7-(4 + 1)-3)+11。 我有一个类Add和一个Subtract类,该程序从输入构建这两个类的树。所以在这个例子中,树看起来像是:
Add: 5
Subtract: 7
11 Add: 4
3 1
现在每个类都有一个递归的StepEvaluate方法,该方法首先向控制台打印整个总和。因此,对于前一个示例的Subtract子树,该对象将打印“7 - (4 + 1) - 3”。然后,它将列出树的每个节点,并要求用户单击一个分支以添加/减去最初为0的运行总计。最后将打印答案。因此,如果我们取5 +(7-3)+ 11,控制台的输出将为:
5 + (7-3) + 11
We are going to add to the total with each choice.
The current total is 0.
Choose from the following:
5
+
7-3
+
11
You chose: 11
The current total is 11.
Choose from the following:
5
+
7-3
You chose: 7-3
7 - 3
We are going to subtract from the total with each choice.
The current total is 0.
Choose from the following:
7
-
3
You chose: -3
The current total is -3.
The only remaining choice is 7.
The current total is 4.
So the answer is 4.
The current total is 15.
The only remaining choice is 5.
The current total is 20.
So the answer is 20.
现在我的控制台是一个文本框。在表单构造函数中,使用新线程Eval来评估并输出上述结果。每次用户按下按钮时,它都会恢复线程Eval并暂停当前线程。 Eval然后计算输出的下一个字符串(使用上面的递归类),将字符串写入静态变量,继续执行主线程并暂停执行Eval。然后主线程读取这些静态变量并将其输出到文本框(producer-consumer)。在按钮单击之间,用户的输入被写入静态变量,因此Eval可以在恢复后读取这些。
我希望在表单上有另一个按钮,它会返回一行。如果这删除了“你选择A”这一行,那么用户可以改变他的选择,所以下一个输出可以是“你选择了B”。
我已经阅读了纪念品和命令模式,并了解基于状态和基于操作的撤消/重做。但是我不知道如何使用上面的递归和生产者/消费者线程来实现它。我真正需要的是一种让Eval的执行点回归的方法。但我很确定我做不到......
如果您想要添加和减去代码,请转到:
class Add : MathsOperation
{
public List<MathsOperation> Children;
private int total;
public override void StepEvaluate()
{
MathsOperation currentEvaluation;
writeToConsole(this.ToString());
List<MathsOperation> toBeEvaluated = new List<MathsOperation>(Children);
writeToConsole("We are going to add to the total with each choice.");
while (toBeEvaluated.Count > 1)
{
writeToConsole("The current total is " + total + ".");
writeToConsole("Please choose from the following:");
string choices = "";
foreach (MathsOperation child in toBeEvaluated)
{
choices += Environment.NewLine + child.ToString();
if (child != Children.Last())
choices += Environment.NewLine + "+";
}
writeToConsole(choices);
currentEvaluation = read();
if (currentEvaluation is Number)
{
//add to the total and write output
}
else
{
currentEvaluation.StepEvaluate();
//add the static variable Result to the total and write output
}
toBeEvaluated.Remove(currentEvaluation);
}
currentEvaluation = toBeEvaluated.First();
writeToConsole("The only remaining choice is " + currentEvaluation.ToString());
if (currentEvaluation is Number)
{
//add to the total and write output
}
else
{
currentEvaluation.StepEvaluate();
//add the static variable Result to the total and write output
}
toBeEvaluated.Remove(currentEvaluation);
writeToConsole("So the answer is " + total.ToString());
//write total to static variable Result
}
private void writeToConsole(string txt)
{
//Write to static variable, resume main thread and pause this one
}
private MathsOperation read()
{
//read the static variable. I have replaced this with return new for simplicity
return new MathsOperation();
}
}
如果您有任何想法,我会非常乐意接受它们。
先谢谢你的帮助。
答案 0 :(得分:0)
我会使用这样的解决方案:使用撤消/重做框架。我在theCodeProject上找到了一个很好的。否则,将undo和redo保持为包含其自己的私有数据副本的堆栈。
在undo-stack上,推送整个状态(您的评估树以及其他必要状态)。确保状态不是通过引用共享,例如彻底实施ICloneable。
这有点简短,但希望它有所帮助。