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

目录
  • 一、前言
  • 二、效果图及源工程
  • 三、实现
    • 1.界面搭建
    • 2.代码实现
  • 四、后记

一、前言

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

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

二、效果图及源工程

效果图:

源工程

三、实现

1.界面搭建

所有的按钮摆放到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;
        }
    }
}

效果图如下:

四、后记

完整代码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( '!','-' );
        }
    }
}

到此这篇关于基于Unity制作一个简易的计算器的文章就介绍到这了,更多相关Unity计算器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • unity实现简单计算器

    本文实例为大家分享了unity实现简单计算器的具体代码,供大家参考,具体内容如下 using System.Text; using UnityEngine; using UnityEngine.UI; using DG.Tweening; using System; public class Calculator : MonoBehaviour { public Text SpendText; private StringBuilder spendPrice;//初始金额 private str

  • Unity3D实战之答题系统的实现

    目录 一.前言 三.实现 1.界面搭建 2.读取文档 3.加载题目 4.按钮功能 5.题目对错判断 四.后言 一.前言 这是本专栏系列的第一篇,答题系统的开发. 这个答题系统,可以从文本文档中提取题目和分数,然后绑定到UI上,在答题的过程中,自动判断分数,自动判断正确率. 目的是实现一个可快速导入到项目中使用的小模块. 二.效果图及工程下载 题目文档  密码:47z2 源工程 三.实现 1.界面搭建 首先,新建工程,然后摆UI,如下图所示: 2.读取文档 题目存放在txt文档中,首先,我们看一下

  • 基于Unity3D实现3D照片墙效果

    一.前言 Unity3D不仅仅可以开发游戏,还有非常多的开发方向,秉承着兴趣为先,将可以使用Unity制作的各种应用案例,分享如何进行开发,如何实现,希望大家可以在感兴趣的地方,学习到自己想要学习的东西. 今天就来实现一个3D照片墙的效果. 我对于这个项目的构思就是照片是3D的,可以滑动,然后使用DoTween插件去做动画平滑移动. OK,那就正式开始. 先看一下效果图: 二.正式开发 新建项目,我使用的版本是Unity3D 2019.4.7f1,模板选用3D: (1)导入DoTween插件.

  • Unity使用多态制作计算器功能

    本文实例为大家分享了Unity使用多态制作计算器,供大家参考,具体内容如下 Unity中需要的组件 在Unity中创建两个InputField,一个Dropdown,一个Button和一个Text 创建脚本文件 计算父类 using System.Collections; using System.Collections.Generic; using UnityEngine; public class Jsq : MonoBehaviour { public abstract class Cal

  • 基于Unity编写一个九宫格抽奖软件

    目录 一.前言 二.效果图 三.案例制作 1.界面搭建 2.代码编写 3.效果演示 四.后言 一.前言 本博文标题和内容参考:基于原生JS实现H5转盘游戏 博主将改编成Unity版本. 二.效果图 三.案例制作 1.界面搭建 使用了9个图片作为奖品栏,然后一个chooseBox作为蒙版,一个StartBtn开始按钮放在中间 2.代码编写 新建脚本goLuckyDraw.cs 使用DoTween插件做动画,没有导入这个插件的下载导入一下 实现抽奖,主要有两个方面,一个是概率的设置,一个是动画 动画

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

    目录 一.前言 二.效果图及源工程 三.实现 1.界面搭建 2.代码实现 四.后记 一.前言 Hello,又见面了,今天分享如何使用Unity制作计算器,难度中等,可以用来学习,或者当成其他项目的小组件导入. 当然,也可以导出来,发布到网页端,来做一个嵌入式工具也可以. 二.效果图及源工程 效果图: 源工程 三.实现 1.界面搭建 所有的按钮摆放到Background下面. 2.代码实现 首先找到所有的按钮,添加到事件: //结果显示 TextComputeProcess = GameObjec

  • 基于QT制作一个简易的传输文件小工具

    最近因为一个事情很恼火,因为办公需要用到企业微信,但是企业微信只能在一个电脑上登陆,所以当别人发文件给你的时候,你只能一个电脑接收,创建共享文件夹也很麻烦,每次都需要去访问,很麻烦.所以准备自己写一个文件传输小工具. 功能就是能实现文件的双向传输,即客户端能传给服务端,服务端可以传给客户端. 使用的tcp通信,其实就是发消息,但是组合数据我是借鉴了IT1995大神写的代码. 先看下效果图 可以看到既可以接受文件也可进行发送文件,只要2台电脑在统一局域网内,就可发送和接受数据. 本地文件下出现了一

  • 基于Java制作一个简易的远控终端

    目录 远控终端的本质 Java制作简易的远控 1.环境 2.新建项目 3.新建一个Java类 4.编写程序 5.将项目打包成jar包并生成exe文件 附完整代码 远控终端的本质 1.服务端(攻击者)传输消息 ----> socket连接 ----> 客户端(被攻击者)接收消息 2.客户端执行消息内容(即执行服务端传回来的命令) 3.客户端传输执行结果 ----> socket连接 ----> 服务端显示命令执行结果 Java制作简易的远控 1.环境 环境:IntelliJ IDEA

  • Unity利用XML制作一个简易的登录系统

    通过XML文件保存账号密码,存储到本地,不连接数据库的简易登录系统. 1.创建一个XML文件,设置一个初始的账号密码. public void Creat() { localPath = UnityEngine.Application.streamingAssetsPath + "/" + "MyXML.xml"; if (!File.Exists(localPath)) { XmlDocument xml = new XmlDocument(); XmlDecla

  • 详解基于electron制作一个node压缩图片的桌面应用

    基于electron制作一个node压缩图片的桌面应用 下载地址:https://github.com/zenoslin/imagemin-electron/releases 项目源码Github:https://github.com/zenoslin/imagemin-electron 准备工作 我们来整理一下我们需要做什么: 压缩图片模块 获取文件路径 桌面应用生成 压缩图片 我们需要使用imagemin这个库来压缩图片,这里我们把这个库封装成压缩模块. const imagemin = r

  • js实现一个简易的计算器

    利用原生js实现一个简易的计算器(附详细注释),供大家参考,具体内容如下 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title&

  • 基于 Mysql 实现一个简易版搜索引擎

    目录 基于 Mysql 实现一个搜索引擎 一.ngram 全文解析器 二.创建全文索引 1.建表时创建全文索引 2.通过 alter table 方式 3.通过 create index 方式 三.检索方式 1.自然语言检索(NATURAL LANGUAGE MODE) 四.与 Like 对比 基于 Mysql 实现一个搜索引擎 前言: 其实 Mysql 很早就支持全文索引了,只不过一直只支持英文的检索,从5.7.6 版本开始,Mysql 就内置了 ngram 全文解析器,用来支持中文.日文.韩

  • Unity 制作一个分数统计系统

    项目中经常遇到分数统计的需求,例如我们执行了某项操作或做了某个题目,操作正确则计分,相反则不计分失去该项分数,为了应对需求需要一个分数统计系统. 首先定义一个分数信息的数据结构,使用Serializable特性使其可序列化: using System; using UnityEngine; namespace SK.Framework { /// <summary> /// 分数信息 /// </summary> [Serializable] public class ScoreI

  • 基于Python实现一个简易的数据管理系统

    目录 创建mysql数据表 增删改查 启动应用  为了方便的实现记录数据.修改数据没有精力去做一个完整的系统去管理数据.因此,在python的控制台直接实现一个简易的数据管理系统,包括数据的增删改查等等.只需要在控制台层面调用相应的功能调用查询.修改等功能,这里记录一下实现过程. 创建mysql数据表 使用比较熟悉的数据库客户端来进行操作,这里使用的是navicate客户端来创建好相应的数据表. 创建数据库并指定编码字符集. CREATE DATABASE `data_boc` CHARACTE

随机推荐