ios - How can I make a swift multiple questions quiz so the questions do not repeat themselves? -


i not have experience programing. have done looking @ youtube videos couple of months. appreciate if can please me. when run code simulator repeats questions several time before next new question presented. run presents 1 question without repeating same question on , over. below please find code.

import uikit  class viewcontroller: uiviewcontroller {      @iboutlet weak var questionlabel: uilabel!      @iboutlet weak var button1: uibutton!      @iboutlet weak var button2: uibutton!      @iboutlet weak var button3: uibutton!      @iboutlet weak var button4: uibutton!      @iboutlet weak var next: uibutton!      @iboutlet weak var labelend: uilabel!     var correctanswer = string()       override func viewdidload() {         super.viewdidload()         // additional setup after loading view, typically nib.         hide()         ramdomquestions()     }      func ramdomquestions () {         var randomnumber = arc4random() % 4         randomnumber += 1          switch (randomnumber) {          case 1:             questionlabel.text = "hola familia, cual es mi nombre? "             button1.settitle ("cesar", forstate: uicontrolstate.normal)             button2.settitle ("karlos", forstate: uicontrolstate.normal)             button3.settitle ("william", forstate: uicontrolstate.normal)             button4.settitle ("chiqui", forstate: uicontrolstate.normal)             correctanswer = "2"              break         case 2:             questionlabel.text = "hola famili, cual es mi apellido? "             button1.settitle ("perez", forstate: uicontrolstate.normal)             button2.settitle ("carvajal", forstate: uicontrolstate.normal)             button3.settitle ("garcia", forstate: uicontrolstate.normal)             button4.settitle ("sanchez", forstate: uicontrolstate.normal)             correctanswer = "1"              break         case 3:             questionlabel.text = "quien hace la lachona mas rica? "             button1.settitle ("willy", forstate: uicontrolstate.normal)             button2.settitle ("mario", forstate: uicontrolstate.normal)             button3.settitle ("karlos", forstate: uicontrolstate.normal)             button4.settitle ("juan david", forstate: uicontrolstate.normal)             correctanswer = "1"              break         case 4:             questionlabel.text = "quien hace las tartas mas lindas"             button1.settitle ("jili", forstate: uicontrolstate.normal)             button2.settitle ("carvajal", forstate: uicontrolstate.normal)             button3.settitle ("garcia", forstate: uicontrolstate.normal)             button4.settitle ("leidy y liz", forstate: uicontrolstate.normal)             correctanswer = "4"              break          default:             break         }     }      func hide (){         labelend.hidden = true         next.hidden = true     }      func unhide () {         labelend.hidden = false         next.hidden = false     }      @ibaction func button1action(sender: anyobject) {         unhide()         if (correctanswer == "1") {             labelend.text = "correcto"         }         else{             labelend.text = "falso"         }     }      func button2action(sender: anyobject) {         unhide()         if (correctanswer == "2") {             labelend.text = "correcto"          }         else{             labelend.text = "falso"         }     }      func button3action(sender: anyobject) {         unhide()         if (correctanswer == "3") {             labelend.text = "correcto"         }         else{             labelend.text = "falso"         }     }      func button4action(sender: anyobject) {         unhide()         if (correctanswer == "4") {             labelend.text = "correcto"         }         else{             labelend.text = "falso"         }     }      @ibaction func next(sender: anyobject) {         ramdomquestions()     } } 

the typical solution have array of questions (or indexes model) , shuffle array it's random.

note, when generating random number, should not use arc4random % operator. introduces small modulo bias. instead, use arc4random_uniform. , shuffling array, should use fisher-yates algorithm, eliminates subtle biases introduced naive shuffling algorithms. general information, see fisher-yates article in wikipedia. specific swift implementation, see how shuffle array in swift?. anyway, algorithm looks like:

extension mutablecollectiontype index == int {     /// shuffle elements of `self` in-place.     mutating func shuffleinplace() {         // empty , single-element collections don't shuffle         if count < 2 { return }          in 0 ..< count - 1 {             let j = int(arc4random_uniform(uint32(count - i))) +             if != j {                 swap(&self[i], &self[j])             }         }     } } 

you can use so:

var questionindexes = array(0 ..< questions.count)  // builds array [0, 1, 2, ... n-1], _n_ number of questions questionindexes.shuffleinplace()                    // shuffle list 

you end array of numbers 0 through n-1 shuffled (i.e. appear in random order, no number occurs more once). can iterate through array of questionindexes , each question asked once , once, they'll presented in random order.


a couple of unrelated observations:

  1. you want adopt cocoa naming conventions, namely method , property names should start lowercase letter. data types (e.g. classes or structs) , enums start uppercase letters.

  2. when doing switch statement in swift, don't need break. swift doesn't fall through objective-c does. when tackled point 5, below, turns out ended factoring out switch statement entirely, future reference, don't need break @ end of each case in swift did in c-based programming languages objective-c. in fact, if want swift case statement fall through next one, in objective-c, you'd have use fallthrough keyword.

  3. you shouldn't initialize correctanswer string(). declare optional (an implicitly unwrapped one, if want).

  4. even better, correctanswer should int rather string. i'd use zero-based value can value confirm whether right button pressed.

  5. this more advanced topic, i'd suggest separating "model" (i.e. data question text, potential answers, , correct answer) "controller" (the code takes information model , updates view). part of model-view-controller paradigm use in our apps. makes app easier maintain in future (e.g. can add more questions, change questions, etc., not have touch code in view controller). enables more flexible patterns (e.g. questions , answers provided remote web service or stored in database).

    for example, might have type captures question, potential answer, , identifies correct answer.

    struct question {     let question: string     let answers: [string]     let correctanswer: int } 

    your model might consist of array of question objects:

    var questions: [question] = [     question(         question: "hola familia, cual es mi nombre?",         answers: ["cesar", "karlos", "william", "chiqui"],         correctanswer: 1),     question(         question: "hola famili, cual es mi apellido?",         answers: ["perez", "carvajal", "garcia", "sanchez"],         correctanswer: 0),     question(         question: "quien hace la lachona mas rica?",         answers: ["willy", "mario", "karlos", "juan david"],         correctanswer: 2),     question(         question: "quien hace las tartas mas lindas?",         answers: ["jili", "carvajal", "garcia", "leidy y liz"],         correctanswer: 3) ] 

    note, forgive changing "correct answer" in these questions presented in question. wanted illustrate we're dealing numbers 0 through 3 (not 1 through 4).


pulling together, might have implementation looks like:

import uikit  struct question {     let question: string     let answers: [string]     let correctanswer: int }  class viewcontroller: uiviewcontroller {      @iboutlet weak var questionlabel: uilabel!      @iboutlet weak var button1: uibutton!     @iboutlet weak var button2: uibutton!     @iboutlet weak var button3: uibutton!     @iboutlet weak var button4: uibutton!      lazy var buttons: [uibutton] = { return [self.button1, self.button2, self.button3, self.button4] }()      @iboutlet weak var nextbutton: uibutton!      @iboutlet weak var endlabel: uilabel!      var questions: [question] = [         question(             question: "hola familia, cual es mi nombre?",             answers: ["cesar", "karlos", "william", "chiqui"],             correctanswer: 1),         question(             question: "hola famili, cual es mi apellido?",             answers: ["perez", "carvajal", "garcia", "sanchez"],             correctanswer: 0),         question(             question: "quien hace la lachona mas rica?",             answers: ["willy", "mario", "karlos", "juan david"],             correctanswer: 2),         question(             question: "quien hace las tartas mas lindas?",             answers: ["jili", "carvajal", "garcia", "leidy y liz"],             correctanswer: 3)     ]      var questionindexes: [int]!     var currentquestionindex = 0      override func viewdidload() {         super.viewdidload()          questionindexes = array(0 ..< questions.count)  // builds array [0, 1, 2, ... n]         questionindexes.shuffleinplace()                // randomizes list          updatelabelsandbuttonsforindex(0)     }      func updatelabelsandbuttonsforindex(questionindex: int) {         // if we're done, show message in `endlabel` , hide `nextbutton`          guard questionindex < questions.count else {             endlabel.hidden = false             endlabel.text = "all done!"             nextbutton.hidden = true             return         }          // update our property          currentquestionindex = questionindex          // hide end label , next button          hideendlabelandnextbutton()          // identify question we're presenting          let questionobject = questions[questionindexes[questionindex]]          // update question label , answer buttons accordingly          questionlabel.text = questionobject.question         (answerindex, button) in buttons.enumerate() {             button.settitle(questionobject.answers[answerindex], forstate: .normal)         }     }      func hideendlabelandnextbutton() {         endlabel.hidden = true         nextbutton.hidden = true     }      func unhideendlabelandnextbutton() {         endlabel.hidden = false         nextbutton.hidden = false     }      // note, because created array of `buttons`, don't need     // have 4 `@ibaction` methods, 1 each answer button,      // rather can index button in `buttons` array     // , see if index button matches index of correct     // answer.      @ibaction func didtapanswerbutton(button: uibutton) {         unhideendlabelandnextbutton()          let buttonindex = buttons.indexof(button)         let questionobject = questions[questionindexes[currentquestionindex]]          if buttonindex == questionobject.correctanswer {             endlabel.text = "correcto"         } else {             endlabel.text = "falso"         }     }      @ibaction func didtapnextbutton(sender: anyobject) {         updatelabelsandbuttonsforindex(currentquestionindex + 1)     }  }  extension mutablecollectiontype index == int {     /// shuffle elements of `self` in-place.     mutating func shuffleinplace() {         // empty , single-element collections don't shuffle         if count < 2 { return }          in 0 ..< count - 1 {             let j = int(arc4random_uniform(uint32(count - i))) +             if != j {                 swap(&self[i], &self[j])             }         }     } } 

there's lot buried in there, wouldn't worry details if don't quite follow that's going on here. key is, build array of indexes model, shuffle it, , can proceed iterate through shuffled array , you're guaranteed won't ask same question twice.


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -