

プログラミングを始めたばかりの入門者です。  
Xcodeで4択のクイズアプリを作成しています。  
CSVデータに記述されている問題をシャッフルして出題するにはどのようなコードを書けばいいのでしょうか。  
ご教授お願いします。  
もしくはヒントとなるサイトだけでも教えていただければ幸いです。

### 仕様

このアプリは、クイズ問題と4択の選択肢が出題され、  
正解の場合は正解音と共に次の問題へ移り、  
不正解の場合は不正解音と共に正解が表示された後に、次の問題に移ります。  
今のコードではCSVデータを順に読み込むようになっているため、シャッフルはされません。

CSVデータには","で分割され、改行ごとに1行分のデータになっていて、

> クイズ問題,選択肢1,選択肢2,選択肢3,選択肢4,正解の選択肢番号

の順に記載されています。

### ソースコード

該当箇所のコードは以下です。

[code]

    import Foundation
    
    class QuestionData {
    
        var question: String
    
        var answer1: String
        var answer2: String
        var answer3: String
        var answer4: String
        var seikai: String
        var correctAnswerNumber: Int
    
        var userChoiceAnswerNumber: Int?
    
        var questionNo: Int = 0
    
        init(questionSourceDataArray: [String]) {
            question = questionSourceDataArray[0]
            answer1 = questionSourceDataArray[1]
            answer2 = questionSourceDataArray[2]
            answer3 = questionSourceDataArray[3]
            answer4 = questionSourceDataArray[4]
    
            correctAnswerNumber = Int(questionSourceDataArray[5])!
            seikai = questionSourceDataArray[correctAnswerNumber]
        }
    
        func isCorrect() -> Bool {
            if correctAnswerNumber == userChoiceAnswerNumber {
                return true
            }
            return false
        }
    }
    
    
    class QuestionDataManager {
    
        static let sharedInstance = QuestionDataManager()
    
        var questionDataArray = [QuestionData] ()
    
        var nowQuestionIndex: Int = 0
    
        private init() {
        }
    
        func loadQuestion() {
            questionDataArray.removeAll()
    
            nowQuestionIndex = 0
    
            guard let csvFilePath = Bundle.main.path(forResource: "question", ofType: "csv") else{
    
               print("csvファイルが存在しません")
               return
            }
    
            do {
                let csvStringData = try String(contentsOfFile: csvFilePath,
                    encoding: String.Encoding.utf8)
    
                csvStringData.enumerateLines(invoking: { (line, stop) in
                    let questionSourceDataArray = line.components(separatedBy: ",")
    
                    let questionData = QuestionData(questionSourceDataArray: questionSourceDataArray)
    
                    self.questionDataArray.append(questionData)
    
                    questionData.questionNo = self.questionDataArray.count
    
    
                })
            } catch let error {
                print("csvファイル読み込みエラーが発生しました:\(error)")
                return
            }
        }
    
        func nextQuestion() -> QuestionData? {
            if nowQuestionIndex < questionDataArray.count {
                let nextQuestion = questionDataArray[nowQuestionIndex]
                nowQuestionIndex += 1
                return nextQuestion
            }
            return nil
        }
    
    }
    
[/code]

google検索でこのシャッフルのやり方について書かれているブログがあったので、  
extensionファイルなるものを作って見よう見まねで記述してみたのですが、  
やはり入門者。  
コードそのものの意味を全く理解できていないため、うまくいきませんでした。  
参考にさせていただいたサイトは以下です。  
<https://qiita.com/fumiyasac@github/items/18ae522885b5aa507ca3>


CC BY-SA 3.0
2017-10-11T20:49:29.993
38614
2017-12-13T22:59:47.570
2017-12-13T22:59:47.570
19110
25610
question
swift xcode
swift クイズアプリの問題をシャッフル出題させるには


リンク先の記事はXcode7/Swift2用のものですし、Swiftアプリではあまり使いたくない`NSMutableArray`を使っているので、あてにせずに独自の処理とされてはいかがでしょうか?

配列をあらかじめシャッフルしておくのではなく、出題のたびに次の問題をランダムに選ぶという発想です。(「出題完了後の問題は`questionDataArray`に残しておく必要はない」と仮定しています。必要であればコピーを保存したり、出題後の問題を保存しておく配列を別に用意したりしてください。)

[code]

    func nextQuestion() -> QuestionData? {
        if questionDataArray.isEmpty {
            return nil
        }
        let nextQuestionIndex = Int(arc4random_uniform(UInt32(questionDataArray.count)))
        let nextQuestion = questionDataArray[nowQuestionIndex]
        questionDataArray.remove(at: nextQuestionIndex)
        return nextQuestion
    }
    
[/code]

ちなみに`remove(at:)`メソッドは削除された要素を戻り値として返すので、最後の3行は1行にまとめることもできます。

[code]

    func nextQuestion() -> QuestionData? {
        if questionDataArray.isEmpty {
            return nil
        }
        let nextQuestionIndex = Int(arc4random_uniform(UInt32(questionDataArray.count)))
        return questionDataArray.remove(at: nextQuestionIndex)
    }
    
[/code]


CC BY-SA 3.0
2017-10-13T00:26:17.197
38651
2017-10-13T00:26:17.197
13972
38614
answer