在iOS中随机显示字符串而不重复它们

时间:2016-01-25 11:03:32

标签: ios swift random

我正在制作一个测验应用。该应用程序使用.json文件作为'数据库'的问题和答案。这个.json文件如下所示......

      {
        "id" : "1",
        "question": "Earth is a:",
             "answers": [
            "Planet",
            "Meteor",
            "Star",
            "Asteroid"
          ],
          "difficulty": "1"
      }

......只是继续讨论500多个问题。

我使用以下代码随机显示问题:

    let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
    LoadQuestion(randomNumber)

这项工作很好,但因为它会随机选择问题,我发现问题的重复性过于频繁(即使我有500多个问题!)。

我对此进行了广泛的研究,并认为我读得太多,因为我现在很困惑。我已经阅读了有关保存所提问题索引以及尝试使用NSUserDefault的播种问题。

简而言之,我如何修改代码以实现以下结果之一:

  1. 根本不重复任何问题,但在所有问题都被问过一次时停止提问;
  2. 与上述1类似,但是用户设置了问题的数量,而不是询问数据库中的所有问题;
  3. 在首先询问所有问题之前,不要重复任何问题;或者,
  4. 不重复之前已正确回答的任何问题,但可能会重复错误回答的问题。
  5. 以下是我认为相关的代码:

        LoadAllQuestionsAndAnswers()
    
        let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
        LoadQuestion(randomNumber)
    
    
    func LoadAllQuestionsAndAnswers()
    {
        let path = NSBundle.mainBundle().pathForResource("content", ofType: "json")
        let jsonData : NSData = NSData(contentsOfFile: path!)!
        allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
        //println(allEntries)
    
    }
    
    
    func LoadQuestion(index : Int)
    {
        let entry : NSDictionary = allEntries.objectAtIndex(index) as! NSDictionary
        let question : NSString = entry.objectForKey("question") as! NSString
        let arr : NSMutableArray = entry.objectForKey("answers") as! NSMutableArray
    
        //println(question)
        //println(arr)
    
        labelQuestion.text = question as String
    
        let indices : [Int] = [0,1,2,3]
        //let newSequence = shuffle(indices)
        let newSequence = indices.shuffle()
        var i : Int = 0
        for(i = 0; i < newSequence.count; i++)
        {
            let index = newSequence[i]
            if(index == 0)
            {
                // we need to store the correct answer index
                currentCorrectAnswerIndex =  i
    
            }
    
            let answer = arr.objectAtIndex(index) as! NSString
            switch(i)
            {
            case 0:
                buttonA.setTitle(answer as String, forState: UIControlState.Normal)
                break;
    
            case 1:
                buttonB.setTitle(answer as String, forState: UIControlState.Normal)
                break;
    
            case 2:
                buttonC.setTitle(answer as String, forState: UIControlState.Normal)
                break;
    
            case 3:
                buttonD.setTitle(answer as String, forState: UIControlState.Normal)
                break;
    
            default:
                break;
            }
    
    
    
        }
        buttonNext.hidden = true
        // we will need to reset the buttons to reenable them
        ResetAnswerButtons()
    
    }
    
    
    
    @IBAction func PressedButtonNext(sender: UIButton) {
        print("button Next pressed")
        let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
        LoadQuestion(randomNumber)
    
    }
    

1 个答案:

答案 0 :(得分:3)

如果我理解你的要求:

  • 您希望在View Controller实例和应用程序启动之间保留随机生成的数字
  • 你永远不想重复任何问题

实现此目标的一种快捷方法是使用NSUserDefaults来跟踪PRNG中(伪)随机数的顺序和值。通过这种方式,您可以通过重放以前的骰子卷来实例化关于即时的可用问题数组,并按照正确的顺序从池中删除这些问题。

这也让你可以将PRNG作为一个黑盒子来处理,而不是关心播种和重播。

此外,请务必从当前池中删除任何骰子掷骰子中的所选问题。

旁注:您没有遵循命名约定 - 例如,函数将以小写字母开头。

为了您自己的良好和可读性,请遵循流行的惯例,至少在与他人共享您的代码时。更好的是,所有的时间。

修改

更详细:

  • NSUserDefaults可以轻松为您节省少量数据。如果你只是想记住一系列数字,那就是去处理。
  • 假设您的数据在如下的实例变量中是helt:

    var questions : [Question] = // load the questions - carefully, see below.
    

    您可以轻松删除PSNG的问题( p seudo- r andom n umber g enerator)选择如此:

    let randomNumber = Int(arc4random_uniform(UInt32(questions.count)))
    questions.removeAtIndex(randomNumber)
    

    因此,下一个骰子滚动(例如你的PSNG的调用)保证不会选择已经问过的问题,因为它不再是从它选择的可用问题池中。

  • 这种方法确实需要您以正确的顺序保存所有随机数,以“重播”实例化新实例之前发生的事情(例如,因为应用程序已重新打开)。这是NSUserDefaults' setObject:forKey:objectForKey:在最初加载问题和“记住”每个新骰子时发挥作用的地方。

我希望,这涵盖了您之前可能不了解的内容。