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

2023-12-03

我正在制作一个测验应用程序。该应用程序使用 .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. 不重复以前正确回答过的问题,但回答错误的问题可以重复。

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

    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)

}

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

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

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

这还允许您将 PRNG 作为黑匣子处理,而不关心播种和重放。

另外,请确保从当前池中删除所有已选择的问题以进行任何掷骰。

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

为了您自己的利益和可读性,请遵循流行的约定,至少在与他人共享您的代码时如此。更好的是,一直如此。

Edit:

更详细地说:

  • NSUserDefaults可以轻松地为您保存少量数据。如果您“只想记住一组数字”,那么这里就是您的最佳选择。
  • 假设您的数据位于实例变量中,如下所示:

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

    您可以轻松删除您的 PSNG 问题(pseudo-random number generator) 像这样选择:

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

    因此,下一次掷骰子(例如调用 PSNG)保证不会选择已经提出的问题,因为它不再位于它选择的可用问题池中。

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS中随机显示字符串而不重复它们 的相关文章

随机推荐