【问题标题】:Quiz app to pick questions from 8 group of questions randomly?测验应用程序从 8 组问题中随机选择问题?
【发布时间】:2017-11-03 03:31:44
【问题描述】:

我为 iOS 构建了一个应用程序,我希望它从 8 个不同的问题组中随机选择问题。问题数量为 356,其中只有 50 个必须随机选择。

  1. 第一组的 8 个问题
  2. 第二组的 5 个问题
  3. 第三组的 5 个问题
  4. 来自第四组的 6 个问题
  5. 第 5 组的 6 个问题
  6. 来自第 6 组的 5 个问题
  7. 来自第 7 组的 9 个问题
  8. 第 8 组的 6 个问题

总共:50 个问题。

我所做的是,我构建了测验,但它会读取所有问题并将它们显示给用户。这些问题是从 .json 文件中读取的。

这是我的代码: (因为代码上没有cmets,问我吧。)

import UIKit

struct Question {
    var Question: String!
    var Answers: [String]!
    var Answer: Int!

    init(item: [String: Any])
    {
        self.Question = item["Question"] as? String
        self.Answers = item["Answers"] as? [String]
        self.Answer = item["Answer"] as? Int
    }
} 

class LittleTestViewController: UIViewController {

    //MARK: Properties
    @IBOutlet weak var questionLabel: UILabel!
    @IBOutlet var buttons: [UIButton]!

    var Questions = [Question]()
    var QNumber = Int()
    var answerNumber = Int()

override func viewDidLoad() {
        super.viewDidLoad()

        jsonParsingQuestionsFile()
        pickQuestion()
    }

    func jsonParsingQuestionsFile ()
    {
        guard let path = Bundle.main.path(forResource: "data", ofType: "json"),
            let array = (try? JSONSerialization.jsonObject(with: Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe), options: JSONSerialization.ReadingOptions.allowFragments)) as? [[String : Any]] else{
                return
        }
        for item in array
        {
            self.Questions.append(Question(item: item))
        }
    }

    func pickQuestion ()
    {
        if Questions.count > 0 {
            QNumber = 0
            questionLabel.text = Questions[QNumber].Question

            answerNumber = Questions[QNumber].Answer

            for i in 0..<buttons.count{
                buttons[i].setTitle(Questions[QNumber].Answers[i], for: UIControlState.normal)
            }
            Questions.remove(at: QNumber)
        }
        else
        {
           print ("End")
        }
    }

@IBAction func btn1(_ sender: UIButton){
        Unhide()
        if answerNumber == 0 {
            print ("Correct!!")
        }
        else
        {

        }
    }

    @IBAction func btn2(_ sender: UIButton) {
        Unhide()
        if answerNumber == 1 {
           print ("Correct!!")
        }
        else
        {

        }
    }
    @IBAction func btn3(_ sender: UIButton) {
        Unhide()
        if answerNumber == 2 {
            print ("Correct!!")
        }
        else
        {

        }
    }
    @IBAction func btn4(_ sender: UIButton) {
        Unhide()
        if answerNumber == 3 {
            print ("Correct!!")
        }
        else
        {

        }
    }
}

data.json

[ {"Question":"Group 1. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 1. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 1. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 3},
  {"Question":"Group 2. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 2. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 1},
  {"Question":"Group 2. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 3. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 3. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 4. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 4. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 3},
  {"Question":"Group 4. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 5. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 0},
  {"Question":"Group 5. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 6. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 0},
  {"Question":"Group 7. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},
  {"Question":"Group 8. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 0},
  {"Question":"Group 8. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 1},
  {"Question":"Group 9. lalala?", "Answers":["lala","trtr","asas","bbbb"],"Answer": 2},]

这个 .json 文件只是一个示例,每个组都有更多问题。每个小组有大约 45 个问题。

【问题讨论】:

    标签: ios json swift


    【解决方案1】:

    不要用代码弄乱你的逻辑。

    如果您担心时间复杂性 - 难以实施,请按照此操作

    只需按照以下算法即可。

    由于您有 8 个组,因此创建一个整数数组,该数组最多可容纳 8 个值并使用全 0 进行初始化

    Array(1)  =   [0 0 0 0 0 0 0 0]
    

    并创建另一个数组,其中包含可以从看起来像的每个组中提取的最多问题

    Array(2)  =   [8 5 5 6 6 5 9 6]
    

    另外,应该有一个数组来保存每个组中剩余的问题数

    n[]   =  [ 8elements ] not mensioned in question
    

    开始

    循环

    1) 创建一个1-8之间的随机数来选择组

    2) 检查小组是否已经选择了最多的问题。通过比较 array(1) 和 array(2) 数组,如果是,请再次执行第 1 步。

    3) 让随机选择的组中的最大问题为 n。生成一个介于 1-n 之间的随机数。数组(1)中对应位置加1,n减1。从组中删除选中的问题 检查您是否达到 50 个问题 如果是,请退出 如果没有,请执行第 4 步

    4) 将您随机选择的问题保存在某处。并继续执行第 1 步

    最好将 50 个问题附加到一个数组中并放入 UI。

    这是您不考虑复杂性的时候 - 易于实现

    为此,您需要将所有问题组随机播放

    Refer this post shuffle

    然后从每个组中提取第一组问题(你想要多少)。这将是随机的。

    给你的建议:先解决问题,再写代码!

    【讨论】:

      【解决方案2】:

      我建议您制作一个新的 .json 文件,其中包含 8 个不同组中的 8 组问题,例如问题 1、问题 2 等。然后使用开关制作 8 个案例,如果选择的问题数量则打破每个案例random 是您希望每个组的数字。

      【讨论】:

        【解决方案3】:

        感谢大家的建议。但我找到了如何做到这一点的方法。我只更改了 pickQuestion 函数。

         func pickQuestion ()
        {
            if Questions.count > 0 && questionscount < 8{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("KEK")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("KEK")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions[QNumber].Answers[i], for: UIControlState.normal)
                }
                print(QNumber)
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 13{
        
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("M")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("M")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("M")}[QNumber].Answer
        
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("M")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                print(QNumber)
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 18{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("N")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("N")}[QNumber].Question
        
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("N")}[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("N")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 24{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("A")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("A")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("A")}[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("A")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 30{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("ΑΔ")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("ΑΔ")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("ΑΔ")}[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("ΑΔ")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 35{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("ΕΠ")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("ΕΠ")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("ΕΠ")}[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("ΕΠ")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 44{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("T")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("T")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("T")}[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("T")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                Questions.remove(at: QNumber)
        
            }else if Questions.count > 0 && questionscount < 50{
                QNumber = Int(arc4random_uniform(UInt32(Questions.filter{$0.Question.hasPrefix("ΑΝΘ")}.count)))
                questionscount += 1
                questionLabel.text = Questions.filter{$0.Question.hasPrefix("ΑΝΘ")}[QNumber].Question
        
                self.title = "Ερώτηση: \(Int(questionscount))/50"
                answerNumber = Questions.filter{$0.Question.hasPrefix("ΑΝΘ")}[QNumber].Answer
        
                for i in 0..<buttons.count{
                    buttons[i].setTitle(Questions.filter{$0.Question.hasPrefix("ΑΝΘ")}[QNumber].Answers[i], for: UIControlState.normal)
                }
                Questions.remove(at: QNumber)
        
            }else
            {
                let alert = UIAlertController(title: "Σκόρ", message: "Απάντησες σωστά τις \(Int(score)) από τις \(Int(questionscount)) ερωτήσεις! \n \(String(format: "%.0f",(score/questionscount*100))) %", preferredStyle: UIAlertControllerStyle.alert)
                alert.addAction(UIAlertAction(title: "Μενού", style: UIAlertActionStyle.default, handler: { action in
                    self.navigationController?.popToRootViewController(animated: true)
                }))
                self.present(alert, animated: true, completion: nil)
            }
            Hide()
        }
        

        【讨论】:

        • 检查你做了什么,有一半的时间你只是改变了前缀。可能值得尝试创建另一个将前缀作为参数的函数。可读性和可维护性将迅速提高。
        【解决方案4】:

        根据您的data.json,您将收到一个包含 356 个问题的列表。 “8 个组*”只是组名称,每个“问题”的一个“属性”就是组。

        如果您实际上是在组个问题中接收数据,那么第一步是将它们一起附加到一个组中,如此处所示。

        那么,如何从 356 个问题的列表中显示 50 个随机问题?

        • 生成一个由 0 到 355 的数字组成的数组(数组从零开始)。
        • 随机播放该数组。那里有很多很好的例子 - 这里有一个相当全面的参考:https://stackoverflow.com/a/24029847/6257435

        数组的前 50 个元素现在包含 0 到 355 之间的随机(无重复)值,因此您可以简单地按该顺序显示实际问题。


        编辑:

        如果要求包括每组预定数量的问题,那只会增加几个步骤:

        不要使用包含所有 356 个问题的大数组,而是将您的 json 数据拆分为 8 个数组,每个数组包含属于特定组的问题。

        然后,将这些数组添加到“组”的二维数组中。

        接下来,构建一个由问题“ID”编号组成的二维数组 - 只是每组中从 0 到问题数量的序列 - 然后随机排列每个数组。

        结果将是每组的 X 个随机问题。

        这是一个可以在 Playground 页面中运行的简单示例。该代码生成一个 Question 对象数组,以及相应的“索引”打乱数组。点击“下一个问题”按钮将逐步查看结果。


        import UIKit
        import PlaygroundSupport
        
        // simple random number function
        func random(_ range:Range<Int>) -> Int {
            return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound)))
        }
        
        // shuffling extension
        extension MutableCollection where Indices.Iterator.Element == Index {
            /// Shuffles the contents of this collection.
            mutating func shuffle() {
                let c = count
                guard c > 1 else { return }
        
                for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
                    let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
                    guard d != 0 else { continue }
                    let i = index(firstUnshuffled, offsetBy: d)
                    swap(&self[firstUnshuffled], &self[i])
                }
            }
        }
        
        extension Sequence {
            /// Returns an array with the contents of this sequence, shuffled.
            func shuffled() -> [Iterator.Element] {
                var result = Array(self)
                result.shuffle()
                return result
            }
        }
        
        // Question object
        struct Question {
            var Question: String!
            var Answers: [String]!
            var Answer: Int!
        
            init(item: [String: Any])
            {
                self.Question = item["Question"] as? String
                self.Answers = item["Answers"] as? [String]
                self.Answer = item["Answer"] as? Int
            }
        }
        
        // standard UIViewController
        class TestViewController : UIViewController {
        
            // standard UIButton
            let btn: UIButton = {
                let b = UIButton()
                b.setTitle("  Next Question  ", for: .normal)
                b.backgroundColor = .red
                b.translatesAutoresizingMaskIntoConstraints = false
                return b
            }()
        
            // standard UILabel
            let questionLabel: UILabel = {
                let v = UILabel()
                v.backgroundColor = .white
                v.numberOfLines = 0
                v.translatesAutoresizingMaskIntoConstraints = false
                return v
            }()
        
            // two-dimensional array of Question objects
            var arrayOfQuestions = [[Question]]()
        
            // two-dimension array of shuffled Index values
            var arrayOfIDs = [[Int]]()
        
            // number of questions per group
            let questionsPerGroup = [8, 5, 5, 6, 6, 5, 9, 6]
        
            // note: arrays are Zero-based, 
            //  so "first question" index will be Zero
            //  and "first group" index will be Zero
        
            // start Question counter at -1 so "next question" will be Zero
            var currentQuestion: Int = -1
        
            // group counter
            var currentGroup: Int = 0
        
            override func viewDidLoad() {
                super.viewDidLoad()
        
                // this is just generating 8 groups of Questions that look like:
                // {"Question":"Group: 1 Question: 1", "Answers":["A", "B", "C", "D"], "Answer":1}
        
                for iGroup in 1...8 {
        
                    //  each group will have between 43 and 48 questions
                    let numQuestions = random(43..<49)
        
                    // new empty array
                    var aGroup = [Question]()
        
                    for iQuestion in 1...numQuestions {
        
                        let s: [String:Any] = [
                            "Question":"Group: \(iGroup) Question: \(iQuestion)",
                            "Answers":["A", "B", "C", "D"],
                            "Answer": random(0..<3)
                        ]
        
                        let q = Question(item: s)
        
                        aGroup.append(q)
        
                    }
        
                    // append this "group" to the array
                    arrayOfQuestions.append(aGroup)
        
                    // create array of numbers 0 through number of questions -1
                    let aIDs = Array(0..<numQuestions)
        
                    // shuffle that array and append to "IDs" array
                    arrayOfIDs.append(aIDs.shuffled())
        
                }
        
                // add a button and label to the view
                self.view.addSubview(btn)
                self.view.addSubview(questionLabel)
        
                btn.topAnchor.constraint(equalTo: view.topAnchor, constant: 40.0).isActive = true
                btn.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0.0).isActive = true
        
                questionLabel.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0).isActive = true
                questionLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16.0).isActive = true
                questionLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16.0).isActive = true
        
                // add touch up target to the button
                btn.addTarget(self, action: #selector(didTap(_:)), for: .touchUpInside)
        
                // show the first question
                showNextQuestion()
        
            }
        
            func showNextQuestion() -> Void {
        
                // increment currentQuestion
                currentQuestion += 1
        
                // if we are past the number of questions in this group
                //  set currentQuestion back to Zero and increment currentGroup
                if currentQuestion == questionsPerGroup[currentGroup] {
                    currentQuestion = 0
                    currentGroup += 1
                }
        
                // if we are past the last group, show a message
                if currentGroup == questionsPerGroup.count {
                    questionLabel.text = "End of quiz"
                } else {
        
                    // get the question ID from the shuffled IDs of the current group
                    let idx = arrayOfIDs[currentGroup][currentQuestion]
        
                    // get that question object from the array
                    let thisQuestion = arrayOfQuestions[currentGroup][idx]
        
                    // get the question parts
                    let sQuestion = thisQuestion.Question ?? "missing data"
                    let aAnswers = thisQuestion.Answers ?? ["missing data"]
                    let iAnswer = thisQuestion.Answer ?? -1
        
                    // show them in our label
                    questionLabel.text = "\nThis is Question: \(currentQuestion + 1) of Group: \(currentGroup + 1)\n\n" +
                        "\(sQuestion)\n" +
                        "\(aAnswers)\n" +
                        "\(iAnswer)\n"
                }
        
            }
        
            func didTap(_ sender: Any?) -> Void {
                showNextQuestion()
            }
        
        }
        
        let vc = TestViewController()
        vc.view.backgroundColor = .blue
        PlaygroundPage.current.liveView = vc
        

        【讨论】:

        • 如果我像我一样将所有问题附加到一个数组中,然后执行 8 个 if 语句并说在第一个“if”上过滤所有包含“group1”的元素并只选择 8 个元素从那里开始,为其他组做同样的事情。你听起来怎么样?
        • 对于 group2 选择 5 个元素等,直到我达到 50 个元素。
        • 您需要第 1 组中的 8 个、第 2 组中的 5 个、第 3 组中的 5 个、第 4 组中的 6 个等等......?还是您只需要 50 个随机问题,所以您可能有 1 组中的 1 个、第 2 组中的 0 个、第 3 组中的 17 个等?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-27
        • 2015-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-04
        相关资源
        最近更新 更多