I've been working on a a math tutoring program, I have the problem generator and solver working but I'm trying to have my random operator generator to use a check and change protocol so there isn't ALL add, sub, mult, or div in a problem. Some math problems will have 1/8/2, 4+3+4+2/1(too many sums), 4-1-5-8 (rarely but it still needs to be avoided), but needs to discern between additive or multiplicative types of math if needed. If

To generate the operation values I pass the method a tuple (this discerns the types of math) and an int (the amount of operands)

        //operator generation
        public static char[] operatorGen(Tuple<int, int> operatorType, int operandAmnt)
        {
            //amount of operators 1 less than operands, but ends with '=' character
            int[] symbolValue = new int[operandAmnt - 1];
            //randomizing operators
            for (int ctr = 0; ctr < symbolValue.Length; ctr++)
            {
                //1 for addsub 2 for multdiv
                symbolValue[ctr] = rand.Next(operatorType.Item1, operatorType.Item2);
            }
            //check and change thresholders so not too many repeats of same operand
            int addCtr = 0, subCtr = 0, multCtr = 0, divCtr = 0, thresh = symbolValue.Length / 3;
            char[] symbolCompute = new char[operandAmnt];
            //converts random numbers in corresponding symbols for display and compute
            for (int ctr = 0; ctr < symbolValue.Length; ctr++)
            {
                symbolCompute[ctr] = operatorThresh(symbolValue[ctr]);
                switch (symbolValue[ctr])
                {
                    case 1: addCtr++;
                        break;
                    case 2: subCtr++;
                        break;
                    case 3: multCtr++;
                        break;
                    case 4: divCtr++;
                        break;
                }

                // attempt at check and change redefine exclusion
                if (addCtr >= thresh) 
                {
                    int[] exclude = { 2, 3, 4 };
                    int symbol = rand.Next(0, 3);
                    int comp = exclude[symbol];
                    symbolCompute[ctr] = operatorThresh(comp);                
                }
                if (subCtr >= thresh) 
                {
                    int[] exclude = { 1, 3, 4 };
                    int symbol = rand.Next(0, 3);
                    int comp = exclude[symbol];
                    symbolCompute[ctr] = operatorThresh(comp);
                }
                if (multCtr >= thresh) 
                {
                    int[] exclude = { 1, 2, 4 };
                    int symbol = rand.Next(0, 3);
                    int comp = exclude[symbol];
                    symbolCompute[ctr] = operatorThresh(comp);
                }
                if (divCtr >= thresh) 
                {
                    int[] exclude = { 1, 2, 3 };
                    int symbol = rand.Next(0, 3);
                    int comp = exclude[symbol];
                    symbolCompute[ctr] = operatorThresh(comp);
                }
            }

            //used to circumvent out of bounds error with problem assembly
            symbolCompute[symbolValue.Length] = '=';
            return symbolCompute;
        }

        public static char operatorThresh(int symbolVal)
        {
            //e for error
            char operation = 'E';
            switch (symbolVal)
            {
                case 1: operation = '+';
                    break;
                case 2: operation = '-';
                    break;
                case 3: operation = '*';
                    break;
                case 4: operation = '/';
                    break;
            }
            return operation;
        }

I've been changing things around like adding my current attempt at the check and change protocol

Here is the how the form is discerning between the types of math the user wants to include. 1,5 is used for all 4 types of math; 1,3 is additive only, and 3,5 is multiplicative only

//define operators per problem
    char[] symbolValue;
    if (checkBoxAddSub.Checked && checkBoxMultDiv.Checked)
    {
        Tuple<int, int> operatorType = new Tuple<int, int>(1, 5);
        symbolValue = ProblemGenerator.operatorGen(operatorType, operandAmnt);
    }
    else if (checkBoxAddSub.Checked && !checkBoxMultDiv.Checked)
    {
        Tuple<int, int> operatorType = new Tuple<int, int>(1, 3);
        symbolValue = ProblemGenerator.operatorGen(operatorType, operandAmnt);
    }
    else if (checkBoxMultDiv.Checked && !checkBoxAddSub.Checked)
    {
        Tuple<int, int> operatorType = new Tuple<int, int>(3, 5);
        symbolValue = ProblemGenerator.operatorGen(operatorType, operandAmnt);
    }
    //at least one must be checked
    else if (!checkBoxAddSub.Checked && !checkBoxMultDiv.Checked)
    {
        //error
        throw new ArgumentException(string.Format("Operator type required"), "Operation Needed");
    }

Any ideas?

I extended the protocols to explicitly discern between additive or multiplicative, which I believe is working but I'll continue testing, any input is appreciated.

//operator generation
        public static char[] operatorGen(Tuple<int, int> operatorType, int operandAmnt)
        {
            //amount of operators 1 less than operands, but ends with '=' character
            int[] symbolValue = new int[operandAmnt - 1];
            //randomizing operators
            for (int ctr = 0; ctr < symbolValue.Length; ctr++)
            {
                symbolValue[ctr] = rand.Next(operatorType.Item1, operatorType.Item2);
            }
            char[] symbolCompute = new char[operandAmnt];

            //check and change thresholders so not too many repeats of same operand
            int thresh = -1, symbolReDef = -1, newComp = -1;

            //includes additive and multiplicative
            if (operatorType.Item1 == 1 && operatorType.Item2 == 5)
            {
                int addCtr = 0, subCtr = 0, multCtr = 0, divCtr = 0;
                thresh = symbolValue.Length / 4;
                if (thresh < 1) thresh = 1;

                //converts random numbers in corresponding symbols for display and compute
                for (int ctr = 0; ctr < symbolValue.Length; ctr++)
                {
                    symbolCompute[ctr] = operatorThresh(symbolValue[ctr]);
                    switch (symbolValue[ctr])
                    {
                        case 1: addCtr++;
                            break;
                        case 2: subCtr++;
                            break;
                        case 3: multCtr++;
                            break;
                        case 4: divCtr++;
                            break;
                    }
                    //if too many of a certain type of operation change the next operation
                    if (addCtr > thresh)
                    {
                        int[] exclude = { 2, 3, 4 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                    if (subCtr > thresh)
                    {
                        int[] exclude = { 1, 3, 4 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                    if (multCtr > thresh)
                    {
                        int[] exclude = { 1, 2, 4 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                    if (divCtr > thresh)
                    {
                        int[] exclude = { 1, 2, 3 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                }
            }
            //additive
            else if (operatorType.Item1 == 1 && operatorType.Item2 == 3)
            {
                int addCtr = 0, subCtr = 0;
                thresh = symbolValue.Length / 2;
                //converts random numbers in corresponding symbols for display and compute
                for (int ctr = 0; ctr < symbolValue.Length; ctr++)
                {
                    symbolCompute[ctr] = operatorThresh(symbolValue[ctr]);
                    switch (symbolValue[ctr])
                    {
                        case 1: addCtr++;
                            break;
                        case 2: subCtr++;
                            break;
                    }

                    if (addCtr >= thresh)
                    {
                        int[] exclude = { 2 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                    if (subCtr >= thresh)
                    {
                        int[] exclude = { 1 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                }
            }
            //multiplicative
            else if (operatorType.Item1 == 3 && operatorType.Item2 == 5)
            {
                int multCtr = 0, divCtr = 0;
                thresh = symbolValue.Length / 2;
                //converts random numbers in corresponding symbols for display and compute
                for (int ctr = 0; ctr < symbolValue.Length; ctr++)
                {
                    symbolCompute[ctr] = operatorThresh(symbolValue[ctr]);
                    switch (symbolValue[ctr])
                    {
                        case 3: multCtr++;
                            break;
                        case 4: divCtr++;
                            break;
                    }

                    if (multCtr >= thresh)
                    {
                        int[] exclude = { 4 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                    if (divCtr >= thresh)
                    {
                        int[] exclude = { 3 };
                        symbolReDef = rand.Next(0, 3);
                        newComp = exclude[symbolReDef];
                        symbolCompute[ctr] = operatorThresh(newComp);
                    }
                }
            }
            else throw new ArgumentException(string.Format("Operator type required"), "Operation Needed");;

            //used to circumvent out of bounds error with problem assembly
            symbolCompute[symbolValue.Length] = '=';
            return symbolCompute;
        }
This question has already been answered. Start a new discussion instead.