0

I'm trying to develop a quiz type math game in which the user has to solve on 1-5 questions. I want to add a counter that will display all the correct and incorrect answers at the end of the quiz, so far I have been doing it using if else statement, but I feel like there's should be a more efficient way of doing it. My code:

    if ( questions == 2 )
    { 
        printf (" What is 2 + 2\n");
        scanf("%d",&A1);
            if( A1 == 4 )       
            {
                    correct ++;
                }
                else
                {
                    incorrect ++;
            }

        printf (" What is 5 + 2\n");
        scanf("%d",&A2);
            if( A2 == 7 )       
            {
                correct ++;
            }
            else
            {
                incorrect ++;
            }

    }

Here's the code i have the same thing written 5 times for each option that the user can pick. All help is greatly appreciated, thanks in advance!

Gnqz
  • 3,292
  • 3
  • 25
  • 35
  • 1
    Just use a single counter? If anything not "correct" is "incorrect", I don't see the need for two counters. –  Oct 30 '17 at 14:00
  • switch (question) { case 1: ... break; case 2: ... break; case 3: ... break; case 4: ... break; case 5: ... break; default: /* input should be 1...5*/ exit(1); } – alinsoar Oct 30 '17 at 14:00
  • I'm using 2 counters because i want to display the number of correct and incorrect answers of all the rounds played by the user – Salman Mukadam Oct 30 '17 at 14:12
  • So you know the operator `-`? –  Oct 30 '17 at 14:24
  • You could have some common data structure (perhaps an array of some `struct`) describing the questions and expected answers. Or even use some database for them (perhaps with [SQLite](http://sqlite.org/)....) – Basile Starynkevitch Oct 30 '17 at 14:44
  • BTW, your question is unclear. Please **edit your question** to improve it and show some [MCVE] – Basile Starynkevitch Oct 30 '17 at 14:47
  • 1
    Your problem is not writing a function, which you thn can call 5 times with different question string and correct answer value. – hyde Oct 30 '17 at 14:50
  • Just as a side note: Google "arrays c". You'll be learning something new, but trust me, if you can learn to use arrays, you'll be saving yourself a lot of work. – Nic Oct 30 '17 at 17:21

4 Answers4

3

You could use the total of the questions and substract the correct answers to get the number of incorrect answers. Here is a sample:

#include <stdio.h>
#include <stdlib.h>
int main()
{
   char arQuestions[5][20] = { "2 + 2 =",
                               "2 * 2 =",
                               "2 - 2 =",
                               "2 / 2 =",
                               "2 ^ 2 ="};
   int answers[5] = {4,4,0,1,4};
   int i = 0;
   int answer  = 0;
   int correct = 0;

   for(;i<5;++i)
   {
       printf("%s ", arQuestions[i]);
       if( 1 == scanf("%d", &answer))
         if(answer == answers[i])
            correct++;
       printf("correct<%d> incorrect<%d>\n", correct, (i+1)-correct);
   }
   return(0);
}
Gnqz
  • 3,292
  • 3
  • 25
  • 35
1

Switch statements can be used when you need to check one variable against multiple values (as you do with your if ( questions == 0...5 ). In order not to rewrite the same questions over and over, we can use the way the switch statement naturally overruns into the next case to "cascade" depending on the number of questions we want.

Finally, as some other pointed out, we don't need to separate variables to track correct or incorrect answers; just track correct answers, and at the end the incorrect answers would equal questions - correct. Putting that all together, we have something that looks like this:

int questions;
printf("Number of questions?\n");
scanf("%d",&questions);

int correct = 0;
int answer = 0;

switch(questions) {
    case 5:
        printf("What is 2 + 2?\n");
        scanf("%d",&answer);
        if(answer == 4)       
        {
            correct++;
        }
        //note - no break at end of each case
    case 4:
        //ask another question
    case 3:
        //ask another question
    case 2:
        //ask another question
    case 1:
        //ask another question
    default:
        break;
}
printf("Results:\nCorrect = %d\nIncorrect = %d", correct, questions - correct);
  • Thanks this really helped! Its a college assingment im doing and i missed out when we did switch statements and ive been trying to learn it but couldnt really get my head around how to use them. Just one question about it though is each case the value set by the user for the varible "questions"? – Salman Mukadam Oct 30 '17 at 14:45
  • Think of switch like multiple `if() else if()` statements. Basically it says, "if questions is 5, do the stuff after the first case; else if it is 4, do the stuff after the second case, etc.". Normally you break at the end of each case, so that the switch doesn't run any other cases. But because we don't break after our cases, it will do the stuff after case 5, _and_ the stuff in case 4, _and_ the stuff in case 3, etc. – Shane Gifford Oct 30 '17 at 14:48
  • In practice `break;` at end of every `case` is recommended. [Duff's device](https://en.wikipedia.org/wiki/Duff%27s_device) is an exceptional trick. – Basile Starynkevitch Oct 30 '17 at 14:51
  • Alright that makes so much more sense to me now thank you so much! – Salman Mukadam Oct 30 '17 at 14:54
  • I don't think changing if-elseif ladder into switch-case is useful change. It's just cosmetics. Problem is 5x copy-paste piece of code. – hyde Oct 30 '17 at 14:54
1

There is another option that might be a little more efficient

you can make correct and incorrect global variables or create a pointer to them, and create another function to check if the entered answer is correct and update correct or incorrect accordingly:

// initiate global variable's
int correct = 0, incorrect = 0;

void checkanswer(int var1, int var2, int useranswer)
{
    if(useranswer == var1 + var2)
        correct++;
    else
        incorrect++;
}

int main(void)
{
...
    printf (" What is 2 + 2\n");
    scanf("%d", &A1);
    checkanswer(2, 2, A1);
//next question
}

This way, instead of repeating yourself, you use the function you wrote.

A few other things:

  • Try to find an alternative to scanf, it is a dangerous function that make your code vurnable. See this and or search for more answers cause this topic has a lot of answered questions online.
  • I wrote a math game as well, if you want some another example for something similar to what your'e writing. In my game you need to get a score of 10 and the questions are random in any game. See here if your'e interested.

Hope I helped! Feel free to ask me about my game if you have any questions or anything else :)

N. Leizer
  • 11
  • 1
  • You could merge the printf and scanf calls into the function as well, assuming the format string is always "%d". Also, scanf is perfectly safe when used correctly. It returns the number of variables in the argument list that it assigned a value to successfully, so you can easily detect invalid input and respond appropriately. And fgets/sscanf or fgets/strtoul have their own issues. Writing safe code isn't just a matter of avoiding a list of evil functions. All three of those approaches are the best option some of the time, and bad ideas other times. – Ray Oct 30 '17 at 14:55
  • Got it, thanks for your input, I'm still learining :) – N. Leizer Oct 30 '17 at 15:00
1

Here's a more generic version which actually calculates the equation and checks it against the user's answer.

#include <stdio.h>

typedef enum
{
  ADD,
  SUB,
  MUL,
  DIV,
} operation_t;

typedef struct
{
  int op1;
  int op2;
  operation_t op;
} equation_t;

char operation_to_char (operation_t op)
{
  const char CH_OP[] = {'+', '-', '*', '/'};
  return CH_OP[op];
}

int solve (const equation_t* eq)
{
  switch(eq->op)
  {
    case ADD: return eq->op1 + eq->op2;
    case SUB: return eq->op1 - eq->op2;
    case MUL: return eq->op1 * eq->op2;
    case DIV: return eq->op1 / eq->op2;
  }
  return 0; // to silence compiler warning, should never happen
}

int main (void)
{
  const equation_t EQUATIONS[] = 
  {
    {1, 1, ADD},
    {2, 2, ADD},
    {1, 1, SUB},
    {2, 2, MUL},
    {9, 3, DIV},
  };
  const size_t EQUATIONS_N = sizeof(EQUATIONS)/sizeof(*EQUATIONS);

  for(size_t i=0; i<EQUATIONS_N; i++)
  {
    printf("What is %d %c %d? ", 
             EQUATIONS[i].op1,  
             operation_to_char(EQUATIONS[i].op),
             EQUATIONS[i].op2);

    int answer;
    scanf("%d", &answer);
    getchar(); // discard line feed

    int solution = solve(&EQUATIONS[i]);
    if(answer == solution)
    {
      puts("Correct");
    }
    else
    {
      printf("Incorrect, the solution is %d\n", solution);
    }
  }
}

Please note that this code has no error handling of user input.

Lundin
  • 195,001
  • 40
  • 254
  • 396