【Unity知识搬运】将一个表达式转换为逆波兰式的具体算法思想

来源:互联网 发布:linux php7环境搭建 编辑:程序博客网 时间:2024/05/24 06:33
原文地址 - http://www.manew.com/blog-27966-2587.html

作为一个U3D程序员,写一行if语句很容易。然而,这一行if语句里包含的逻辑,对其进行修改,是需要重新编译的,是写死在代码里的。那么问题来了,策划说:“来,按我的思路把这里改一下”。好了,原来写好的if(A or B),可能就要被改成if(A and B),甚至是if(A and(B or C)),重复编译与修改……这时你一定想说:“好呀,想改的话,自己改啊”。那么如何把这一逻辑问题,合理地交给策划呢?答案是——使用编译原理,公式由策划输入。

笔者大学还留了点儿编译原理知识没忘,依稀记得编译原理有一种利于计算机分析运算公式的式子——逆波兰式。所谓的逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。逆波兰记法不需要括号来标识操作符的优先级。举个简单的例子,平常我们写的数学表达式a+b,就是一种中缀表达式,写成后缀表达式就是ab+。再举一个复杂的例子,中缀表达式(a+b)*c-(a+b)/e的逆波兰式是ab+c*ab+e/-。逆波兰式的转化与运算算法:
(--------一大篇算法来袭-----------)
将一个表达式转换为逆波兰式的具体算法思想:
1.首先,需要分配2个栈,栈s1用于临时存储运算符(含一个结束符号),此运算符在栈内遵循越往栈顶优先级越高的原则;栈s2用于输入逆波兰式,为方便起见,栈s1需先放入一个优先级最低的运算符,在这里假定为'#';
2.从中缀式的左端开始逐个读取字符x,逐序进行如下步骤:
         (1)若x是操作数,则分析出完整的运算数(在这里为方便,用字母代替数字),将x直接压入栈s2;
         (2)若x是运算符,则分情况讨论:
                   (A)若x是'(',则直接压入栈s1;
                   (B)若x是')',则将距离栈s1栈顶的最近的'('之间的运算符,逐个出栈,依次压入栈s2,最后抛弃'(';
                   (C)若x是除'('和')'外的运算符,则再分如下情况讨论:
                            (a)若当前栈s1的栈顶元素为'(',则将x直接压入栈s1;
                            (b)若当前栈s1的栈顶元素不为'(',则将x与栈s1的栈顶元素比较,
                                   若x的优先级大于栈s1栈顶运算符优先级,则将x直接压入栈s1;
                                   否则,将栈s1的栈顶运算符弹出,压入栈s2中,
                                   直到栈s1的栈顶运算符优先级别低于(不包括等于)x的优先级,
                                   或栈s2的栈顶运算符为'(',此时则再将x压入栈s1;
3.在进行完步骤2后,检查栈s1是否为空,若不为空,则将栈中元素依次弹出并压入栈s2中(不包括'#');      
4.完成上述步骤后,栈s2便为逆波兰式输出结果。但是栈s2应做一下逆序处理,因为此时表达式的首字符位于栈底;
计算逆波兰式方法:
观察逆波兰式的栈顶,如果当前字符为变量或者常数,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
(---------------算法完了--------------------)
算法中提到的所有字符,其实是为了方便描述,我们可以使用class这样复合结构,包含类型、取值等信息,并做关于这个类的List列表。
算法中提到的运算符,是“加减乘除”,其实换成“与或非”,是一样一样的,无非就是把四则运算,变成了逻辑运算。双目运算符优先级:与>异或>或。
算法中提到的操作数,实际操作中主要应该是未知变量,而不是常量,所以应当分给每个未知变量一个id,直到必须要算出变量值的时候,再凭id去计算,由变量转常量(注意,这些变量能不计算就不计算,比如true和变量A做或运算,则不计算A也能知道结果为true)。另外,数据结构方面,除了要使用上面算法中谈到的两个栈,还需要一个字典结构,用来记录已经算过结果的操作数变量,避免对其进行重复计算。
 
笔者在做某游戏技能系统的时候,就用到了这一解决方法。技能系统,包括三大块:触发技能的指令集合、技能施放目标对象集合、技能触发需要满足的条件集合。其中,条件集合的若干条件如何组合就需要让策划配置。
原创粉丝点击