0

I know that there are some solutions with shuffle, or something like that, but I dont know if I can apply them in my code. Can you please help me? How do I make the questions not repeat?

func RandomQuestions(){

    var RandomNumber = arc4random() % 28
    RandomNumber += 1

    switch(RandomNumber){
    case 1:
        QuestionLabel.text = "Who is the Numer One Best DJ According to DJ Mag 2014?"
        Button1.setTitle("Tiësto", forState: UIControlState.Normal)
        Button2.setTitle("Avicii", forState: UIControlState.Normal)
        Button3.setTitle("Hardwell", forState: UIControlState.Normal)
        Button4.setTitle("Dimitri Vegas & Like Mike", forState: UIControlState.Normal)
        CorrectAnwser = "3"
        break
    case 2:
        QuestionLabel.text = "Who is the Only DJ that played in an Olimpic Games?"
        Button1.setTitle("Avicii", forState: UIControlState.Normal)
        Button2.setTitle("Tiësto", forState: UIControlState.Normal)
        Button3.setTitle("Armin Van Buuren", forState: UIControlState.Normal)
        Button4.setTitle("Calvin Harris", forState: UIControlState.Normal)
        CorrectAnwser = "2"
        break
    }

    /* ...more questions...* /

}
Will
  • 24,082
  • 14
  • 97
  • 108
nicolasxviii
  • 21
  • 1
  • 5
  • What's exactly your question here? – Eendje May 11 '15 at 03:45
  • If there is a code so the questions do not repeat ( thanks for asking ) @JacobsonTalom – nicolasxviii May 11 '15 at 03:46
  • due to grammar reasons I deleted my answer - Thanks for the awesome lesson @fogmeister – Daij-Djan May 11 '15 at 15:12
  • possible duplicate of [How do I shuffle an array in Swift?](http://stackoverflow.com/questions/24026510/how-do-i-shuffle-an-array-in-swift) – Daij-Djan May 11 '15 at 15:13
  • 1
    Can someone please stop down voting everything on this page. At least explain why?! There is absolutely nothing good that can coming from getting trigger happy with the down vote button. Especially on correct answers. – Fogmeister May 11 '15 at 15:15
  • @Daij-Djan no need to delete it :D Just wanted to point it out seeing as it's a public framework :D your answer was fine though. No need to delete it. – Fogmeister May 11 '15 at 15:19
  • @Fogmeister I fixed it there – Daij-Djan May 11 '15 at 15:38
  • @nicolasxviii I explained "the worst approach to this problem" in my answer. And you accepted an answer that does exactly what I said not to do. – Fogmeister May 12 '15 at 06:51

5 Answers5

4

Your code needs to be reformatted, keeping it this way (the one you propose) you will end up adding huge bunchs of code every time you need to add a new question. Please consider doing it this way:

class Question{
 let question : String
 let optionA: String
 let optionB: String
 let optionC: String
 let optionD: String
 let correctAnswer: Int

 //add initializers here.
}

or

class Question{
 let question : String
 let options: [String]
 let correctAnswer: Int

 //add initializers here.
}

then

class QuestionRepository{
 private var questions: [Question]

 /// use this to load questions to be asked only once per game, this way you will end up having the order in which you will ask questions and there will be no repetitions.
 var readyToAskQuestions : [Question] {
    let shuffledQuestions = shuffle(questions)
    return shuffledQuestions
 }      

 init()
  {
    //build your harcoded 'questions' variable here 
  }

 convenience init(url: String)
 {
   //or load your questions from a file, NSUserDefaults, database sql file, from a webservice on the internet, etc.. 
 }
} 

Shuffle function stated here can be any of the stated as answers at sorting arrays in swift

Community
  • 1
  • 1
Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
  • Thanks a lot to everyone, and i really don't understand why people dislike good work like this , the hole thing of this is to get help not judging – nicolasxviii May 11 '15 at 23:51
  • 1
    @nicolasxviii I'm seeing that your accepted question has raised controversial discussion on this post, you can always remove the accepted answer and assign it to another answer. As always as you are sure that answer is indeed better. – Hugo Alonso May 13 '15 at 15:15
3

The worst way to approach this is to keep generating random numbers and "keep track" of numbers that have already been used. For an array of 100 questions you'll have to roll the last random number on average 100 times to get the last available question.

The easiest way to do something like this would be to just shuffle the array before using it and then iterate through it in order.

You can see an implementation of the Fisher-Yates shuffle in this answer... How do I shuffle an array in Swift?

Then it's just a case of iterating the array...

for question in shuffledArray {
    // ask question
}

You could even create a generator for it that will allow you to get the next question and so on.

Also, you're going about it the wrong way by using a switch and switching on the random value.

Create a Question object that has properties... questionText, option1, option2, correctAnswer... etc...

You could even create an array of options and store the correctAnswerIndex alongside it.

Then stick all the Question objects in an array. Even better, put them in a plist file so you can read them in at runtime. Much easier to manage that way.

Community
  • 1
  • 1
Fogmeister
  • 76,236
  • 42
  • 207
  • 306
2

My answer to another post:

var someArray = Array(1...28)

let index = Int(arc4random_uniform(UInt32(someArray.count)))
let randomNumber = someArray[index]

someArray.removeAtIndex(index)

And then you can pass randomNumber to your function:

func randomQuestions(question: Int) {
    switch(question) {
    case 1: // Question1
    case 2: // Question2
}
Community
  • 1
  • 1
Eendje
  • 8,815
  • 1
  • 29
  • 31
1

Trying to make arc4random() not repeat isn't the right way to look at this problem. You want to avoid asking the same question twice, so you'll need to somehow keep track of the questions you've already asked. I recommend using an array, and perhaps giving each question some type of ID, and then storing each Question ID in the array, and removing them or moving them to a new "asked questions" array as they are asked.

Will
  • 24,082
  • 14
  • 97
  • 108
-3

I would add a variable that will hold already asked questions to the view controller:

var askedQuestions = [Int]()

Then, in your function you can do something like:

func RandomQuestions(){

    var randomNumber:Int = (Int)(arc4random() % 28 + 1)

    while find(askedQuestions, randomNumber) != nil && askedQuestions.count < 28 {
        randomNumber = (Int)(arc4random() % 28 + 1)
    }

    if askedQuestions.count > 28 {
        return
    }

    askedQuestions.append(randomNumber)

    switch(randomNumber){
    case 1:
        QuestionLabel.text = "Who is the Numer One Best DJ According to DJ Mag 2014?"
        Button1.setTitle("Tiësto", forState: UIControlState.Normal)
        Button2.setTitle("Avicii", forState: UIControlState.Normal)
        Button3.setTitle("Hardwell", forState: UIControlState.Normal)
        Button4.setTitle("Dimitri Vegas & Like Mike", forState: UIControlState.Normal)
        CorrectAnwser = "3"
        break
    case 2:
        QuestionLabel.text = "Who is the Only DJ that played in an Olimpic Games?"
        Button1.setTitle("Avicii", forState: UIControlState.Normal)
        Button2.setTitle("Tiësto", forState: UIControlState.Normal)
        Button3.setTitle("Armin Van Buuren", forState: UIControlState.Normal)
        Button4.setTitle("Calvin Harris", forState: UIControlState.Normal)
        CorrectAnwser = "2"
        break
    }

    /* ...more questions...*/

}

Also note that you have to take care of what happens when you run out of all 28 questions. :)

PS: It's best not to use capitalized variable names like RandomNumber. Use randomNumber instead. It's good practice. :)

Jure
  • 3,003
  • 3
  • 25
  • 28
  • that results in an endless loop at the end – Daij-Djan May 11 '15 at 14:13
  • Did you even read what I wrote? Yes, once all 28 questions have been asked, it wont work. I don't know what the use case is and what is expected to happen once all 28 are over. Does it start over? Is it game over? Don't know ... Not sure why you have to downvote the answer, though. :) – Jure May 11 '15 at 14:22
  • you run in an endless loop and NOT ONLY after it is done but as soon as there are duplicated questions. Just fix it as fixed mine and it is ok – Daij-Djan May 11 '15 at 15:01
  • How do you mean duplicated questions? There can't be duplicated questions inside the `askedQuestions` array? I'll add a safety check to prevent an endless loop, but like I already said - I have no idea what the author is trying to do once he runs out of questions. – Jure May 11 '15 at 15:34
  • Thanks a lot Jure and you were right @Daij-Djan there is and endless top do you know a way i could make the game going back to a menu? – nicolasxviii May 12 '15 at 00:01
  • 2
    1. You shouldn't use arc4random with mod. 2. You shouldn't be using a switch for this. 3. This is an incredibly inefficient way of find all the random questions. 4. For large numbers of questions this will take undefined time. 5. Seriously, this is like O(undefined). 6. ANY of the other answers (not just mine) are better than this. 7. This is the wrong answer, don't use it. Use a different answer. – Fogmeister May 12 '15 at 06:48
  • This is also not very efficient, compared for only asking for as many random values as you need, as others' answers do. – Will May 12 '15 at 07:19
  • totally agree with fogmeister – Daij-Djan May 12 '15 at 07:23