在iOS中随机显示string,而不重复

我正在做一个测验的应用程序。 该应用程序使用.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) 

这个工作很好,但是因为它随机select了问题,所以我发现问题重复性太强(即使我有500多个问题!)。

我已经对此进行了广泛的研究,也许我已经读得太多了,因为我现在很困惑。 我已经阅读了关于“播种”的内容,关于保存问题索引,并尝试使用NSUserDefault。

总之,如何修改我的代码来实现下列其中一个结果:

  1. 根本不要重复任何问题,而是在所有问题都被提出一次时停止提问;
  2. 与上面的1类似,但是具有由用户设置的问题的数量而不是询问数据库中的所有问题;
  3. 在所有问题都被问到之前,不要重复任何问题; 要么,
  4. 不要重复以前已经正确回答的任何问题,但可能会重复错误回答的问题。

以下是我认为是代码的相关位:

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

如果我正确理解你的要求:

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

实现这个目的的一个快速方法是使用NSUserDefaults来跟踪PRNG中(伪)随机数的顺序和值。 通过这种方式,您可以通过重播以前的掷骰子实例化即时可用问题arrays,并以正确的顺序从池中移除这些问题。

这也可以让你把PRNG当成一个黑盒子,而不是关心播种和重播。

此外,请确保从任何骰子滚动中删除当前池中的任何选定问题。

注意 :你不是遵循命名约定 – 例如,函数将以小写字母开头。

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

编辑

更详细地说:

  • NSUserDefaults可以以简单的方式为您保存less量的数据。 如果你只是想记住一个数字的数组,那就去放置吧。
  • 假设你的数据是在一个实例variableshelt,如下所示:

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

    你可以很容易地删除你的PSNG问题(如下所示):

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

    因此,下一个掷骰子(例如调用你的PSNG)不会select已经问过的问题,因为它已经不在其select的可用问题池中。

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

我希望,这涵盖了你以前可能不了解的东西。