基于Unity制作一个简易的计算器

作者:恬静的小魔龙 时间:2023-02-18 10:02:39 

一、前言

Hello,又见面了,今天分享如何使用Unity制作计算器,难度中等,可以用来学习,或者当成其他项目的小组件导入。

当然,也可以导出来,发布到网页端,来做一个嵌入式工具也可以。

二、效果图及源工程

效果图:

基于Unity制作一个简易的计算器

源工程

三、实现

1.界面搭建

基于Unity制作一个简易的计算器

基于Unity制作一个简易的计算器

所有的按钮摆放到Background下面。

2.代码实现

首先找到所有的按钮,添加到事件:

//结果显示
       TextComputeProcess = GameObject.Find("Canvas/Background/Image/TextComputeProcess").GetComponent<Text>();
       TextComputeResult = GameObject.Find("Canvas/Background/Image/TextComputeResult").GetComponent<Text>();
       TextComputeResult.text = "0";
       RUNSTATE = 0;

//操作
       BtnReset = GameObject.Find("Canvas/Background/重置").GetComponent<Button>();
       BtnReset.onClick.AddListener(() => OperationDispose("CE"));
       BtnDelete = GameObject.Find("Canvas/Background/删除").GetComponent<Button>();
       BtnDelete.onClick.AddListener(() => OperationDispose("Del"));

//加减乘除
       BtnAdd = GameObject.Find("Canvas/Background/加").GetComponent<Button>();
       BtnAdd.onClick.AddListener(() => OperationDispose("+"));
       BtnSub = GameObject.Find("Canvas/Background/减").GetComponent<Button>();
       BtnSub.onClick.AddListener(() => OperationDispose("-"));
       BtnMul = GameObject.Find("Canvas/Background/乘").GetComponent<Button>();
       BtnMul.onClick.AddListener(() => OperationDispose("*"));
       BtnDiv = GameObject.Find("Canvas/Background/除").GetComponent<Button>();
       BtnDiv.onClick.AddListener(() => OperationDispose("/"));
       BtnEqual = GameObject.Find("Canvas/Background/等于").GetComponent<Button>();
       BtnEqual.onClick.AddListener(() => OperationDispose("="));

//数字
       Btn0 = GameObject.Find("Canvas/Background/0").GetComponent<Button>();
       Btn0.onClick.AddListener(() => NumDispose("0"));
       Btn1 = GameObject.Find("Canvas/Background/1").GetComponent<Button>();
       Btn1.onClick.AddListener(() => NumDispose("1"));
       Btn2 = GameObject.Find("Canvas/Background/2").GetComponent<Button>();
       Btn2.onClick.AddListener(() => NumDispose("2"));
       Btn3 = GameObject.Find("Canvas/Background/3").GetComponent<Button>();
       Btn3.onClick.AddListener(() => NumDispose("3"));
       Btn4 = GameObject.Find("Canvas/Background/4").GetComponent<Button>();
       Btn4.onClick.AddListener(() => NumDispose("4"));
       Btn5 = GameObject.Find("Canvas/Background/5").GetComponent<Button>();
       Btn5.onClick.AddListener(() => NumDispose("5"));
       Btn6 = GameObject.Find("Canvas/Background/6").GetComponent<Button>();
       Btn6.onClick.AddListener(() => NumDispose("6"));
       Btn7 = GameObject.Find("Canvas/Background/7").GetComponent<Button>();
       Btn7.onClick.AddListener(() => NumDispose("7"));
       Btn8 = GameObject.Find("Canvas/Background/8").GetComponent<Button>();
       Btn8.onClick.AddListener(() => NumDispose("8"));
       Btn9 = GameObject.Find("Canvas/Background/9").GetComponent<Button>();
       Btn9.onClick.AddListener(() => NumDispose("9"));
       BtnPoint = GameObject.Find("Canvas/Background/点").GetComponent<Button>();
       BtnPoint.onClick.AddListener(() => NumDispose("."));
       BtnPm = GameObject.Find("Canvas/Background/正负").GetComponent<Button>();
       BtnPm.onClick.AddListener(() => NumDispose("-"));

按钮操作:

//操作点击处理
   private void OperationDispose(string operation)
   {
       switch (operation)
       {
           case "+":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 + ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " + ";
                   m_operation = "+";
                   RUNSTATE = 2;
               }
               break;
           case "-":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 - ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " - ";
                   m_operation = "-";
                   RUNSTATE = 2;
               }
               break;
           case "*":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 * ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " * ";
                   m_operation = "*";
                   RUNSTATE = 2;
               }
               break;
           case "/":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 / ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " / ";
                   m_operation = "/";
                   RUNSTATE = 2;
               }
               break;
           case "=":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 = ";
               else
               {
                   if (RUNSTATE == 3)
                   {
                       double result;
                       switch (m_operation)
                       {
                           case "+":
                               result = double.Parse(calculateString) + double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " + " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           case "-":
                               result = double.Parse(calculateString) - double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " - " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           case "*":
                               result = double.Parse(calculateString) * double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " * " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           case "/":
                               result = double.Parse(calculateString) / double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " / " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           default:
                               break;
                       }
                   }
                   else
                   {
                       TextComputeProcess.text = TextComputeResult.text + " = ";
                   }
               }
               break;
           case "CE":
               TextComputeProcess.text = "";
               TextComputeResult.text = "0";
               RUNSTATE = 0;
               break;
           case "Del":
               if (RUNSTATE == 0)
                   return;
               else
               {
                   if (TextComputeResult.text.Length == 1)
                   {
                       TextComputeResult.text = "0";
                   }
                   else
                   {
                       TextComputeResult.text = TextComputeResult.text.Remove(TextComputeResult.text.Length - 1, 1);
                   }
               }
               break;
           default:
               break;
       }
   }

数字点击处理:

//数字点击处理
   private void NumDispose(string num)
   {
       switch (num)
       {
           case ".":
               if (RUNSTATE == 0)
                   TextComputeResult.text = "0";
               else
                   TextComputeResult.text += num;
               break;
           case "-":
               if (RUNSTATE == 0)
                   TextComputeResult.text = "0";
               else
               {
                   if (RUNSTATE == 1)
                   {
                       if (pmState)
                       {
                           TextComputeResult.text = TextComputeResult.text.Remove(0, 1);
                           pmState = false;
                       }
                       else
                       {
                           TextComputeResult.text = num + TextComputeResult.text;
                           pmState = true;
                       }
                   }
                   else if (RUNSTATE == 2)
                   {
                       pmState = false;
                   }
                   else if (RUNSTATE == 3)
                   {
                       if (pmState)
                       {
                           TextComputeResult.text = TextComputeResult.text.Remove(0, 1);
                           pmState = false;
                       }
                       else
                       {
                           TextComputeResult.text = num + TextComputeResult.text;
                           pmState = true;
                       }
                   }
                   else if (RUNSTATE == 4)
                   {
                       pmState = false;
                       OperationDispose("CE");
                   }
               }
               break;
           default:
               if (RUNSTATE == 0)
               {
                   TextComputeResult.text = num;
                   RUNSTATE = 1;
               }
               else if (RUNSTATE == 1)
               {
                   pmState = false;
                   TextComputeResult.text += num;
               }
               else if (RUNSTATE == 2)
               {
                   calculateString = TextComputeResult.text;
                   TextComputeResult.text = "";
                   TextComputeResult.text += num;
                   RUNSTATE = 3;
               }
               else if (RUNSTATE == 3)
               {
                   TextComputeResult.text += num;
               }
               else if (RUNSTATE == 4)
               {
                   OperationDispose("CE");
                   TextComputeResult.text = num;
                   RUNSTATE = 1;
               }
               break;
       }
   }

完整代码:

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

public class CalculatorControl : MonoBehaviour
{
   private Text TextComputeProcess;//计算过程
   private Text TextComputeResult;//计算结果

private Button BtnReset;
   private Button BtnDelete;
   private Button BtnAdd;
   private Button BtnSub;
   private Button BtnMul;
   private Button BtnDiv;
   private Button BtnEqual;

private Button Btn0, Btn1, Btn2, Btn3, Btn4, Btn5, Btn6, Btn7, Btn8, Btn9;
   private Button BtnPoint, BtnPm;

private string calculateString = "";//计算数
   private string m_operation = "";//操作数
   private bool pmState = false;//正负状态
   private int RUNSTATE = 0;//0 默认 1 输入数字 2 输入操作符 3 输入操作符再输入数字 4 计算结果后

void Start()
   {
       //结果显示
       TextComputeProcess = GameObject.Find("Canvas/Background/Image/TextComputeProcess").GetComponent<Text>();
       TextComputeResult = GameObject.Find("Canvas/Background/Image/TextComputeResult").GetComponent<Text>();
       TextComputeResult.text = "0";
       RUNSTATE = 0;

//操作
       BtnReset = GameObject.Find("Canvas/Background/重置").GetComponent<Button>();
       BtnReset.onClick.AddListener(() => OperationDispose("CE"));
       BtnDelete = GameObject.Find("Canvas/Background/删除").GetComponent<Button>();
       BtnDelete.onClick.AddListener(() => OperationDispose("Del"));

//加减乘除
       BtnAdd = GameObject.Find("Canvas/Background/加").GetComponent<Button>();
       BtnAdd.onClick.AddListener(() => OperationDispose("+"));
       BtnSub = GameObject.Find("Canvas/Background/减").GetComponent<Button>();
       BtnSub.onClick.AddListener(() => OperationDispose("-"));
       BtnMul = GameObject.Find("Canvas/Background/乘").GetComponent<Button>();
       BtnMul.onClick.AddListener(() => OperationDispose("*"));
       BtnDiv = GameObject.Find("Canvas/Background/除").GetComponent<Button>();
       BtnDiv.onClick.AddListener(() => OperationDispose("/"));
       BtnEqual = GameObject.Find("Canvas/Background/等于").GetComponent<Button>();
       BtnEqual.onClick.AddListener(() => OperationDispose("="));

//数字
       Btn0 = GameObject.Find("Canvas/Background/0").GetComponent<Button>();
       Btn0.onClick.AddListener(() => NumDispose("0"));
       Btn1 = GameObject.Find("Canvas/Background/1").GetComponent<Button>();
       Btn1.onClick.AddListener(() => NumDispose("1"));
       Btn2 = GameObject.Find("Canvas/Background/2").GetComponent<Button>();
       Btn2.onClick.AddListener(() => NumDispose("2"));
       Btn3 = GameObject.Find("Canvas/Background/3").GetComponent<Button>();
       Btn3.onClick.AddListener(() => NumDispose("3"));
       Btn4 = GameObject.Find("Canvas/Background/4").GetComponent<Button>();
       Btn4.onClick.AddListener(() => NumDispose("4"));
       Btn5 = GameObject.Find("Canvas/Background/5").GetComponent<Button>();
       Btn5.onClick.AddListener(() => NumDispose("5"));
       Btn6 = GameObject.Find("Canvas/Background/6").GetComponent<Button>();
       Btn6.onClick.AddListener(() => NumDispose("6"));
       Btn7 = GameObject.Find("Canvas/Background/7").GetComponent<Button>();
       Btn7.onClick.AddListener(() => NumDispose("7"));
       Btn8 = GameObject.Find("Canvas/Background/8").GetComponent<Button>();
       Btn8.onClick.AddListener(() => NumDispose("8"));
       Btn9 = GameObject.Find("Canvas/Background/9").GetComponent<Button>();
       Btn9.onClick.AddListener(() => NumDispose("9"));
       BtnPoint = GameObject.Find("Canvas/Background/点").GetComponent<Button>();
       BtnPoint.onClick.AddListener(() => NumDispose("."));
       BtnPm = GameObject.Find("Canvas/Background/正负").GetComponent<Button>();
       BtnPm.onClick.AddListener(() => NumDispose("-"));
   }

//操作点击处理
   private void OperationDispose(string operation)
   {
       switch (operation)
       {
           case "+":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 + ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " + ";
                   m_operation = "+";
                   RUNSTATE = 2;
               }
               break;
           case "-":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 - ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " - ";
                   m_operation = "-";
                   RUNSTATE = 2;
               }
               break;
           case "*":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 * ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " * ";
                   m_operation = "*";
                   RUNSTATE = 2;
               }
               break;
           case "/":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 / ";
               else
               {
                   TextComputeProcess.text = TextComputeResult.text + " / ";
                   m_operation = "/";
                   RUNSTATE = 2;
               }
               break;
           case "=":
               if (RUNSTATE == 0)
                   TextComputeProcess.text = "0 = ";
               else
               {
                   if (RUNSTATE == 3)
                   {
                       double result;
                       switch (m_operation)
                       {
                           case "+":
                               result = double.Parse(calculateString) + double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " + " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           case "-":
                               result = double.Parse(calculateString) - double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " - " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           case "*":
                               result = double.Parse(calculateString) * double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " * " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           case "/":
                               result = double.Parse(calculateString) / double.Parse(TextComputeResult.text);
                               TextComputeProcess.text = calculateString + " / " + TextComputeResult.text + " = ";
                               TextComputeResult.text = result.ToString();
                               RUNSTATE = 4;
                               break;
                           default:
                               break;
                       }
                   }
                   else
                   {
                       TextComputeProcess.text = TextComputeResult.text + " = ";
                   }
               }
               break;
           case "CE":
               TextComputeProcess.text = "";
               TextComputeResult.text = "0";
               RUNSTATE = 0;
               break;
           case "Del":
               if (RUNSTATE == 0)
                   return;
               else
               {
                   if (TextComputeResult.text.Length == 1)
                   {
                       TextComputeResult.text = "0";
                   }
                   else
                   {
                       TextComputeResult.text = TextComputeResult.text.Remove(TextComputeResult.text.Length - 1, 1);
                   }
               }
               break;
           default:
               break;
       }
   }

//数字点击处理
   private void NumDispose(string num)
   {
       switch (num)
       {
           case ".":
               if (RUNSTATE == 0)
                   TextComputeResult.text = "0";
               else
                   TextComputeResult.text += num;
               break;
           case "-":
               if (RUNSTATE == 0)
                   TextComputeResult.text = "0";
               else
               {
                   if (RUNSTATE == 1)
                   {
                       if (pmState)
                       {
                           TextComputeResult.text = TextComputeResult.text.Remove(0, 1);
                           pmState = false;
                       }
                       else
                       {
                           TextComputeResult.text = num + TextComputeResult.text;
                           pmState = true;
                       }
                   }
                   else if (RUNSTATE == 2)
                   {
                       pmState = false;
                   }
                   else if (RUNSTATE == 3)
                   {
                       if (pmState)
                       {
                           TextComputeResult.text = TextComputeResult.text.Remove(0, 1);
                           pmState = false;
                       }
                       else
                       {
                           TextComputeResult.text = num + TextComputeResult.text;
                           pmState = true;
                       }
                   }
                   else if (RUNSTATE == 4)
                   {
                       pmState = false;
                       OperationDispose("CE");
                   }
               }
               break;
           default:
               if (RUNSTATE == 0)
               {
                   TextComputeResult.text = num;
                   RUNSTATE = 1;
               }
               else if (RUNSTATE == 1)
               {
                   pmState = false;
                   TextComputeResult.text += num;
               }
               else if (RUNSTATE == 2)
               {
                   calculateString = TextComputeResult.text;
                   TextComputeResult.text = "";
                   TextComputeResult.text += num;
                   RUNSTATE = 3;
               }
               else if (RUNSTATE == 3)
               {
                   TextComputeResult.text += num;
               }
               else if (RUNSTATE == 4)
               {
                   OperationDispose("CE");
                   TextComputeResult.text = num;
                   RUNSTATE = 1;
               }
               break;
       }
   }
}

效果图如下:

基于Unity制作一个简易的计算器

四、后记

完整代码278行,还是依旧那么简练,整体代码难度不大,主要是状态之间的切换:

1、输入数字的状态

2、输入操作符状态

3、输入操作符后再输入数字状态

4、计算结果后状态

理解这些状态后,代码就容易理解了。

最后,拓展一下,将其他大佬写的代码给大家看一下,大家如果觉得上面的代码太简单,可以看一下:

代码使用OnGUI搭建界面,直接拖到任意对象上就可以看到效果了:

using UnityEngine;
using System.Text.RegularExpressions;
using System;

public class Calculator2 : MonoBehaviour
{
   public static bool IsNumeric(string value)
   {
       return Regex.IsMatch(value, @"^[+-]?\d*[.]?\d*$");
   }

public string result = "";//用来显示结果
   public static string str1 = "";//第一个操作数
   public static bool haveDot = false;//第二个操作数
   public static bool isCaclutate = false;

void OnGUI()
   {
       //对数字进行处理
       if (GUI.Button(new Rect(100, 100, 100, 60), "CE"))
       {
           result = "";
           str1 = "";
           haveDot = false;
       }
       if (GUI.Button(new Rect(210, 100, 100, 60), "×") && str1.Substring(str1.Length - 1, 1) != "-" && str1.Substring(str1.Length - 1, 1) != "+" && str1.Substring(str1.Length - 1, 1) != ".")
       {
           if (IsNumeric(str1.Substring(str1.Length - 1, 1)))
           {
               Debug.Log(str1.Substring(str1.Length - 1, 1));
               str1 += "*";
               haveDot = false;
               isCaclutate = false;
           }
           result = str1;
       }
       if (GUI.Button(new Rect(320, 100, 100, 60), "÷") && str1.Substring(str1.Length - 1, 1) != "-" && str1.Substring(str1.Length - 1, 1) != "+" && str1.Substring(str1.Length - 1, 1) != ".")
       {
           if (IsNumeric(str1.Substring(str1.Length - 1, 1)))
           {
               str1 += "/";
               haveDot = false;
               isCaclutate = false;
           }
           result = str1;
       }
       if (GUI.Button(new Rect(430, 100, 100, 60), "←"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
           }
           else if (result.Length != 0)
           {
               str1 = str1.Substring(0, str1.Length - 1);
           }
           result = str1;
       }
       if (GUI.Button(new Rect(100, 170, 100, 60), "1"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "1";
           result = str1;
       }
       if (GUI.Button(new Rect(210, 170, 100, 60), "2"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "2";
           result = str1;
       }
       if (GUI.Button(new Rect(320, 170, 100, 60), "3"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "3";
           result = str1;
       }
       if (GUI.Button(new Rect(430, 170, 100, 60), "-"))
       {
           if (IsNumeric(str1.Substring(str1.Length - 1, 1)) && str1.Substring(str1.Length - 1, 1) != "-" && str1.Substring(str1.Length - 1, 1) != "+" && str1.Substring(str1.Length - 1, 1) != ".")
           {
               str1 += "-";
               haveDot = false;
               isCaclutate = false;
           }
           result = str1;
       }
       if (GUI.Button(new Rect(100, 240, 100, 60), "4"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "4";
           result = str1;
       }
       if (GUI.Button(new Rect(210, 240, 100, 60), "5"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "5";
           result = str1;
       }
       if (GUI.Button(new Rect(320, 240, 100, 60), "6"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "6";
           result = str1;
       }
       if (GUI.Button(new Rect(430, 240, 100, 60), "+") && str1.Substring(str1.Length - 1, 1) != "+" && str1.Substring(str1.Length - 1, 1) != "-" && str1.Substring(str1.Length - 1, 1) != ".")
       {
           if (IsNumeric(str1.Substring(str1.Length - 1, 1)))
           {
               str1 += "+";
               haveDot = false;
               isCaclutate = false;
           }
           result = str1;
       }
       if (GUI.Button(new Rect(100, 310, 100, 60), "7"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "7";
           result = str1;
       }
       if (GUI.Button(new Rect(210, 310, 100, 60), "8"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "8";
           result = str1;
       }
       if (GUI.Button(new Rect(320, 310, 100, 60), "9"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "9";
           result = str1;
       }
       if (GUI.Button(new Rect(430, 310, 100, 130), "="))
       {

var tmp = Evaluator.Eval(result);
           Debug.Log(tmp.ToString());
           result = tmp.ToString();
           str1 = result;
           isCaclutate = true;
           if (result.Contains("."))
           {
               haveDot = true;
           }
       }
       if (GUI.Button(new Rect(100, 380, 210, 60), "0"))
       {
           if (isCaclutate == true)
           {
               str1 = "";
               isCaclutate = false;
               haveDot = false;
           }
           str1 += "0";
           result = str1;
       }

if (GUI.Button(new Rect(320, 380, 100, 60), "."))
       {
           if (isCaclutate == true)
           {
               str1 = "0.";
               isCaclutate = false;
           }
           if (IsNumeric(str1.Substring(str1.Length - 1, 1)) && str1.Substring(str1.Length - 1, 1) != "." && haveDot == false)
           {
               Debug.Log(str1.Substring(str1.Length - 1, 1));
               str1 += ".";
               haveDot = true;
               isCaclutate = false;
           }
           result = str1;
       }
       GUI.TextArea(new Rect(100, 20, 430, 60), result);
   }

/**/
   /// <summary>
   /// 动态求值
   /// </summary>
   public class Evaluator
   {
       /**/
       /// <summary>
       /// 计算结果,如果表达式出错则抛出异常
       /// </summary>
       /// <param name="statement">表达式,如"1+2+3+4"</param>
       /// <returns>结果</returns>
       public static object Eval(string statement)
       {
           if (statement.Trim() != string.Empty)
           {
               Evaluator evaluator = new Evaluator();
               return evaluator.GetFormulaResult(statement);
           }
           else
           {
               return null;
           }
       }

private object GetFormulaResult(string s)
       {
           if (s == "")
           {
               return null;
           }
           string S = BuildingRPN(s);

string tmp = "";
           System.Collections.Stack sk = new System.Collections.Stack();

char c = ' ';
           System.Text.StringBuilder Operand = new System.Text.StringBuilder();
           double x, y;
           for (int i = 0; i < S.Length; i++)
           {
               c = S[i];
               //added c==',' for germany culture
               if (char.IsDigit(c) || c == '.' || c == ',')
               {
                   //数据值收集.
                   Operand.Append(c);
               }
               else if (c == ' ' && Operand.Length > 0)
               {
                   #region 运算数转换
                   try
                   {
                       tmp = Operand.ToString();
                       if (tmp.StartsWith("-"))//负数的转换一定要小心...它不被直接支持.
                       {
                           //现在我的算法里这个分支可能永远不会被执行.
                           sk.Push(-((double)Convert.ToDouble(tmp.Substring(1, tmp.Length - 1))));
                       }
                       else
                       {
                           sk.Push(Convert.ToDouble(tmp));
                       }
                   }
                   catch
                   {
                       return null; //
                   }
                   Operand = new System.Text.StringBuilder();
                   #endregion
               }
               else if (c == '+'//运算符处理.双目运算处理.
                   || c == '-'
                   || c == '*'
                   || c == '/'
                   || c == '%'
                   || c == '^')
               {
                   #region 双目运算
                   if (sk.Count > 0)/*如果输入的表达式根本没有包含运算符.或是根本就是空串.这里的逻辑就有意义了.*/
                   {
                       y = (double)sk.Pop();
                   }
                   else
                   {
                       sk.Push(0);
                       break;
                   }
                   if (sk.Count > 0)
                       x = (double)sk.Pop();
                   else
                   {
                       sk.Push(y);
                       break;
                   }
                   switch (c)
                   {
                       case '+':
                           sk.Push(x + y);
                           break;
                       case '-':
                           sk.Push(x - y);
                           break;
                       case '*':
                           if (y == 0)
                           {
                               sk.Push(x * 1);
                           }
                           else
                           {
                               sk.Push(x * y);
                           }
                           break;
                       case '/':
                           if (y == 0)
                           {
                               sk.Push(x / 0);
                           }
                           else
                           {
                               sk.Push(x / y);
                           }
                           break;
                       case '%':
                           sk.Push(x % y);
                           break;
                       case '^'://
                           if (x > 0)//
                           {
                               //我原本还想,如果被计算的数是负数,又要开真分数次方时如何处理的问题.后来我想还是算了吧.
                               sk.Push(System.Math.Pow(x, y));
                               //
                           }
                           //
                           else//
                           {
                               //
                               double t = y;
                               //
                               string ts = "";
                               //
                               t = 1 / (2 * t);
                               //
                               ts = t.ToString();
                               //
                               if (ts.ToUpper().LastIndexOf('E') > 0)//
                               {
                                   //
                                   ;
                                   //
                               }
                               //
                           }
                           break;
                   }
                   #endregion
               }
               else if (c == '!')//单目取反. )
               {
                   sk.Push(-((double)sk.Pop()));
               }
           }
           if (sk.Count > 1)
           {
               return null;//;
           }
           if (sk.Count == 0)
           {
               return null;//;
           }
           return sk.Pop();
       }
       /**/
       /// <summary>
       ///
       /// </summary>
       private string BuildingRPN(string s)
       {
           System.Text.StringBuilder sb = new System.Text.StringBuilder(s);
           System.Collections.Stack sk = new System.Collections.Stack();
           System.Text.StringBuilder re = new System.Text.StringBuilder();

char c = ' ';
           //sb.Replace( " ","" );
           //一开始,我只去掉了空格.后来我不想不支持函数和常量能滤掉的全OUT掉.
           for (int i = 0; i < sb.Length; i++)
           {
               c = sb[i];
               //added c==',' for german culture
               if (char.IsDigit(c) || c == ',')//数字当然要了.
                   re.Append(c);
               //if( char.IsWhiteSpace( c )||
               char.IsLetter(c);//如果是空白,那么不要.现在字母也不要.
               //continue;
               switch (c)//如果是其它字符...列出的要,没有列出的不要.
               {
                   case '+':
                   case '-':
                   case '*':
                   case '/':
                   case '%':
                   case '^':
                   case '!':
                   case '(':
                   case ')':
                   case '.':
                       re.Append(c);
                       break;
                   default:
                       continue;
               }
           }
           sb = new System.Text.StringBuilder(re.ToString());
           #region 对负号进行预转义处理.负号变单目运算符求反.
           for (int i = 0; i < sb.Length - 1; i++)
               if (sb[i] == '-' && (i == 0 || sb[i - 1] == '('))
                   sb[i] = '!';
           //字符转义.
           #endregion
           #region 将中缀表达式变为后缀表达式.
           re = new System.Text.StringBuilder();
           for (int i = 0;
               i < sb.Length;
               i++)
           {
               if (char.IsDigit(sb[i]) || sb[i] == '.')//如果是数值.
               {
                   re.Append(sb[i]);
                   //加入后缀式
               }
               else if (sb[i] == '+'
                   || sb[i] == '-'
                   || sb[i] == '*'
                   || sb[i] == '/'
                   || sb[i] == '%'
                   || sb[i] == '^'
                   || sb[i] == '!')//.
               {
                   #region 运算符处理
                   while (sk.Count > 0) //栈不为空时
                   {
                       c = (char)sk.Pop();
                       //将栈中的操作符弹出.
                       if (c == '(') //如果发现左括号.停.
                       {
                           sk.Push(c);
                           //将弹出的左括号压回.因为还有右括号要和它匹配.
                           break;
                           //中断.
                       }
                       else
                       {
                           if (Power(c) < Power(sb[i]))//如果优先级比上次的高,则压栈.
                           {
                               sk.Push(c);
                               break;
                           }
                           else
                           {
                               re.Append(' ');
                               re.Append(c);
                           }
                           //如果不是左括号,那么将操作符加入后缀式中.
                       }
                   }
                   sk.Push(sb[i]);
                   //把新操作符入栈.
                   re.Append(' ');
                   #endregion
               }
               else if (sb[i] == '(')//基本优先级提升
               {
                   sk.Push('(');
                   re.Append(' ');
               }
               else if (sb[i] == ')')//基本优先级下调
               {
                   while (sk.Count > 0) //栈不为空时
                   {
                       c = (char)sk.Pop();
                       //pop Operator
                       if (c != '(')
                       {
                           re.Append(' ');
                           re.Append(c);
                           //加入空格主要是为了防止不相干的数据相临产生解析错误.
                           re.Append(' ');
                       }
                       else
                           break;
                   }
               }
               else
                   re.Append(sb[i]);
           }
           while (sk.Count > 0)//这是最后一个弹栈啦.
           {
               re.Append(' ');
               re.Append(sk.Pop());
           }
           #endregion
           re.Append(' ');
           return FormatSpace(re.ToString());
           //在这里进行一次表达式格式化.这里就是后缀式了.  
       }

/// <summary>  
       /// 优先级别测试函数.  
       /// </summary>  
       /// <param name="opr"></param>  
       /// <returns></returns>  
       private static int Power(char opr)
       {
           switch (opr)
           {
               case '+':
               case '-':
                   return 1;
               case '*':
               case '/':
                   return 2;
               case '%':
               case '^':
               case '!':
                   return 3;
               default:
                   return 0;
           }
       }

/// <summary>  
       /// 规范化逆波兰表达式.
       /// </summary>  
       /// <param name="s"></param>  
       /// <returns></returns>  
       private static string FormatSpace(string s)
       {
           System.Text.StringBuilder ret = new System.Text.StringBuilder();
           for (int i = 0; i < s.Length; i++)
           {
               if (!(s.Length > i + 1 && s[i] == ' ' && s[i + 1] == ' '))
                   ret.Append(s[i]);
               else
                   ret.Append(s[i]);
           }
           return ret.ToString();
           //.Replace( '!','-' );
       }
   }
}

来源:https://itmonon.blog.csdn.net/article/details/117370619

标签:Unity,计算器
0
投稿

猜你喜欢

  • springboot2.x整合tkmapper的示例代码

    2021-09-19 11:56:59
  • Android权限管理之Permission权限机制及使用详解

    2023-04-07 09:12:45
  • C#简单实现防止多个程序运行的方法

    2021-07-31 04:36:27
  • Java上传文件错误java.lang.NoSuchMethodException的解决办法

    2023-11-10 13:15:43
  • C#通过流写入一行数据到文件的方法

    2023-08-22 13:04:08
  • C#委托与匿名委托详解

    2023-02-24 21:12:41
  • 详解Android数据存储—使用SQLite数据库

    2023-07-31 03:14:08
  • unity实现场景切换进度条显示

    2022-05-16 20:56:42
  • Android 使用maven publish插件发布产物(aar)流程实践

    2023-03-04 18:07:45
  • Springboot+SpringSecurity+JWT实现用户登录和权限认证示例

    2021-11-14 11:06:11
  • Java SpringBoot实现带界面的代码生成器详解

    2023-09-28 11:54:14
  • Android自定义控件实现圆形进度条

    2023-02-02 05:01:59
  • C#实现简单的计算器小功能

    2023-05-13 06:46:11
  • Android Mms之:短信发送流程(图文详解)

    2022-07-27 02:10:21
  • Java Bean Validation使用示例详解

    2023-07-19 07:05:26
  • Android自定义View之渐变色折线图的实现

    2023-09-23 21:43:03
  • SpringBoot用@Async注解实现异步任务

    2023-08-07 06:36:09
  • java数据结构与算法之中缀表达式转为后缀表达式的方法

    2023-11-22 12:51:35
  • 如何更改Dialog的标题与按钮颜色详解

    2023-06-01 23:54:54
  • TabLayout标题文字不显示的解决操作

    2023-02-19 18:34:48
  • asp之家 软件编程 m.aspxhome.com