0

the following function is part of sort of a game with questions and answers. I have a problem with the randomization of the questions by their complexity-some questions appear more than once and the first also appears in every level, which should not happen. Please help!

typedef struct
{
    char question[300];
    char date[30], author[30], ansr1[80], ansr2[80], ansr3[80], ansr4[80];
    int id, correctAnsr, level;
} game;

typedef struct Node
{
    game data;
    struct Node* next;
}  node;

void printRandom1(node *head)
{
    if (isEmpty(head))
        return;

    srand(time(NULL));

    node *result = head->data.question;

    node *current = head;
    int n;
    for (n = 17; current != NULL; n++)
    {
        if (rand() % n == 0 && current->data.level == 0)
            result = current->data.question;
        current = current->next;
    }
    printf("%s\n", result);
    int i, ans;

    printf("1.-%s\n", result->data.ansr1);
    printf("2.-%s\n", result->data.ansr2);
    printf("3.-%s\n", result->data.ansr3);
    printf("4.-%s\n", result->data.ansr4);

    printf("Enter the correct answer: ");
    scanf("%d", &ans);
    if (ans == result->data.correctAnsr)
        printf("CORRECT ANSWER!\n");
    else
    {
        printf("WRONG ANSWER\n");
        printf("GAME OVER");
        printf("The correct answer is: %d\n", result->data.correctAnsr);
        return menu();
        exit(1);
    }
}
2
  • in node result = head->data.question; the result is not a node pointer it is a char pointer. Sorry for the pointers, I am on my mobile and i didn't find the backquotes. Commented May 29, 2016 at 18:35
  • thank u. So how should i position the pointers for the answers. I'm sorry for asking but i'm really bad at this Commented May 29, 2016 at 18:50

1 Answer 1

1

Ad "some questions appear more than once": this is because you do not track used questions anyhow -- your random choice method always selects from the list of all questions (regardless if they have already been asked or not).

Ad "first also appears in every level": my bet is that your random choice method (which is quite strange) is not guaranteed to select a question (i.e. the result = current->data.question part may not be executed with quite high probability). The initial value of result is kept in this case (which happens to be the first question).

Below is a modified version of your code. Some remarks:

  • counting the number of questions in linked list is added. It is needed for the random choice which selects among the answers with equal probability (to be correct -- there is some negligible bias, but probably not important here)

  • used answers are tracked in a new linked-list

  • there is no level logic implemented. You may want to remove questions with inappropriate level from the linked list at the beginning of the game

  • the current variable is a pointer-to-a-pointer which simplifies the unlinking process (you do not need to keep the previous entry pointer this way)

Code:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct
    {
    char question[300];
    char date[30], author[30], ansr1[80], ansr2[80], ansr3[80], ansr4[80];
    int id, correctAnsr, level;
} question;

typedef struct questionListNode {
    question data;
    struct questionListNode* next;
} questionListNode;

typedef struct {
    questionListNode* headAvailable; // Your former head variable
    questionListNode* headUsed; // Initialize this to NULL
    int numberOfAvailableNodes; // Number of nodes in headAvailable
    int numberOfCorrectAnswers; // Number of nodes in headUsed
} game;

void printRandom1(game* currentGame)
{
    if (currentGame->headAvailable == NULL || currentGame->numberOfAvailableNodes <= 0) {
        printf("No more questions, you've won!\n");
        exit(1);
    }

    srand(time(NULL)); // Consider moving this to the start of main()

    int chosenIndex = rand() % currentGame->numberOfAvailableNodes;
    questionListNode** current = &(currentGame->headAvailable);
    while ((chosenIndex > 0) && (*current != NULL)) { // the second check is for safety
        current = &((*current)->next);
        chosenIndex--;
    }

    questionListNode* currentQuestion = (*current);
    if (currentQuestion == NULL) {
        printf("Internal error: available count mismatch!\n");
        exit(1);
    }
    printf("%s\n", currentQuestion->data.question);
    int i, ans;

    printf("1.-%s\n", currentQuestion->data.ansr1);
    printf("2.-%s\n", currentQuestion->data.ansr2);
    printf("3.-%s\n", currentQuestion->data.ansr3);
    printf("4.-%s\n", currentQuestion->data.ansr4);

    printf("Enter the correct answer: ");
    scanf("%d", &ans);
    if (ans != currentQuestion->data.correctAnsr) {
        printf("WRONG ANSWER\n");
        printf("GAME OVER\n");
        printf("The correct answer is: %d\n", currentQuestion->data.correctAnsr);
        exit(1);
    }
    printf("CORRECT ANSWER!\n");
    // Remove currentQuestion from the available list
    (*current) = currentQuestion->next;
    // Put currentQuestion into used list
    currentQuestion->next = currentGame->headUsed;
    currentGame->headUsed = currentQuestion;
    // Update counters
    currentGame->numberOfAvailableNodes--;
    currentGame->numberOfCorrectAnswers++;
}

int main(int c, char** t)
{
    game g;
    g.headAvailable = NULL;
    g.headUsed = NULL;
    g.numberOfAvailableNodes = 0;
    g.numberOfCorrectAnswers = 0;

    questionListNode q1 = { { "Question 1", "", "", "A1*", "B1", "C1", "D1", 1, 1, 0 }, NULL };
    questionListNode q2 = { { "Question 2", "", "", "A2", "B2*", "C2", "D2", 2, 2, 0 }, &q1 };
    questionListNode q3 = { { "Question 3", "", "", "A3", "B3*", "C3", "D3", 3, 2, 0 }, &q2 };

    g.headAvailable = &q3;
    g.numberOfAvailableNodes = 3;

    while (1)
        printRandom1(&g);
}

Some additional (random) notes:

  • I am not sure linked-list is the best data structure for this task

  • Consider naming your typedefs with some prefix (e.g. t_game, t_node)

  • If you wanted to re-start the game (instead of exit()) you would need to join the two linked lists back together and reset the counters

Good luck!

Disclaimer: I did not spend that much time checking the code so please take it just as an example...

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.