I am writing a program for a class project, trying to emulate the game Who wants to be a Millionaire, but am running into some issues having my questions in a separate input file being read properly. Here is my source code the issues i believe come during the second for loops in the functions get_question, get_answerA, get_answerB, get_answerC, get_answerD. Any immediate help would be appreciated. Code: #include <stdio.h> #include <string.h> #include <stdlib.h> /*for rand and srand*/ #include <time.h> /* for time */ void rules(); int search(char player[]); char play_game(); void display_qa(int question_number); void get_question(int r, int question_number); void get_answerA(int r, int question_number); void get_answerB(int r, int question_number); void get_answerC(int r, int question_number); void get_answerD(int r, int question_number); FILE* get_filename(int question_number); int main() { char player[20]; /*The name of the player*/ char game_choice; char leave_game='N'; //char play_again; /*The player confirms/denies playing again*/ int earnings; /*The player's previous winnings*/ int question_number; /*The question player is on*/ srand(time(0)); //Seed the rand() function. printf("Welcome to Who Wants to Be a Millionaire!\nHello contestant, say your name.\n"); //Greet player and prompt for player name scanf("%s", &player); earnings=search(player); if(earnings==0) //Check to see if player has played before, if so print previous winnings printf("\nNice to meet you %s! I see you have not played before.\n\n", player); else printf("\nNice to meet you %s! I see you have played before and have a high score of $%d.\n\n", player, earnings); //Read the rules to the player rules(); printf("Are you ready to play (enter Y or N)? "); scanf(" %c", &game_choice); //The player decides whether they want to play or not switch(game_choice) { case 'Y': case 'y': printf("Let's play Who Wants to Be a Millionaire!\n\n"); question_number=1; while (leave_game!='Y' && leave_game!='y') { display_qa(question_number); question_number++; printf("Would you like to take your winnings and leave?"); scanf("%c", &leave_game); } break; case 'N': case 'n': exit(0); break; default: printf("Invalid choice.\n"); main(); } } //Tell player the rules of the game void rules() { printf("The rules are simple. Correctly answer each question to progress to the next question, worth a\nlarger sum of money. You have the option of using three lifelines to answer any question:\n"); printf("\t1. 50/50 (eliminating two incorrect answers from the selection),\n\t2. You may ask the audience, or\n\t3. You may phone a friend (the computer does this).\n"); printf("If at any point during a question, you would like to use a lifeline, enter the coordinating number\n(1 for 50/50; 2 for Ask the audience; 3 for Phone a friend) when entering your answer."); printf("If you are uncertain of the correct answer you may opt to end your game with the money you’ve earned thus far. Select your answer by entering the associated letter.\n\n"); } //Search the high score file to see if the player is on the list; if they are return the past winnings int search(char player[]) { FILE* highscore; char highscores[20][30]; int i=1, j; highscore=fopen("HighScore.txt","r"); while(fscanf(highscore,"%s", &highscores[i])!=EOF) i++; for(j=0; j<40; j++) { if(strcmp(player,highscores[j])==0) return((int)highscores[j+1]); } return(0); } char play_game() { char response; /*The player confirms/denies gameplay*/ printf("Are you ready to play (enter Y or N)? "); scanf("%c", &response); return(response); } //Display the questions and the answers void display_qa(int question_number) { int r, j; char question[300]; //The question being asked the player char answerA[30]; /*Answer choice A*/ char answerB[30]; /*Answer choice B*/ char answerC[30]; /*Answer choice C*/ char answerD[30]; /*Answer choice D*/ char correct_answer[30]; /*The correct answer to the question*/ r=rand()%3 + 1; //Finding a random number 1-3 which coordinates with questions 1,2,3 in each respective earnings question file //get_question(r, question_number); get_question(r, question_number, question); //Retrieve a random question from the file get_answerA(r, question_number, answerA); //Retrieve answer choice A from the random question get_answerB(r, question_number, answerB); //Retrieve answer choice B from the random question get_answerC(r, question_number, answerC); //Retrieve answer choice C from the random question get_answerD(r, question_number, answerD); //Retrieve answer choice D from the random question printf("%s", question); //Print the question to the screen for the player printf("%s", answerA); //Print the question's answer choice A printf("%s", answerB); //Print the question's answer choice B printf("%s", answerC); //Print the question's answer choice C printf("%s", answerD); //Print the question's answer choice D } //Finds the right file for the FILE* get_filename(int question_number) { FILE* questionfile; switch(question_number) { case '2': questionfile=fopen("200dollars.txt", "r"); break; case '3': questionfile=fopen("300dollars.txt", "r"); break; case '4': questionfile=fopen("500dollars.txt", "r"); break; case '5': questionfile=fopen("1000dollars.txt", "r"); break; case '6': questionfile=fopen("2000dollars.txt", "r"); break; case '7': questionfile=fopen("4000dollars.txt", "r"); break; case '8': questionfile=fopen("8000dollars.txt", "r"); break; case '9': questionfile=fopen("16000dollars.txt", "r"); break; case '10': questionfile=fopen("32000dollars.txt", "r"); break; case '11': questionfile=fopen("64000dollars.txt", "r"); break; case '12': questionfile=fopen("125000dollars.txt", "r"); break; case '13': questionfile=fopen("250000dollars.txt", "r"); break; case '14': questionfile=fopen("500000dollars.txt", "r"); break; case '15': questionfile=fopen("1000000dollars.txt", "r"); break; default: questionfile=fopen("100dollars.txt", "r"); break; } return(questionfile); } //Read the questions from the correct file and return the array void get_question(int r, int question_number, char question[]) { FILE* question_lvl; int i; char read_all[30][300]; //2D array to read all the contents of the file //char question[300]; question_lvl=get_filename(question_number); //Reads and gets all the information from the file and puts it into the array read_all for(i=0; i<30; i++) { if(strcmp((fgets(read_all[i],300,question_lvl)),("-1"))==0) break; } //Contents of read_all are checked against the random number generated to get the correspponding questions for(i=0; i<30; i++) { if((read_all[i][0]==(char)r) && (read_all[i][1]=='.')) strcpy(question,read_all[i]); } } //Answer Choice A void get_answerA(int r, int question_number, char answerA[]) { FILE* question_lvl; int i; char read_all[30][300]; //2D array to read all the contents of the file //char answers[300]; question_lvl=get_filename(question_number); //Reads and gets all the information from the file and puts it into the array read_all for(i=0; i<30; i++) { if(strcmp((fgets(read_all[i],300,question_lvl)),("-1"))==0) break; } //Contents of read_all are checked against the random number generated to get the correspponding questions for(i=0; i<30; i++) { if((read_all[i][0]==(char)r) && (read_all[i+1][0]=='A')) strcpy(answerA,read_all[i+1]); } } //Answer Choice B void get_answerB(int r, int question_number, char answerB[]) { FILE* question_lvl; int i; char read_all[30][300]; //2D array to read all the contents of the file //char answers[300]; question_lvl=get_filename(question_number); //Reads and gets all the information from the file and puts it into the array read_all for(i=0; i<30; i++) { if(strcmp((fgets(read_all[i],300,question_lvl)),"-1")==0) break; } //Contents of read_all are checked against the random number generated to get the correspponding questions for(i=0; i<30; i++) { if((read_all[i][0]==r) && (read_all[i][1]=='.')) strcpy(answerB,read_all[i+2]); } } //Answer Choice C void get_answerC(int r, int question_number, char answerC[]) { FILE* question_lvl; int i; char read_all[30][300]; //2D array to read all the contents of the file //char answers[300]; question_lvl=get_filename(question_number); //Reads and gets all the information from the file and puts it into the array read_all for(i=0; i<30; i++) { if(strcmp((fgets(read_all[i],300,question_lvl)),"-1")==0) break; } //Contents of read_all are checked against the random number generated to get the correspponding questions for(i=0; i<30; i++) { if((read_all[i][0]==r) && (read_all[i][1]=='.')) strcpy(answerC,read_all[i+3]); } } //Answer Choice D void get_answerD(int r, int question_number, char answerD[]) { FILE* question_lvl; int i; char read_all[30][300]; //2D array to read all the contents of the file //char answers[300]; question_lvl=get_filename(question_number); //Reads and gets all the information from the file and puts it into the array read_all for(i=0; i<30; i++) { if(strcmp((fgets(read_all[i],300,question_lvl)),"-1")==0) break; } //Contents of read_all are checked against the random number generated to get the correspponding questions for(i=0; i<30; i++) { if((read_all[i][0]==r) && (read_all[i][1]=='.')) strcpy(answerD,read_all[i+4]); } } //Get correct answer void get_correctanswer(int r, int question_number, char correct_answer[]) { FILE* question_lvl; int i; char read_all[30][300]; //2D array to read all the contents of the file //char answers[300]; question_lvl=get_filename(question_number); //Reads and gets all the information from the file and puts it into the array read_all for(i=0; i<30; i++) { if(strcmp((fgets(read_all[i],300,question_lvl)),"-1")==0) break; } //Contents of read_all are checked against the random number generated to get the correspponding questions for(i=0; i<30; i++) { if((read_all[i][0]==r) && (read_all[i][1]=='.')) strcpy(correct_answer,read_all[i+5]); } }
in the function "get_question" you've got Code: if(strcmp((fgets(read_all[i],300,question_lvl)),("-1"))==0) I don't know what your data file(s) look like, but fgets will store the '\n' char if it will fit, so if your file looks something like line of stuff line of stuff etc -1 to strcmp, you may be getting "-1\n", "-1" so check read_all before calling strcmp. Code: char *p; int i=0; while(i < 30 && fgets(read_all[i], sizeof read_all[i], question_lvl) != NULL) { if((p = strchr(real_all[i], '\n')) != NULL) *p = '\0'; if(strcmp(read_all[i], "-1") == 0) ... ++i; } in the function "get_filename", you could do something like below to trim a few lines so long as question_number is something like 100, 200, 500, etc. Code: char fname[80] = { 0 }; ... sprintf(fname, "%ddollars.txt", question_number); questionfile = fopen(fname, "r"); return (questionfile); One other thing is watch out for is having boundary errors in your arrays. Several loops you've got don't account for what's actually stored versus how much can be stored and/or iterating past the last element.
Code: #include <iostream> #include <string> #include <map> #include <cassert> #include <cstdlib> #include <ctime> using namespace std; typedef map<string,string> QuestionsAndAnswers; typedef pair<string,string> qa; void init(QuestionsAndAnswers&); unsigned random(double min, double max); int main(int argc, char *argv[]) { QuestionsAndAnswers QandA; QuestionsAndAnswers::iterator i; string a; size_t N, n, k; time_t t; // Initialize srand((unsigned)time(&t)); init(QandA); N = QandA.size(); // Play while (true) { n = random(1,N); for (i = QandA.begin(), k = 1; k != n; i++, k++); cout << i->first << "> "; getline(cin,a); if (a == i->second) { cout << ". Correct!" << endl; } else { cout << ". No" << endl; } } return 0; } void init(QuestionsAndAnswers &q_a) { string q; q = string("What is the Capitol of California?\n"); q += string("a. San Francisco\n"); q += string("b. Benicia\n"); q += string("c. Sacramento\n"); q += string("d. Los Angeles\n"); q_a.insert(qa( q,"c") ); q = string("Where would a cowboy wear his chaps?\n"); q += string("a. Hands\n"); q += string("b. Legs\n"); q += string("c. Arms\n"); q += string("d. Head\n"); q_a.insert(qa( q,"b") ); q = string("Sherpas and Gurkhas are native to which country?\n"); q += string("a. Ecuador \n"); q += string("b. Morocco\n"); q += string("c. Russia\n"); q += string("d. Nepal\n"); q_a.insert(qa( q,"d") ); // ... etc. ... } unsigned random(double rangeMin, double rangeMax) { assert(rangeMin <= rangeMax); double maxN = rangeMax - rangeMin + 1; return static_cast<unsigned> (((rand() / (double)RAND_MAX) * maxN) + rangeMin); } #if 0 Sample run: Where would a cowboy wear his chaps? a. Hands b. Legs c. Arms d. Head > b . Correct! What is the Capitol of California? a. San Francisco b. Benicia c. Sacramento d. Los Angeles > a . No #endif EDIT: here's the translation to using just arrays and C-strings, with levels and dollar amounts included; this should be more than enough help for you to complete this project. Code: #include <iostream> #include <cassert> #include <cstdlib> #include <cstring> #include <ctime> using namespace std; const size_t MAX_Q_LEN = 1024; // the following two values are small for this demo, a larger // number of questions per level should be provided, 25 or 50 // for example, and the number of levels set to 15, for the // different dollar amounts from $500 to $1,000,000. const size_t NUM_Q_PER_LEVEL = 3; const size_t NUM_LEVELS = 2; // One question and answer typedef struct { char q[ MAX_Q_LEN ]; char a; } QA; // Question database typedef struct { QA qGrp[ NUM_LEVELS ][ NUM_Q_PER_LEVEL ]; unsigned value[ NUM_LEVELS ]; } QDB; void init(QDB&); unsigned random(double min, double max); int main(int argc, char *argv[]) { QDB qdb; size_t n, level=0; char a; bool done = false; unsigned winnings = 0; time_t t; // Initialize srand((unsigned)time(&t)); init(qdb); // Play while ((done == false) && (level < NUM_LEVELS)) { n = random(0,NUM_Q_PER_LEVEL-1); cout << qdb.qGrp[level][n].q << "> "; cin >> a; if (a == qdb.qGrp[level][n].a) { cout << ". Correct!" << endl << endl; winnings += qdb.value[level++]; } else { cout << ". No" << endl << ". Game over." << endl; done = true; } } cout << endl << "Winnings = $" << winnings << endl; return 0; } void init(QDB &q_a) { q_a.value[0] = 500; strcpy(q_a.qGrp[0][0].q,"What is the Capitol of California?\n"); strcat(q_a.qGrp[0][0].q,"a. San Francisco\n"); strcat(q_a.qGrp[0][0].q,"b. Benicia\n"); strcat(q_a.qGrp[0][0].q,"c. Sacramento\n"); strcat(q_a.qGrp[0][0].q,"d. Los Angeles\n"); q_a.qGrp[0][0].a = 'c'; strcpy(q_a.qGrp[0][1].q,"Where would a cowboy wear his chaps?\n"); strcat(q_a.qGrp[0][1].q,"a. Hands\n"); strcat(q_a.qGrp[0][1].q,"b. Legs\n"); strcat(q_a.qGrp[0][1].q,"c. Arms\n"); strcat(q_a.qGrp[0][1].q,"d. Head\n"); q_a.qGrp[0][1].a = 'b'; strcpy( q_a.qGrp[0][2].q, "Sherpas and Gurkhas are native to which country?\n" ); strcat(q_a.qGrp[0][2].q,"a. Ecuador\n"); strcat(q_a.qGrp[0][2].q,"b. Morocco\n"); strcat(q_a.qGrp[0][2].q,"c. Russia\n"); strcat(q_a.qGrp[0][2].q,"d. Nepal\n"); q_a.qGrp[0][2].a = 'd'; q_a.value[1] = 1000; strcpy( q_a.qGrp[1][0].q, "Complete the title of the James Bond " ); strcat(q_a.qGrp[1][0].q,"film The Man With The Golden...\n"); strcat(q_a.qGrp[1][0].q,"a. Gun\n"); strcat(q_a.qGrp[1][0].q,"b. Tooth\n"); strcat(q_a.qGrp[1][0].q,"c. Delicious\n"); strcat(q_a.qGrp[1][0].q,"d. Eagle\n"); q_a.qGrp[1][0].a = 'a'; strcpy( q_a.qGrp[1][1].q, "Poaching involves cooking something in what?\n" ); strcat(q_a.qGrp[1][1].q,"a. Beer\n"); strcat(q_a.qGrp[1][1].q,"b. Oven\n"); strcat(q_a.qGrp[1][1].q,"c. Liquid\n"); strcat(q_a.qGrp[1][1].q,"d. Grill\n"); q_a.qGrp[1][1].a = 'c'; strcpy(q_a.qGrp[1][2].q,"Who played Zorro in Disney's old television series?\n"); strcat(q_a.qGrp[1][2].q,"a. Guy Lombardo\n"); strcat(q_a.qGrp[1][2].q,"b. Guy Williams\n"); strcat(q_a.qGrp[1][2].q,"c. Buddy Guy\n"); strcat(q_a.qGrp[1][2].q,"d. Guy Lafleur\n"); q_a.qGrp[1][2].a = 'b'; // ... etc. ... } unsigned random(double rangeMin, double rangeMax) { assert(rangeMin <= rangeMax); double maxN = rangeMax - rangeMin + 1; return static_cast<unsigned> (((rand() / (double)RAND_MAX) * maxN) + rangeMin); } #if 0 Sample run: Where would a cowboy wear his chaps? a. Hands b. Legs c. Arms d. Head > b . Correct! Who played Zorro in Disney's old television series? a. Guy Lombardo b. Guy Williams c. Buddy Guy d. Guy Lafleur > b . Correct! Winnings = $1500 #endif
zachry00, that's nice. I wonder if the OP is still waiting or if too much time has elapsed... here's my stab at it in C and the data file, but it's a work in progress... well actually nah, I'm over it. I don't know the rules anyway. questions.dat Code: Which is not an ancient wonder of the world:C:Great Pyramid of Giza_Temple of Artemis_Golden Gate Bridge_Colossus of Rhodes Which is not a primary color:B:Red_White_Green_Blue How many sides are there in an octogon:D:4_6_12_8 How many pounds are in one ton:B:500_2000_1000_4000 How many continents are there:C:5_9_7_8 How many Equinoxes are there:D:1_4_3_2 Which planet was reclassified:D:Mercury_Neptune_Earth_Pluto What many years does it take Halley's comet to orbit the sun:A:76_40_83_65 main.c Code: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <time.h> #define OFFSET 4 // max questions for each round #define MAX_ROUNDS 2 // max rounds const size_t AMOUNT[] = { 0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 4000, 8000, 16000, 25000, 40000, 80000, 100000, 250000, 500000, 1000000 }; typedef struct { char ques[200]; char tmp[200]; char ans[4][60]; char correct; short lline; size_t winnings; } qadata; void play_game(FILE *, qadata *); void fetch_qna(char *, qadata *); int main(void) { FILE *fp = fopen("questions.dat", "rt"); qadata qna; srand((unsigned)time(0)); if(fp) { for(;;) { char inp[3] = { 0 }; printf("1) Play Game\n"); printf("2) Quit\n\n--> "); fgets(inp, sizeof inp, stdin); if(inp[0] == '2') break; else if(inp[0] == '1') { memset(&qna, 0, sizeof(qadata)); play_game(fp, &qna); if(qna.winnings == 0) puts("\nYour game ends without winning any money!\n\n"); else printf("\nCongratulations in winning %u dollars\n\n", qna.winnings); } else puts("\nUnknown or invalid choice"); } fclose(fp); } return 0; } void play_game(FILE *f, qadata *target) { /* read data file (f) and choose a "random" question ((rand() % OFFSET) + 1) + (round - 1 * OFFSET) for each round. passes the selected line to "fetch_qna" for parsing into in the designated fields of (target). run until either a wrong answer is given, the user chooses to quit at a given round, or the max number of questions (MAX_QUES) has been correctly answered one life line is given per game in form of 50-50, which removes two of the incorrect choices */ int line, advance, round = 1, randq; char file_buf[BUFSIZ] = { 0 }, inp[3] = { 0 }, *p; target->lline = 1; // init single life line for each game do { // loop so long as player advances randq = ((rand() % OFFSET) + 1) + ((round - 1) * OFFSET); line = 0; // re-init line counter variable advance = 0; // re-init control variable rewind(f); // set file pointer back to beginning of file while(line != randq && (fgets(file_buf, sizeof file_buf, f) != NULL)) { ++line; } fetch_qna(file_buf, target); // parse the chosen line and store it in (target) do { // loop so long as question hasn't been answered or bogus input received system("cls"); // non-standard function; remove or change to suit printf("Round %2d is worth %u; so far you have won %u\n", round, AMOUNT[round], target->winnings); printf("---------------------------------------------\n"); printf("%s\n\n", target->ques); printf("A) %s\nB) %s\nC) %s\nD) %s\nE) life line\nF) walk away\n\n--> ", target->ans[0], target->ans[1], target->ans[2], target->ans[3]); fgets(inp, sizeof inp, stdin); if((p = strchr(inp, '\n')) != NULL) *p = '\0'; else while(getchar() != '\n'){} if(toupper(inp[0]) != 'A' && toupper(inp[0]) != 'B' && toupper(inp[0]) != 'C' && toupper(inp[0]) != 'D' && toupper(inp[0]) != 'E' && toupper(inp[0]) != 'F') { // gibberish input ignore it and reinit the questions time_t t1 = time(0), t2; printf("Unrecognized or invalid choice - ignoring %c\n", inp[0]); fflush(stdout); do { t2 = time(0); }while(t2 < t1 + 2); } else { if(toupper(inp[0]) == 'F') { // user walks away with winnings up until current round // should be modified to whatever actual rule is target->winnings = AMOUNT[round]; round = 0; // trigger game end advance = 1; // trigger round end } else if(toupper(inp[0]) != 'E' && toupper(inp[0]) != toupper(target->correct)) { // answered question incorrectly ending the game and losing all money round = 0; target->winnings = AMOUNT[round]; advance = 1; } else if(toupper(inp[0]) == 'E' && target->lline == 1) { // 50-50 remove two incorrect choices // user can still choose removed choices; fix if desired int i = 0, idx; char q; while(i != 2) { idx = rand() % 4; q = "ABCD"[idx]; if(q != target->correct && target->ans[idx][0] != '\0') { target->ans[idx][0] = '\0'; ++i; } } target->lline = 0; // update life line } else if(toupper(inp[0]) == 'E' && target->lline == 0) { // life line was used up time_t t1 = time(0), t2; printf("you have exhausted your life lines\n"); fflush(stdout); do { t2 = time(0); } while(t2 < t1 + 2); } else if(toupper(inp[0]) == toupper(target->correct)) { // question was answered correctly; advance to next question target->winnings = AMOUNT[round]; ++round; // increment round advance = 1; // trigger round end } } } while(advance == 0); } while(round != 0 && round <= MAX_ROUNDS); } void fetch_qna(char *source, qadata *target) { /* parse (source) along the following syntax (question:correct answer:ans1_ans2_ans3_ans4 and store into the appropriate fields of (target) */ int i = 0; char *p; p = strtok(source, ":"); // split line on ":" while(p) { // add error checking for correct syntax switch(i) { case 0 : strcpy(target->ques, p); break; case 1 : sscanf(p, "%c", &target->correct); break; case 2 : strcpy(target->tmp, p); break; } p = strtok(NULL, ":"); ++i; } i = 0; p = strtok(target->tmp, "_"); // split line on "_" while(p) { // store each answer; add error checks strcpy(target->ans[i], p); p = strtok(NULL, "_"); ++i; } }