是否有可能减少重复的基于排列的 if 语句?

Is it possible to reduce repetitive permutation-based if-statements?

你好,我正在做这个数学游戏,在我的最后一个场景中,我做了很多重复的代码,但我不确定是否有办法简化它,我在下面链接了一些更多经验丰富的程序员可能有一些更优雅的解决方案! 例如,我试图生成类似 (a[]b)²[]c[]d 的每个排列,其中括号将替换为 +、-、* 或 /。我一直在做的只是创建随机百分比 if 语句来选择特定版本,如“(a+b)²/c-d” 是否有比我一直在做的更少的“蛮力”和可读性方法?

if(UnityEngine.Random.Range(0,101)>50){
        // 50% of being (a+b)²(c)+d
    if(UnityEngine.Random.Range(0,101)>50){
        ans = ((int) Mathf.Pow((float) a+ (float) b, 2))*c+d;
        input.text = "("+a+"+"+b+")"+"²"+"("+c+")"+"+"+d+"=";
        Debug.Log("Problem ID: 78");
        // 50% of being (a+b)²(c)-d
    } else {
        ans = ((int) Mathf.Pow((float) a+ (float) b, 2))*c-d;
        input.text = "("+a+"+"+b+")"+"²"+"("+c+")"+"-"+d+"=";
        Debug.Log("Problem ID: 79");
    }
    // 50% of being (a-b)²(c)[]d
} else {
    // 50% of being (a-b)²(c)+d
    if(UnityEngine.Random.Range(0,101)>50){
        ans = ((int) Mathf.Pow((float) a- (float) b, 2))*c+d;
        input.text = "("+a+"-"+b+")"+"²"+"("+c+")"+"+"+d+"=";
        Debug.Log("Problem ID: 80");
        // 50% of being (a-b)²(c)-d
    } else {
        ans = ((int) Mathf.Pow((float) a- (float) b, 2))*c-d;
        input.text = "("+a+"-"+b+")"+"²"+"("+c+")"+"-"+d+"=";
        Debug.Log("Problem ID: 81");
    }

(下面的 Pastebin 以获取更多上下文) https://pastebin.pl/view/d1bfb99e

将计算分成几个部分 - a±bsquare * c±d。分别计算,相乘得到最终结果。对于文本,可以使用字符串插值

float ans;
string operator1;
string operator2;
if (UnityEngine.Random.Range(0,101)>50) {
    ans = (float) a + (float) b;
    operator1 = "+";
} else {
    ans = (float) a - (float) b;
    operator1 = "-";
}
ans = (int)(ans * ans) * c;
if (UnityEngine.Random.Range(0,101)>50) {
    ans += d;
    operator2 = "+";
} else {
    ans -= d;
    operator2 = "-";
}
input.text = $"(a{operator1}b)²(c){operator2}d";

另请注意,UnityEngine.Random.Range(0,101) > 50 并非恰好是 50% 的概率。您可能指的是 UnityEngine.Random.Range(1,101) > 50,但我只会使用 UnityEngine.Random.Range(0,2) == 0.

问题 ID 可以通过生成 2 个随机位并将由这些位编码的 2 位数加到 78 上来展平:

float ans;
string operator1;
string operator2;
int random1 = UnityEngine.Random.Range(0,2);
int random2 = UnityEngine.Random.Range(0,2);
if (random1 == 0) {
    ans = (float) a + (float) b;
    operator1 = "+";
} else {
    ans = (float) a - (float) b;
    operator1 = "-";
}
ans = (int)(ans * ans) * c;
if (random2 == 0) {
    ans += d;
    operator2 = "+";
} else {
    ans -= d;
    operator2 = "-";
}
int problemID = 78 + random1 + random2 * 2;
Debug.Log($"Problem ID: {problemID}");
input.text = $"(a{operator1}b)²(c){operator2}d";

虽然在我看来这个技巧不是特别可读。

我赞赏您希望使您的代码更具可读性的愿望。基本思想是拆分 (a) 定义,(b) 选择和 (c) 应用您的运算符。

  • 第 1 步:您定义 Operators。每个 Operator 结合了数学运算(例如 Add 将是 (a, b) => a + b)和符号(例如 Add 将是 "+")。

    class Operator
    {
        public Func<int, int, int> Calculate { get; }
        public string Symbol { get; }
    
        public Operator(Func<int, int, int> calculate, string symbol)
        {
            Calculate = calculate;
            Symbol = symbol;
        }
    }
    
    private Operator Add = new Operator((a, b) => (a + b), "+");
    private Operator Subtract = new Operator((a, b) => (a - b), "-");
    
  • 第2步:然后你随机选择你的操作符(我用的是System.Random,因为我不熟悉Unity,但是你可以随意用你的随机数生成器替换它选择):

    var rnd = new Random();
    
    private (Operator op1, Operator op2, int problemId) RandomlyChooseProblem()
    {
        switch (rnd.Next(4))
        {
            case 0: return (Add, Add, 78);
            case 1: return (Add, Subtract, 79);
            case 2: return (Subtract, Add, 80);
            case 3: return (Subtract, Subtract, 81);
            default: throw new InvalidOperationException("This should not happen.");
        }
    }
    
  • 第 3 步:应用它们:

    var (op1, op2, problemId) = RandomlyChooseProblem();
    
    ans = op2.Calculate((int)Math.Pow(op1.Calculate(a, b), 2) * c, d);
    input.text = $"(a{op1.Symbol}b)²*c{op2.Symbol}d");
    Debug.Log($"Problem ID: {problemId}");
    

添加新运算符(例如 Multiply)或新问题变体(例如 (Add, Multiply, 82))现在只需一行代码。