0

我是 Swift 和 iOS 开发的新手,并且正在学习一些在线课程。在一门课程中,我完成了一个 iPhone 测验应用程序。所有的问题和可能的答案都是从 .json 文件中加载的,我们处理的代码会随机选择一个问题供用户回答。这很好用,只是随着时间的推移问题会重复出现,所以我一直在寻找防止这种情况发生的方法。

在几次尝试让应用程序存储随机选择并将它们从剩余问题的整体池中删除的尝试失败后,我意识到更有效的方法是最初将问题打乱,然后一一询问。

所以,我做了一些挖掘,发现了所谓的 Fisher-Yates shuffle 并且一直试图找到一种方法来实现这一点。然后我从 Swift 的 Gameplaykit 中找到了使用 GKRandomSource 来洗牌的参考,所以我一直在尝试使用它来解决问题,但似乎无法让它发挥作用。

以下是我迄今为止在代码等方面尝试过的内容。

所有问题和可能的答案选择都存储在 .json 文件中,如下所示:

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

我使用以下代码加载 .json 文件:

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)

}

下面是我用来尝试实现所有问题的随机播放的代码:

var shuffledNumber : Int! = 0

    loadAllQuestionsAndAnswers()

    if #available(iOS 9.0, *) {
        let shuffledNumber = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(allEntries as NSArray as [AnyObject])
    } else {
        // Fallback on earlier versions
    }
    LoadQuestion(shuffledNumber)

我使用一个标签来显示问题,并使用四个图像来显示可能的答案,使用以下代码:

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")
        if #available(iOS 9.0, *) {
            _ = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(allEntries as [AnyObject])
        } else {
            // Fallback on earlier versions
        }
        LoadQuestion(shuffledNumber)

现在,虽然我认为这一切都应该奏效,但事实并非如此。虽然应用程序加载正常,但它始终会向用户显示 .json 文件中的第一个问题,并且每次点击“下一步”按钮时都会重复相同的问题。

我怎样才能得到这个来洗牌所有的问题,然后一个接一个地问他们?让我知道是否需要包含更多代码。

4

1 回答 1

1

arrayByShufflingObjectsInArray给你一个洗牌的新数组。因此,您应该调用它一次,并在调用时沿着它移动索引PressedButtonNext。鉴于您已宣布

    var shuffledNumber : Int! = 0

然后有效地重新声明

    let shuffledNumber = ...

它不起作用也就不足为奇了。我怀疑你没有在 IOS 9 下运行,所以你没有收到编译错误(尽管我之前没有使用过#available)。

您应该声明以下实例变量:

    var shuffledQuestions: [AnyObject]!
    var nextQuestion = -1

然后在loadAllQuestionsAndAnswers,你应该包括

    shuffledQuestions = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(...

而在PressedButtonNext

    nextQuestion++
    LoadQuestion(nextQuestion)

然后更改您的 LoadQuestion 以entry从打乱的问题中获取:

    let entry : NSDictionary = shuffledQuestions[index] as! NSDictionary

看看这个例子here

于 2016-02-01T05:15:36.890 回答