quiz machine help, datatypes, and then PROGMEM?

Hi,

I'm trying to build a quiz machine for the kids. It will have an LCD for display and buttons for the multiple choice answers. I'm having trouble working with the datatypes. I'm converting from 'string constant' to "char*" as well as then trying to compare a int to a pointer.

I'd like to figure out how to do what I'm trying to do, then find out what the best way I probably should have tried, and then figure out how to move my multi-dimensional array in to PROGMEM and access that. Here is what I did:

#include <avr/pgmspace.h>

char* myQuiz [4] [6] = {
{"Third-grade students went to a concert in 8 buses. Each bus took 45 students. How many students went to the concert?", "320", "360", "380", "3240", "B"},
{"A company has 6 big trucks. Each truck has 18 wheels. How many wheels is this in all?", "24", "96", "108", "116", "C"},
{"On Friday, 1250 people visited the zoo. Three times as many people visited on Saturday than on Friday. How many people visited the zoo on Saturday?", "3615", "3650", "3750", "3753", "C"},
{"9000 - 3782", "5218", "5328", "6782", "12,782", "A"}
};

void doQuestion(byte questionNumber);
void getAnswer(byte questionNumber);
char response;

void setup() {
  Serial.begin(9600);
  DDRD = B00001110; // pins 4-7 are inputs for answer buttons.
  PORTD = B11110000; // input pullups. 
}

void doQuestion(byte questionNumber){
  
  Serial.println(myQuiz[questionNumber][0]);
  for (int i = 1; i < 5; i++ ) {
    Serial.print(i);
    Serial.print(".");
    Serial.println(myQuiz[questionNumber][i]);
  }
}
    
void getAnswer(byte questionNumber){
   char* correctAnswer = myQuiz[questionNumber][5];
   while(true){
     switch(PIND){
      case B01110011:
        response = 'A';
      break;
      case B10110011:
        response = 'B';
      break;
      case B11010011:
       response = 'C';
      break;
      case B11100011:
       response = 'D';
      break;
  }
  if (correctAnswer == response){
     Serial.println("correct");
     } else {
     Serial.println("incorrect");
     }
     
   }
     
}    
   
void loop() {
         
  doQuestion(0);
  getAnswer(0);
  
}

So I have an array like {question. choice a, choice b, choice c, choice d, correct answer}. and then I want to show the question and the choices, then compare a button press with the last element of the array to see if the answer was correct.

Any advice is appreciated.

Thanks.

This works better as far as the datatypes go:

#include <avr/pgmspace.h>

char* myQuiz [4] [6] = {
  {
    "Third-grade students went to a concert in 8 buses. Each bus took 45 students. How many students went to the concert?", "320", "360", "380", "3240", "B"  }
  ,
  {
    "A company has 6 big trucks. Each truck has 18 wheels. How many wheels is this in all?", "24", "96", "108", "116", "C"  }
  ,
  {
    "On Friday, 1250 people visited the zoo. Three times as many people visited on Saturday than on Friday. How many people visited the zoo on Saturday?", "3615", "3650", "3750", "3753", "C"  }
  ,
  {
    "9000 - 3782", "5218", "5328", "6782", "12,782", "A"  }
};

void doQuestion(byte questionNumber);
void getAnswer(byte questionNumber);
char* response;

void setup() {
  Serial.begin(9600);
  DDRD = B00001110; // pins 4-7 are inputs for answer buttons.
  PORTD = B11110000; // input pullups. 
}

void doQuestion(byte questionNumber){

  Serial.println(myQuiz[questionNumber][0]);
  for (int i = 1; i < 5; i++ ) {
    Serial.print(i);
    Serial.print(".");
    Serial.println(myQuiz[questionNumber][i]);
  }
}

void getAnswer(byte questionNumber){
  char* correctAnswer = myQuiz[questionNumber][5];
  while(true){
    switch(PIND){
    case B01110011:
      
      response = "A";
      if (correctAnswer == response){
        Serial.println("correct");
        } else {
        Serial.println("incorrect");
        }
        delay(200);
      break;
      
    case B10110011:
      
      response = "B";
      if (correctAnswer == response){
        Serial.println("correct");
        } else {
        Serial.println("incorrect");
        }
        delay(200);
      break;
      
    case B11010011:
      
      response = "C";
      if (correctAnswer == response){
        Serial.println("correct");
        } else {
        Serial.println("incorrect");
        }
        delay(200);
      break;
   
    case B11100011:
      
      response = "D";
      if (correctAnswer == response){
        Serial.println("correct");
        } else {
        Serial.println("incorrect");
        }
        delay(200);
      break;
    }
  }
  

}    

void loop() {

  doQuestion(0);
  getAnswer(0);

}

Now on to PROGMEM.

You need to have an array of integers holding the correct answer number for each question.

You need a way to wait for the user to press a button, and then return a number to indicate which button was pressed.

Apart from when you're actually printing text for the user to see, you should represent questions and answers as numbers. (The correctAnswer variable should be an integer, not a character pointer.)

Your method of reading the switch input states directly from the hardware port is not how I'd do it, and doesn't deal with edge detection or waiting for a switch to be operated. Instead, I suggest you store the input pin numbers in a global array, and write a function which waits for all the inputs to not be pressed and then waits for one of them to be pressed and then returns the array index number of the one that was pressed. You will need to use FOR loops to implement that function.

You need to have an array of integers holding the correct answer number for each question.

So I should separate the answers from the questions? For instance, have the one array of the quesions and answers as char pointers and then another array of the correct answer for each question and the index would be the same, like answer[1] would go to question[1]?

You need a way to wait for the user to press a button, and then return a number to indicate which button was pressed.

Your method of reading the switch input states directly from the hardware port is not how I'd do it, and doesn't deal with edge detection or waiting for a switch to be operated. Instead, I suggest you store the input pin numbers in a global array, and write a function which waits for all the inputs to not be pressed and then waits for one of them to be pressed and then returns the array index number of the one that was pressed. You will need to use FOR loops to implement that function.

I've got something working here where I poll the buttons until one is pressed, and it seems to be working pretty well. I'll see if I can implement it the way you mention here. I can also change the way I refer to the buttons, I'm just building it up step by (baby) step.

Apart from when you're actually printing text for the user to see, you should represent questions and answers as numbers. (The correctAnswer variable should be an integer, not a character pointer.)

I'm having a hard time understanding datatypes and conversion and casting, so the first thing I was able to make work was treating everything like it was char*.

Thanks for taking a look, and all your good suggestions.

Jimmy

mixographer:
So I should separate the answers from the questions? For instance, have the one array of the quesions and answers as char pointers and then another array of the correct answer for each question and the index would be the same, like answer[1] would go to question[1]?

That is what I'd do. In fact I'd go one step further and hold the questions, options and answers in separate arrays rather than putting the questions and options in the same array. But it's no big deal, and your way can be made to work.