Avoid questions appear twice in my quiz app

Hi!
I'm almost ready with my quiz app. I have a minor problem. I can't find how I have to avoid questions appear twice or more I my quiz. Does anyone know how to do this?

Rather than requesting a random list of quiz questions from the start, you could create a loop where each time you add a new question to your list you then reduce the space of available questions to get the next one from.

Thank you! Because I am still a beginner in making apps, I don't quite understand you. Here's some code:

struct Question {
    let text: String
    let answers: [Answer]
	}
    struct Answer {
    let text: String
    let correct: Bool
	}
private func ConfiqureUI(question: Question){
        label.text = question.text
        label.adjustsFontSizeToFitWidth = true
        CurrentQuestion = question
        table.reloadData()
    }
let NextQuestion = allQuestions.randomElement()
                    print("\(NextQuestion!.text)")
                    CurrentQuestion = nil
                    ConfiqureUI(question:NextQuestion!)
                    Progress += 1
                    updateLabel()

Can you help me further? Thanks in advance!

You're going to need to keep a list of questions which have already appeared, and then when you select the next question (allQuestions.randomElement()), you need to keep trying until you find one not on the list. So in principle, something like this:

// Select a question.
var nextQuestion = allQuestions.randomElement()

// Check that this question wasn't shown already.
while didWeAlreadyShowThisQuestion(nextQuestion) {
  nextQuestion = allQuestions.randomElement() // Try again.
}

// Mark this question as shown so we don't choose it again.
markQuestionAsShown(nextQuestion)

// Okay: 'nextQuestion' is definitely not a duplicate.

So now the question is: how do we store a list of questions, and how do we mark a question as shown?

There are lots of options, optimised for different use-cases:

  • Store a list of questions in an Array<Question>. Check questions using .contains(nextQuestion) and add questions to the list using .append(nextQuestion). It would help to make Question and Answer conform to Equatable. This is a better option if the number of questions in the quiz is small.

  • Store the list of questions in a Set<Question>. Check questions using .contains(nextQuestion) and add questions to the list using .insert(nextQuestion). You will have to make Question and Answer conform to Equatable and Hashable. Set has a very fast contains() operation which always takes roughly the same amount of time, regardless of how many things are in it. This is a better option if the number of questions in the quiz is large (like if you had a quiz consisting of 10,000 questions - better to use a Set in that case). It probably doesn't apply to your situation, but I think it's important when learning to understand the choices you make and the options you have to do things in other ways.

  • Rather than storing a list of Question objects, store a list of indexes in one of the above data structures (Array or Set). Both of the above suggestions compare content, which is great and correct, but perhaps not the most efficient way of doing things. If you know your allQuestions database doesn't itself contain any duplicates, you can switch to comparing positions instead.

    So your list of previously-shown questions won't be [question A, question B, question C, ...], but rather [the question at position 5, the question at position 117, the question at position 41, ...]. Regardless of which data-structure you choose, this is a more efficient solution, because we are simply comparing positions rather than content.

As you're learning, it's helpful to start with one of the first 2 options, just to get a feel for what you're doing. But modern software development also prioritises efficiency: these days lots of devices are battery-powered, so it's important to know when you can do the same job using less energy. I think most experienced Swift developers would write this using indexes, so I would encourage you to try it out and get comfortable with the idea.

Put the questions in the order you want them to appear, then iterate through them. Perhaps you want to shuffle them first.

Shuffling quizzes was key in my Spanish-verb-conjugation app. Here is the line in the Quiz model that shuffles. Twice!

You may notice that the app doesn't shuffle if shouldShuffle is false. Showing the same questions in the same order is helpful for UI tests.

Thank you all for the answers! Hopefully it will work.