Unity 计算器

原理:后缀表达式

1,在运算之前对字符串检测,确保改字符串没有问题
2,创建两个栈,一个操作数栈S1,一个运算符栈S2
3,开始从左往右扫描字符串,
3-1: 如果是操作数,入栈S1
3-2: 如果是运算符,while死循环
3-2-1:如果S2为空或者S2的栈顶是左括号,则直接入栈,break
3-2-2:如果当前运算符的优先级大于S2栈顶运算符优先级,直接入栈,break
3-2-3:否则,将S2出栈入S1栈
3-3:如果是左括号:直接入S2栈
3-4:如果是右括号:在S2出栈寻找左括号,中间出栈的符号都入操作数S1栈,左右括号都不要
3-5:如果此时S2不为空,将S2的元素出栈入S1
此时对S1栈从出栈放入插入一个List中的第一个位置
清空S1和S2
遍历这个List
如果是操作数,则入S1,如果是操作符,做则从S1中取出操作数进行计算,在将计算结果放入S1中,最后,栈S1的栈顶元素就是计算结果

代码块

using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System;

[System.Serializable]
public class Calculator 
{
    public List<string> CalculatorList = new List<string>();
    public CalculatorManager calculatorManager;
    public event Action<string> onInputValueChange;
    public event Action<string> onOutputValueChange;

    public List<int> leftIndexList = new List<int>(), rightIndexList = new List<int>();
    private int index = 0;
    public Calculator()
    {
        calculatorManager = new CalculatorManager();
    }
    
    //输入
    public void Input(string str)
    {

        if (str == "(")
            leftIndexList.Add(index);
        else if (str == ")")
            rightIndexList.Add(index);
        if (CalculatorList.Count > 0)
        {
            //如果当前输入的和上一个输入的都是不能重复出现的
            if (CalculatorManager.IsNotRepeated(str) && CalculatorManager.IsNotRepeated(CalculatorList.Last()))
            {
                CalculatorList[CalculatorList.Count - 1] = str;
            }
            else
            {

                if (CalculatorList.Count > 2 && float.TryParse(str, out float result2) && CalculatorList.Last() == "-" && CalculatorManager.IsBackspace(CalculatorList[CalculatorList.Count - 2]))
                    CalculatorList[CalculatorList.Count - 1] += str;
                else if (str == "." && (CalculatorManager.IsChar(CalculatorList.Last())))
                {
                    str = "0.";
                    CalculatorList.Add(str);
                }
                else
                {
                    if(CalculatorList.Last()=="0.")//如果是0.
                    {
                        if(float.TryParse(str, out float result3))
                        {
                            CalculatorList[CalculatorList.Count - 1] += str;
                        }
                        else
                        {
                            CalculatorList[CalculatorList.Count - 1] = "0";
                        }
                    }
                    else if (float.TryParse(CalculatorList.Last(), out float result1))//如果最后输入的事小数
                    {
                        if (float.TryParse(str, out float result))
                        {
                            if (result1 == 0)
                                CalculatorList[CalculatorList.Count - 1] = str;
                            else
                                CalculatorList[CalculatorList.Count - 1] += str;
                        }
                        else if (str == ".")
                        {
                            CalculatorList[CalculatorList.Count - 1] += str;
                        }
                        else
                        {
                            CalculatorList.Add(str);
                        }
                    }
                    else
                    {
                        CalculatorList.Add(str);
                    }
                }
            }
        }
        else
        {
            CalculatorList.Add(str);
        }
        //如果当前输入的是不能重复出现并且最后一次输入的也是不能重复出现
        
        
        string calcuatorString = CalculatorList.Aggregate((a,b)=> { return a + b; });
        onInputValueChange?.Invoke(calcuatorString);
        index++;
    }
    //输出
    public void OutPut()
    {
        //对其括号
        if (leftIndexList.Count > rightIndexList.Count)
        {
            for (int i = 0; i < leftIndexList.Count - rightIndexList.Count; i++)
                CalculatorList.Add(")");
        }
        else if (leftIndexList.Count < rightIndexList.Count)
        {
            for (int i = rightIndexList.Count - leftIndexList.Count; i > 0; i--)
            {
                CalculatorList.RemoveAt(rightIndexList.Last());
                rightIndexList.RemoveAt(rightIndexList.Count - 1);
            }
        }
        index = 0;
        leftIndexList.Clear(); rightIndexList.Clear();

        //对最后一个输入进行非法处理
        if (CalculatorManager.IsNotLast(CalculatorList.Last()))
        {
            CalculatorList.RemoveAt(CalculatorList.Count - 1);
        }
        
        string calcuatorString = CalculatorList.Aggregate((a, b) => { return a + b; });
        onOutputValueChange?.Invoke(calcuatorString);

        string calculateResult = calculatorManager.Calculate(CalculatorList);
        CalculatorList.Clear();
        CalculatorList.Add(calculateResult);
        Debug.Log($"计算结果{calculateResult}");
        onInputValueChange?.Invoke(calculateResult);
    }
    //清楚
    public void Clear()
    {
        CalculatorList.Clear();
        CalculatorList.Add("0");
        onInputValueChange?.Invoke("0");
    }
    //退格
    public void Backspace()
    {
        if (CalculatorList.Count > 0)
        {
            CalculatorList.RemoveAt(CalculatorList.Count - 1);
            if (CalculatorList.Count == 0)
                CalculatorList.Add("0");
            string calcuatorString = CalculatorList.Aggregate((a, b) => { return a + b; });
            onInputValueChange?.Invoke(calcuatorString);
        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class CalculatorManager
{
public Stack OperandStack = new Stack();
public Stack OperatorStack = new Stack();
public List SuffixList = new List();
public static IOperation CreateOperation(string s)
{
switch (s)
{
case “+”:
return new AddOperation();
case “-”:
return new SubOperation();
case “*”:
return new MultiplicationOperation();
case “/”:
return new DivisionOperation();
case “sin”:
return new SinOperation();
case “(”:
return new LeftBracket();
case “)”:
return new RightBracket();
case “cos”:
return new CosOperation();
default:
return null;
}
}
///
/// 能否重复出现
///
///
///
public static bool IsNotRepeated(string str)
{
return str == “+” || str == “-” || str == “+” || str == “/”||str==".";
}
///
/// 如果是运算符
///
///
///
public static bool IsOperation(string str)
{
return str == “+” || str == “-” || str == “+” || str == “/” || str == “sin”||str==“cos” ;
}
public static bool IsChar(string str)
{
return IsOperation(str) || IsBackspace(str);
}
public static bool IsBackspace(string str)
{
return str == “(” || str == “)”; ;
}
public static bool IsNotLast(string str)
{
return IsOperation(str) || str == “.”;
}
public string Calculate(List list)
{
// SuffixList.Clear();
OperandStack.Clear();
OperatorStack.Clear();
SuffixList.Clear();
//转为后缀表达式
GetSuffixList(list, SuffixList);
//计算
OperandStack.Clear();
OperatorStack.Clear();
foreach(var item in SuffixList)
{
var operation = item as IOperation;
if (operation != null)
{
float[] operands = new float[operation.OperandCount];
for(int i= operation.OperandCount-1; i>=0;i–)
{
operands[i] =(float) OperandStack.Pop() ;
}
operation.SetOperation(operands);
OperandStack.Push(operation.Calculate());
}
else
{
OperandStack.Push(item);
}
}
return OperandStack.Pop().ToString();
}

public void GetSuffixList(List<string> list,List<object> suffixList)
{
    suffixList.Clear();
    foreach (var str in list)
    {
        //操作数
        if (float.TryParse(str, out float result))
        {
            OperandStack.Push(result);
        }
        else if (IsOperation(str))//操作符
        {
            var operation = CreateOperation(str);
            while (true)
            {
                if (OperatorStack.Count == 0 || (OperatorStack.Peek() as LeftBracket != null))
                {
                    OperatorStack.Push(operation);
                    break;
                }
                else if (operation.Priority > OperatorStack.Peek().Priority)
                {
                    OperatorStack.Push(operation);
                    break;
                }
                else
                {
                    OperandStack.Push(OperatorStack.Pop());
                }
            }
        }
        else if (str == "(")//左括号
        {
            var operation = CreateOperation(str);
            OperatorStack.Push(operation);
        }
        else if (str == ")")//右括号
        {
            object operatorA ;
            //当前栈顶元素不为空并且不是左括号
            while (OperatorStack.Count>0)
            {
                operatorA = OperatorStack.Pop();
                if ((operatorA as LeftBracket) == null)
                {
                    OperandStack.Push(operatorA);
                }
                else
                {
                    break;
                }
            }
        }
    }
    while(OperatorStack.Count>0)
    {
        OperandStack.Push(OperatorStack.Pop());
    }
    while(OperandStack.Count!=0)
    {
        suffixList.Insert(0,OperandStack.Pop());
    }
}
}
public interface IOperation
{
     void SetOperation(params float[] operands);
    float Calculate();
    int Priority { get; }
    int OperandCount { get; }
}
public abstract class Operation : IOperation
{
    protected float a, b;

    public virtual int Priority => 1;

    public virtual int OperandCount => 2;

    public abstract float Calculate();

    public void SetOperation(params float[] operands)
    {
        if (operands.Length < OperandCount)
            Debug.LogError($"赋值操作数长度不对,需要{OperandCount},赋值的{operands.Length}");
        this.a = operands[0];
        if (OperandCount > 1)
            this.b = operands[1];
    }
}
public class AddOperation : Operation
{
    
    public override float Calculate()
    {
        return a + b;
    }
}
public class SubOperation : Operation
{
   
    public override float Calculate()
    {
        return a - b;
    }
}
public class MultiplicationOperation : Operation
{
    public override int Priority => 2;
    public override float Calculate()
    {
        return a * b;
    }
}
public class DivisionOperation : Operation
{
    public override int Priority => 2;
    public override float Calculate()
    {
        if (b == 0)
            Debug.LogError("除法为0");
        return a / b;
    }
}
public class SinOperation : Operation
{
    public override int Priority => 3;
    public override int OperandCount => 1;
    public override float Calculate()
    {
        return Mathf.Sin(a*Mathf.Deg2Rad);
    }
}
public class CosOperation : Operation
{
    public override int Priority => 3;
    public override int OperandCount => 1;
    public override float Calculate()
    {
        return Mathf.Cos(a * Mathf.Deg2Rad);
    }
}
public class LeftBracket : Operation
{
    public override int Priority => 5;
    public override int OperandCount => 0;
    public override float Calculate()
    {
        return 0;
    }
}
public class RightBracket : Operation
{
    public override int Priority => 5;
    public override int OperandCount => 0;
    public override float Calculate()
    {
        return 0;
    }
}


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CalculatorUIPlane : MonoBehaviour
{
public Calculator calculator;
[SerializeField] private Text inputText, outputText;
void Start()
{
calculator = new Calculator();
calculator.onInputValueChange += InputCallback;
calculator.onOutputValueChange += OutputCallback;
OnInput(“0”);
}
private void OnDestroy()
{
calculator.onInputValueChange -= InputCallback;
calculator.onOutputValueChange -= OutputCallback;
}
void InputCallback(string inputStr)
{
inputText.text = inputStr;
}
void OutputCallback(string outputStr)
{
outputText.text = outputStr;
}
public void OnInput(string str)
{
calculator.Input(str);
}
public void OnOutput()
{
calculator.OutPut();
}
public void OnClear()
{
calculator.Clear();
}
public void OnBackspace()
{
calculator.Backspace();
}
}

UnityDemo网盘链接

链接:https://pan.baidu.com/s/1djTfbSgJKVno5gQAHvNk1Q
提取码:2222

Guess you like

Origin blog.csdn.net/weixin_44806700/article/details/120907510