测验应用程序随机挑选8组问题?

时间:2017-11-03 03:31:44

标签: ios json swift

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

  1. 第一组的8个问题
  2. 来自第二组的5个问题
  3. 来自第3组的5个问题
  4. 第4组的6个问题
  5. 来自第5组的6个问题
  6. 第6组的5个问题
  7. 来自第7组的9个问题
  8. 第8组的6个问题
  9. 总计:50个问题。

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

    这是我的代码: (因为没有对代码的评论,请问我。)

    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个问题。

4 个答案:

答案 0 :(得分:2)

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

如果您担心时间复杂性 - 难以实施

,请执行此操作

请按照以下算法进行操作。

由于您有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

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

给你的建议:首先解决问题,然后编写代码!

答案 1 :(得分:1)

我建议你在8个不同的小组中制作一个包含8组问题的新的.json文件,例如问题1,问题2等。之后用开关制作8个案例,如果选择的问题数量则打破每个案例随机是你想要的每个组的数字。

答案 2 :(得分:1)

感谢你们的建议。但我找到了如何做到的方法。我只更改了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()
}

答案 3 :(得分:0)

根据您的data.json,您将收到356个问题的单一列表。 &#34; 8组*只是组指定,具有一个&#34;属性&#34;每个&#34;问题&#34;作为小组。

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

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

  • 生成数字0到355的数组(数组从零开始)。
  • 随机播放该阵列。很多很好的例子 - 这里有一个相当全面的参考:here

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

修改

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

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

然后,将这些数组添加到&#34;组&#34;。

的二维数组中

接下来,建立一个问题的二维数组&#34; ID&#34;数字 - 只是每组中0到数量的问题的序列 - 然后随机播放每个数组。

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

这是一个可以在Playground页面中运行的简单示例。该代码生成一个Question对象数组,以及&#34;索引&#34;的相应混洗数组。点击&#34;下一个问题&#34;按钮将逐步显示结果。

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