随机生成四则运算表达式【Unity】

根据自己项目需求调整代码中表达式的公共方法

 

using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
/// <summary>
/// 四则运算管理类
/// </summary>
public class FourArithmetic : Singleton<FourArithmetic>
{
    #region 表达式方法
    public string expression = "";
    /// <summary>
    /// 随机数加法表达式
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    public void RandomNumAdd(int min, int max)
    {
        expression = "";
        //System.Random ran = new System.Random();
        //int n1 = ran.Next(min, max);
        //int n2 = ran.Next(min, max);
        int n1 = UnityEngine.Random.Range(min, max);
        int n2 = UnityEngine.Random.Range(min, max);

        if (n1 < 0) expression += "(" + n1 + ")";
        else expression += n1;
        expression += "+";
        if (n2 < 0) expression += "(" + n2 + ")";
        else expression += n2;
    }

    /// <summary>
    /// 随机数减法表达式
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    public void RandomNumMinus(int min, int max)
    {
        expression = "";
        //System.Random ran = new System.Random();
        //int n1 = ran.Next(min, max);
        //int n2 = ran.Next(min, max);
        int n1 = UnityEngine.Random.Range(min, max);
        int n2 = UnityEngine.Random.Range(min, max);

        if (n1 > n2)
        {
            if (n1 < 0) expression += "(" + n1 + ")";
            else expression += n1;
            expression += "-";
            if (n2 < 0) expression += "(" + n2 + ")";
            else expression += n2;
        }
        else
        {
            RandomNumMinus(min, max);
        }
    }

    /// <summary>
    /// 随机数乘法表达式
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    public void RandomNumMultiply(int min, int max)
    {
        expression = "";
        //System.Random ran = new System.Random();
        //int n1 = ran.Next(min, max);
        //int n2 = ran.Next(0, 3);
        int  n1, n2;
        if (max > 10)
        {
             n1 = UnityEngine.Random.Range(min, max);
             n2 = UnityEngine.Random.Range(1, 3);
        }
        else 
        {
             n1 = UnityEngine.Random.Range(min, max);
             n2 = UnityEngine.Random.Range(min, max);
        }
        
        if (n1 < 0) expression += "(" + n1 + ")";
        else expression += n1;
        expression += "*";
        if (n2 < 0) expression += "(" + n2 + ")";
        else expression += n2;
    }

    /// <summary>
    /// 随机数除法表达式
    /// </summary>
    public void RandomNumDivide(int min, int max)
    {
        expression = "";
        //System.Random ran = new System.Random();
        //int n1 = ran.Next(min, max);
        //int n2 = ran.Next(min, max);
        int n1 = UnityEngine.Random.Range(min, max);
        int n2 = UnityEngine.Random.Range(1, 10);
        if (n1 < 0) expression += "(" + n1 + ")";
        else expression += n1;
        expression += "/";
        if (n2 < 0) expression += "(" + n2 + ")";
        else expression += n2;
    }

    /// <summary>
    /// 三个数以上四则运算混合计算表达式
    /// </summary>
    /// <param name="select">选择对应的表达式</param>
    /// <param name="min"></param>
    /// <param name="max"></param>
    public void MixedCalculation(int select, int min, int max)
    {
        System.Random ran = new System.Random();
        //int n1, n2;
        expression = "";
        switch (select)
        {
            case 0://带括号三个数字的混合计算
                {
                    int n1 = ran.Next(min, max);
                    int n2 = ran.Next(min, max);
                    int n3 = ran.Next(1, 3);
                    expression += "(";
                    if (n1 < 0) expression += "(" + n1 + "";
                    else expression += n1;
                    if (ran.Next(0, 2) == 1) expression += "+";
                    else expression += "-";
                    if (n2 < 0) expression += "(" + n2 + ")";
                    else expression += n2 + ")";
                    expression += "*" + n3;
                    break;
                }
            case 2: //三个数字的加减混合表达式
                {
                    int n1 = ran.Next(min, max);
                    int n2 = ran.Next(min, max);
                    int n3 = ran.Next(min, max);
                    expression += n1;
                    AddAndMinuMix(n2);
                    AddAndMinuMix(n3);
                    break;
                }
            case 3: //三个数字的混合计算
                {
                    int n1 = ran.Next(min, max);
                    int n2 = ran.Next(min, max);
                    int n3 = ran.Next(min, max);
                    expression += n1;
                    AddMinusMultiplyMix(n2);
                    AddMinusMultiplyMix(n3);
                    break;
                }
            case 4: //四个数字的混合计算
                {
                    int n1 = ran.Next(min, max);
                    int n2 = ran.Next(min, max);
                    int n3 = ran.Next(min, max);
                    int n4 = ran.Next(min, max);
                    expression += n1;
                    AddMinusMultiplyMix(n2);
                    AddMinusMultiplyMix(n3);
                    AddMinusMultiplyMix(n4);
                    break;
                }
            case 5: //五个数字的混合计算
                {
                    int n1 = ran.Next(min, max);
                    int n2 = ran.Next(min, max);
                    int n3 = ran.Next(min, max);
                    int n4 = ran.Next(min, max);
                    int n5 = ran.Next(min, max);
                    expression += n1;
                    AddMinusMultiplyMix(n2);
                    AddMinusMultiplyMix(n3);
                    AddMinusMultiplyMix(n4);
                    AddMinusMultiplyMix(n5);
                    break;
                }
            default:
                break;
        }

    }

    /// <summary>
    /// 加减混合表达式
    /// </summary>
    /// <param name="nextNum"></param>
    private void AddAndMinuMix(int nextNum)
    {
        int random = UnityEngine.Random.Range(0, 2);
        if (random.Equals(0))
        {
            expression += "+";
        }
        else if (random.Equals(1))
        {
            expression += "-";
        }
        expression += nextNum;
    }

    /// <summary>
    /// 加减乘混合表达式
    /// </summary>
    /// <param name="nextNum"></param>
    private void AddMinusMultiplyMix(int nextNum)
    {
        //System.Random ran = new System.Random();
        //if (ran.Next(0, 3) == 0)
        //{
        //    expression += "+";
        //}
        //else if (ran.Next(0, 3) == 1)
        //{
        //    expression += "-";
        //}
        //else
        //{
        //    nextNum = ran.Next(1, 3);//重新随机
        //    expression += "*";
        //}
        int random = UnityEngine.Random.Range(0, 3);
        if (random.Equals(0))
        {
            expression += "+";
        }
        else if (random.Equals(1))
        {
            expression += "-";
        }
        else
        {
            nextNum = UnityEngine.Random.Range(1, 3);
            expression += "*";
        }

        expression += nextNum;
    }

    /// <summary>
    /// 四则运算混合表达式
    /// </summary>
    /// <param name="nextNum"></param>
    private void FourArithmeticMix(int nextNum)
    {
        int random = UnityEngine.Random.Range(0, 4);
        if (random.Equals(0))
        {
            expression += "+";
        }
        else if (random.Equals(1))
        {
            expression += "-";
        }
        else if (random.Equals(2))
        {
            nextNum = UnityEngine.Random.Range(1, 3);
            expression += "*";
        }
        else if (random.Equals(3))
        {
            nextNum = UnityEngine.Random.Range(1, 10);
            expression += "/";
        }
        expression += nextNum;
    }
    #endregion

    #region 计算表达式
    private Dictionary<char, int> priorities = new Dictionary<char, int> { { '#', -1 }, { '+', 0 }, { '-', 0 }, { '*', 1 }, { '/', 1 } };  //优先级

    // private Dictionary<char, int> priorities = null;
    /// <summary>
    /// 初始化运算符优先级
    /// </summary>
    public void InitPriorities()                         //添加了四种运算符以及四种运算符的优先级
    {
        //priorities = new Dictionary<char, int>();
        //priorities.Add('#', -1);
        //priorities.Add('+', 0);
        //priorities.Add('-', 0);
        //priorities.Add('*', 1);
        //priorities.Add('/', 1);
    }

    /// <summary>
    /// 计算表达式
    /// </summary>
    /// <param name="expression"></param>
    /// <returns></returns>
    public double Calcuate()
    {
        try
        {
            var rpn = QueueSort(expression);                   //rpn逆波兰表达式reverse polish notation
            Stack<double> operandStack = new Stack<double>();
            double left, right;
            object cur;
            while (rpn.Count > 0)
            {
                cur = rpn.Dequeue();                           //出列

                if (cur is char)                               //如果cur为字符的话
                {
                    right = operandStack.Pop();                //右边的数字出栈
                    left = operandStack.Pop();                 //左边的数字出栈
                    //Debug.Log("左:" + left + "右:" + right + "现在的字符:" + cur);
                    operandStack.Push(Compute(left, right, (char)cur));    //此时调用compute方法
                }
                else
                {
                    operandStack.Push(double.Parse(cur.ToString()));            //是数字就压栈
                }
            }
            return operandStack.Pop();
        }
        catch
        {
            Debug.LogError("表达式格式不正确!");
            throw new Exception("表达式格式不正确!");
        }
    }

    /// <summary>
    /// 队列排序
    /// </summary>
    /// <param name="expression"></param>
    /// <returns></returns>
    private Queue<object> QueueSort(string expression)           // 队列排序
    {
        Queue<object> result = new Queue<object>();
        Stack<char> operatorStack = new Stack<char>();           //运算符栈
        operatorStack.Push('#');
        char top, cur, tempChar;                                          //top栈顶,current最近的;
        string tempNum;
        for (int i = 0, j; i < expression.Length;)                 //取出表达式
        {
            cur = expression[i++];                                  //取出表达式的每个字符赋给cur
            top = operatorStack.Peek();                             //栈顶元素赋给top此时为"#"

            if (cur == '(')                                         //将左括号压栈,此时栈顶元素为"("
            {
                operatorStack.Push(cur);
            }
            else
            {
                if (IsOperator(cur))                             //如果是运算符的话
                {
                    while (IsOperator(top) && ((IsAssoc(cur) && priorities[cur] <= priorities[top])) || (!IsAssoc(cur) && priorities[cur] < priorities[top]))
                    {
                        result.Enqueue(operatorStack.Pop());     //如果元素为运算符并且优先级小于栈顶元素优先级,出栈
                        top = operatorStack.Peek();              //继续把栈顶元素赋给top
                    }
                    operatorStack.Push(cur);                     //把数字压栈
                }
                else if (cur == ')')                           //将右括号添加到结尾
                {
                    while (operatorStack.Count > 0 && (tempChar = operatorStack.Pop()) != '(')
                    {
                        result.Enqueue(tempChar);
                    }
                }
                else
                {
                    tempNum = "" + cur;
                    j = i;
                    while (j < expression.Length && (expression[j] == '.' || (expression[j] >= '0' && expression[j] <= '9')))
                    {
                        tempNum += expression[j++];
                    }
                    i = j;
                    result.Enqueue(tempNum);
                }
            }
        }
        while (operatorStack.Count > 0)
        {
            cur = operatorStack.Pop();
            if (cur == '#') continue;
            if (operatorStack.Count > 0)
            {
                top = operatorStack.Peek();
            }

            result.Enqueue(cur);
        }

        return result;
    }

    const string operators = "+-*/";                 //运算符
    /// <summary>
    /// 计算左右两个数的方法
    /// </summary>
    /// <param name="leftNum"></param>
    /// <param name="rightNum"></param>
    /// <param name="op"></param>
    /// <returns></returns>
    private double Compute(double leftNum, double rightNum, char op)  //这是一种方法,用来计算左右两个数的静态方法!
    {
        switch (op)
        {
            case '+': return leftNum + rightNum;
            case '-': return leftNum - rightNum;
            case '*': return leftNum * rightNum;
            case '/': return leftNum / rightNum;
            default: return 0;
        }
    }

    /// <summary>
    /// 判断这个字符是否是运算符?
    /// </summary>
    /// <param name="op"></param>
    /// <returns></returns>
    private bool IsOperator(char op)                  //每次判断这个字符是否是运算符?
    {
        return operators.IndexOf(op) >= 0;
    }

    /// <summary>
    /// 返回一个关联符号
    /// </summary>
    /// <param name="op"></param>
    /// <returns></returns>
    private bool IsAssoc(char op)                //返回一个关联符号
    {
        return op == '+' || op == '-' || op == '*' || op == '/';
    }
    #endregion
}

 

参考博客链接:https://www.cnblogs.com/thinking-star/p/4917349.html

posted @ 2022-03-08 09:44  U3DEngineer  阅读(85)  评论(0编辑  收藏  举报