Hello I'm working on this math game and for my last scene I did what feels like a lot of repetitive code but I'm not sure if there's a way to simplify it, I have linked below so maybe some more seasoned programmers might have some more elegant solutions! For example, Im trying to generate every permutation of something like (a[]b)²[]c[]d where the brackets will be replaced by +,-,*, or /. What I have been doing is just creating random percent if statements to pick a specific version like "(a+b)²/c-d" Is there possibly a less "brute-force" and readable approach then what I have been doing?
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 below for more context) https://pastebin.pl/view/d1bfb99e
I applaud your desire to make your code more readable. The basic idea is to split (a) defining, (b) choosing and (c) applying your operators.
Step 1: You define Operator
s. Each Operator
combines both a mathematical operation (e.g. Add
would be (a, b) => a + b
) and a symbol (e.g. Add
would be "+"
).
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), "-");
Step 2: Then you randomly choose your operators (I used System.Random
, since I'm not familiar with Unity, but feel free to replace it with the random number generator of your choice):
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.");
}
}
Step 3: You apply them:
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}");
Adding a new operator (e.g. Multiply
) or a new problem variant (e.g. (Add, Multiply, 82)
) is now just a single line of code.