Приложение Quiz не должно повторять случайные вопросы

Я знаю, что есть некоторые решения с перемешиванием или чем-то в этом роде, но я не знаю, смогу ли я применить их в своем коде. Не могли бы вы мне помочь? Как сделать, чтобы вопросы не повторялись?

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...* /

}

person nicolasxviii    schedule 11.05.2015    source источник
comment
Какой именно у вас здесь вопрос?   -  person Eendje    schedule 11.05.2015
comment
Если есть код, то вопросы не повторяются (спасибо за вопрос) @JacobsonTalom   -  person nicolasxviii    schedule 11.05.2015
comment
по грамматическим причинам я удалил свой ответ - спасибо за отличный урок @fogmeister   -  person Daij-Djan    schedule 11.05.2015
comment
возможный дубликат Как перетасовать массив в Swift?   -  person Daij-Djan    schedule 11.05.2015
comment
Может кто-нибудь, пожалуйста, перестаньте голосовать за все на этой странице. Хотя бы объясни почему?! Нет абсолютно ничего хорошего в том, чтобы триггер был доволен кнопкой голосования против. Особенно на правильные ответы.   -  person Fogmeister    schedule 11.05.2015
comment
@Daij-Djan нет необходимости удалять его: D Просто хотел указать на это, поскольку это общедоступный фреймворк: D, хотя ваш ответ был в порядке. Нет необходимости удалять его.   -  person Fogmeister    schedule 11.05.2015
comment
@Fogmeister Я исправил это там   -  person Daij-Djan    schedule 11.05.2015
comment
@nicolasxviii Я объяснил наихудший подход к этой проблеме в своем ответе. И вы приняли ответ, который делает именно то, что я сказал не делать.   -  person Fogmeister    schedule 12.05.2015


Ответы (5)


Ваш код необходимо переформатировать, сохраняя его таким (тот, который вы предлагаете), вы в конечном итоге будете добавлять огромные куски кода каждый раз, когда вам нужно добавить новый вопрос. Пожалуйста, рассмотрите возможность сделать это следующим образом:

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.
}

тогда

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.. 
 }
} 

Указанная здесь функция перемешивания может быть любой из указанных в качестве ответов на сортировка массивов в swift

person Hugo Alonso    schedule 11.05.2015
comment
Большое спасибо всем, и я действительно не понимаю, почему людям не нравится такая хорошая работа, суть в том, чтобы получить помощь, а не осуждать. - person nicolasxviii; 12.05.2015
comment
@nicolasxviii Я вижу, что ваш принятый вопрос вызвал неоднозначную дискуссию в этом посте, вы всегда можете удалить принятый ответ и назначить его другому ответу. Как всегда, вы уверены, что ответ действительно лучше. - person Hugo Alonso; 13.05.2015

Худший способ приблизиться к этому — продолжать генерировать случайные числа и «отслеживать» числа, которые уже использовались. Для массива из 100 вопросов вам придется подбрасывать последнее случайное число в среднем 100 раз, чтобы получить последний доступный вопрос.

Самый простой способ сделать что-то подобное — просто перетасовать массив перед его использованием, а затем выполнить итерацию по порядку.

Вы можете увидеть реализацию перетасовки Фишера-Йейтса в этом ответе... Как перетасовать массив в Swift?

Тогда это просто случай итерации массива...

for question in shuffledArray {
    // ask question
}

Вы даже можете создать для него генератор, который позволит вам получить вопрос next и так далее.

Кроме того, вы делаете это неправильно, используя переключатель и включая случайное значение.

Создайте объект Question со свойствами... questionText, option1, option2, correctAnswer... и т.д...

Вы даже можете создать массив опций и хранить рядом с ним correctAnswerIndex.

Затем вставьте все объекты Question в массив. Еще лучше поместите их в файл plist, чтобы вы могли читать их во время выполнения. Так гораздо проще управлять.

person Fogmeister    schedule 11.05.2015

Мой ответ на другой пост:

var someArray = Array(1...28)

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

someArray.removeAtIndex(index)

И тогда вы можете передать randomNumber своей функции:

func randomQuestions(question: Int) {
    switch(question) {
    case 1: // Question1
    case 2: // Question2
}
person Eendje    schedule 11.05.2015
comment
Хорошо, большое спасибо, пожалуйста, скажите мне, когда найдете @JacobsonTalom - person nicolasxviii; 11.05.2015
comment
Извините, это не я. Я не могу легко проголосовать против, если только кто-то не грубит и не нарушает правила. - person Eendje; 11.05.2015
comment
@JacobsonTalom хорошо, не беспокойся. - person Fogmeister; 11.05.2015
comment
Я на самом деле удивлен ответом, что он, похоже, еще не нашел решения, хотя проблема кажется довольно простой (мой ответ, конечно, лучший! :p). - person Eendje; 11.05.2015
comment
Что ж, теперь он нашел ответ... неправильный ответ. Ржу не могу! Ну что ж. - person Fogmeister; 12.05.2015

Попытка сделать так, чтобы arc4random() не повторялось, — неправильный подход к этой проблеме. Вы хотите не задавать один и тот же вопрос дважды, поэтому вам нужно как-то отслеживать вопросы, которые вы уже задавали. Я рекомендую использовать массив и, возможно, присвоить каждому вопросу какой-либо идентификатор, а затем сохранить каждый идентификатор вопроса в массиве и удалить их или переместить в новый массив «задаваемых вопросов» по ​​мере их появления.

person Will    schedule 11.05.2015

Я бы добавил в контроллер представления переменную, которая будет содержать уже заданные вопросы:

var askedQuestions = [Int]()

Затем в вашей функции вы можете сделать что-то вроде:

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...*/

}

Также обратите внимание, что вы должны позаботиться о том, что произойдет, когда у вас закончатся все 28 вопросов. :)

PS: лучше не использовать имена переменных с заглавной буквы, такие как RandomNumber. Вместо этого используйте randomNumber. Это хорошая практика. :)

person Jure    schedule 11.05.2015
comment
что приводит к бесконечному циклу в конце - person Daij-Djan; 11.05.2015
comment
Ты хоть читал, что я написал? Да, после того как все 28 вопросов будут заданы, это не сработает. Я не знаю, каков вариант использования и что ожидается, когда все 28 закончатся. Это начинается сначала? Игра окончена? Не знаю ... Однако не уверен, почему вы должны понизить ответ. :) - person Jure; 11.05.2015
comment
вы работаете в бесконечном цикле и НЕ ТОЛЬКО после того, как это будет сделано, но как только появятся дублированные вопросы. Просто исправьте это как исправлено мое, и все в порядке - person Daij-Djan; 11.05.2015
comment
Как вы понимаете повторяющиеся вопросы? Внутри массива askedQuestions не может быть повторяющихся вопросов? Я добавлю проверку безопасности, чтобы предотвратить бесконечный цикл, но, как я уже сказал, я понятия не имею, что пытается сделать автор, когда у него заканчиваются вопросы. - person Jure; 11.05.2015
comment
Большое спасибо, Юре, и ты был прав, @Daij-Djan есть и бесконечный верх, ты знаешь, как я могу вернуть игру в меню? - person nicolasxviii; 12.05.2015
comment
1. Вы не должны использовать arc4random с модом. 2. Вы не должны использовать для этого переключатель. 3. Это невероятно неэффективный способ найти все случайные вопросы. 4. Для большого количества вопросов это займет неопределенное время. 5. Серьезно, это как O(undefined). 6. ЛЮБОЙ другой ответ (не только мой) лучше этого. 7. Это неправильный ответ, не используйте его. Используйте другой ответ. - person Fogmeister; 12.05.2015
comment
Это также не очень эффективно по сравнению с тем, что вы запрашиваете столько случайных значений, сколько вам нужно, как и ответы других. - person Will; 12.05.2015
comment
полностью согласна с fommeister - person Daij-Djan; 12.05.2015