-2

I'm creating a simple quiz app and would like to always show different questions; here is my code, the part about random numbers is in "nextQuestion()", but doesnt seem to work, no errors appeared on the console

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Collections.Generic;
using System.Linq;

public class test : MonoBehaviour {

public Text question;
public Text answerA;
public Text answerB;
public Text answerC;
public Text answerD;
public Text answersInfo;

public int themeid;

public string[] questions; //store all questions
public string[] choicesA;  //store all choices A
public string[] choicesB;  //store all choices B
public string[] choicesC;  //store all choices C
public string[] choicesD;  //store all choices D

public string[] right;     //store all right choices

private int questionid;
private int id;
private bool checkRandom = true;

private float totalRight;
private float totalQuestions;
private float average;
private int finalNote;

List<int> idUsed = new List<int>();

void Start()
{
    id = Random.Range(0, 4);
    questionid = 0;
    totalQuestions = 5;
    question.text = questions[id];
    answerA.text = choicesA[id];
    answerB.text = choicesB[id];
    answerC.text = choicesC[id];
    answerD.text = choicesD[id];

    idUsed.Add(id);

    answersInfo.text = "Answering question " + (questionid + 1).ToString() +     " out of " + totalQuestions.ToString();
}

public void response(string choice)
{
    switch (choice)
    {
        case "A":
            if (choicesA[id] == right[id])
            {
                totalRight += 1;

            }
            break;
        case "B":
            if (choicesB[id] == right[id])
            {
                totalRight += 1;

            }
            break;
        case "C":
            if (choicesC[id] == right[id])
            {

                totalRight += 1;
            }
            break;
        case "D":
            if (choicesD[id] == right[id])
            {

                totalRight += 1;
            }
            break;
    }

    nextQuestion();
}   

void nextQuestion()
{
    questionid += 1;
    if (questionid <= (totalQuestions - 1))
    {          
        totalQuestions = 5;
        id = Random.Range(0, 4);

        while(checkRandom)
        {
            if (idUsed.Contains(id))
            {
                id = Random.Range(0, 4);
            }
            else
            {
                idUsed.Add(id);
                checkRandom = false;
            }
        }

        question.text = questions[id];
        answerA.text = choicesA[id];
        answerB.text = choicesB[id];
        answerC.text = choicesC[id];
        answerD.text = choicesD[id];

        answersInfo.text = "Answering question " + (questionid + 1).ToString() + " out of " + totalQuestions.ToString();

    }
    else
    {
        average = 10 * (totalRight / totalQuestions);
        finalNote = Mathf.RoundToInt(average);

        if (finalNote > PlayerPrefs.GetInt("finalNote" + themeid.ToString()))
        {
            PlayerPrefs.SetInt("finalNote" + themeid.ToString(), finalNote);
            PlayerPrefs.SetInt("totalRight" + themeid.ToString(), (int)totalRight);
        }

        PlayerPrefs.SetInt("finalTempNote" + themeid.ToString(), finalNote);
        PlayerPrefs.SetInt("totalRight" + themeid.ToString(), (int)totalRight);

        SceneManager.LoadScene("FinalNote");
    }
}
ViVi
  • 4,339
  • 8
  • 29
  • 52
  • 2
    You say "but doesnt seem to work". Have you debugged it in visual studio ? What behaviour is it "that doesn't seem to work" ? – PhillipH Jul 16 '16 at 18:33
  • @PhillipH I have, but I'm using it to make questions in the quiz not repeat themselves, which happens whenever I test the app in unity. – Andre Barreira Jul 16 '16 at 19:49

1 Answers1

0

It is not clear from your question what "doesn't seem to work" means. It would be better if you would provide a more specific description of what exactly happens, and how precisely that is different from what you want to happen.

That said, looking at the code it seems to me your concern might be that you expect for the program to never repeat a question during the quiz, but that you sometimes do get the same question more than once.

If that's an accurate description of your problem, then the primary cause is that you never set the checkRandom flag back to true. So once you've selected a question successfully, the code will never verify that subsequently selected questions were not already asked.

One way to fix this would be to set checkRandom to true just before selecting a new question (i.e. in the nextQuestion() method). But really, you shouldn't need the flag at all. You can put the Contains() condition as the actual condition for the loop. For example:

if (questionid <= (totalQuestions - 1))
{          
    totalQuestions = 5;
    id = Random.Range(0, 4);

    while(idUsed.Contains(id))
    {
        id = Random.Range(0, 4);
    }
    idUsed.Add(id);

    question.text = questions[id];
    answerA.text = choicesA[id];
    answerB.text = choicesB[id];
    answerC.text = choicesC[id];
    answerD.text = choicesD[id];

    answersInfo.text = "Answering question " + (questionid + 1).ToString() + " out of " + totalQuestions.ToString();

}

Notes:

  • I don't see any reason to set the totalQuestions field in the code above.
  • IMHO if (questionid < totalQuestions) is a better way to express that condition than if (questionid <= (totalQuestions - 1)).
  • You have a number of fields, including totalQuestions, which you've declared as float when it seems to me that the values really are just integers, i.e. the variable should be int instead of float.
  • You should get into the habit of not copy/pasting code. Elements of your code such as where you set the answersInfo.text property value should be encapsulated in a helper method you can call for that purpose.
  • For a relatively short list of ID values, a List<int> for the idUsed collection is fine. But you should keep in mind the HashSet<T> class (i.e. HashSet<int>) for collections where you will want fast, efficient tests for containment. The list requires searching the entire data structure, while the hash set can determine containment immediately, without having to check more than one location in the collection.
  • Finally, while the loop you're using to choose a random question ID value should work fine, it's a fairly clumsy and inefficient way to do that. A better approach would be to shuffle an array of question ID values and then just select the IDs from the shuffled array in order.


If the above does not address your question, please provide a good Minimal, Complete, and Verifiable code example that reliably reproduces the problem, along with a detailed description of what that code does and what you want it to do instead.

Community
  • 1
  • 1
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • Thank you so much! As you can probably tell, I'm quite new to this , and tend to write the code that just seems logical with a clean slate, as I can't rely on experience - so sorry for my noobiness. The code can now generate different numbers each loop but, when "nextQuestion()" runs for the last question, unity freezes.I suspect it's because the while loop started an endless loop, but I can't see how that is possible nor how I can fix it – Andre Barreira Jul 16 '16 at 23:52
  • Without a good [mcve], it's impossible for me to say for sure what your problem might be. But your guess seems likely. You set `totalQuestions` to `5`, but you are selecting question ID values from only four possibilities (0, 1, 2, and 3). So by the time you get to the `questionid` variable having value of `4`, you have already selected four different values. You either need to allow a larger range of random #'s, or select fewer questions. – Peter Duniho Jul 17 '16 at 01:46