質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1119閲覧

クイズの選択肢をランダムに出力したいです。

yuki0402

総合スコア4

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2021/06/04 08:55

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
swiftでクイズアプリを作っています。
CSVファイルに書いてあるクイズの問題の選択肢を配列を使って、ランダムに表示したいのですが、そもそも要素番号を複数加える事ができませんでした。

発生している問題・エラーメッセージ

余分なデータが含まれていると表示されてしまいます。

エラーメッセージ Extra arguments at positions #2, #3, #4 in call

該当のソースコード

swift

1 var csvArray: [String] = [] 2 var quizArray: [String] = [] 3 quizArray = csvArray[quizCount].components(separatedBy: ",") 4 quizNumberLabel.text = "第(quizCount + 1)問" 5 quizTextView.text = quizArray[0] 6 answerButton1.setTitle(quizArray[2,3,4,5]/*エラー部分*/, for: .normal) 7 answerButton2.setTitle(quizArray[3], for: .normal) 8 answerButton3.setTitle(quizArray[4], for: .normal) 9 answerButton4.setTitle(quizArray[5], for: .normal) 10

試したこと

特にございません、

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。
answerButton1のようにボタンひとつにつき、ひとつの配列の要素を取得する仕様となっております。
配列は0が問題文、1が正解番号、2,3,4,5は選択肢となります。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TomohiroKumagai

2021/06/05 03:31

`answerButton1.setTitle(quizArray[2,3,4,5]/*エラー部分*/, for: .normal)` 上のコードの意図を汲み取れなかったのですけれど、何をしようと思ってこのコードを書かれたのですか?
yuki0402

2021/06/05 04:00

説明が足りず申し訳ありません。 array.randomElement()のように、配列の中の複数の要素からランダムに一つのデータを取得したいと考えて折りました。
TomohiroKumagai

2021/06/05 04:06

なるほど、わかりました。そうすると「4つの選択肢の中から、ランダムで1つ選んだ値を answerButton1 のタイトルに設定する」ということですね。 他の answerButton2, answerButton3, answerButton4 については「ランダムではなく、それぞれ二番目の選択肢、三番目の選択肢、四番目の選択肢をタイトルとして設定する」コードに見えて、answerButton1 の様子と違うように見えるのですけど、ここは将来的にはもしかして「answerButton1 〜 answerButton4 のそれぞれに、用意した4つの選択肢それぞれをランダムな順番で入れる」のを考えていたりしますか?
yuki0402

2021/06/05 07:31

仰る通りで、ボタンそれぞれに4つの選択肢を割り当てようと考えております。 可能であれば、4つ以上の選択肢の中から4つのボタンそれぞれにランダムで割り当て、尚且正解の選択肢が含まれるように仕掛けたいと考えております。
yuki0402

2021/06/05 07:35 編集

追記:CSVファイルについてです。配列の要素は{ぼうしの中に入っている動物はなに?,4,かめ,ウサギ,キリン,うし}です。順番に[0]が問題文、[1]が正解番号、[2,3,4,5]は選択肢となります。
guest

回答1

0

ベストアンサー

丁寧な補足情報をありがとうございました。

4つのボタンに4つの選択肢をランダムに表示させることが目的とのことなので、それであればもしかすると今回の場合であれば「問題と正解番号、4つの選択肢が含まれた quizArray のインデックス番号 2 から 5 までをランダムに並べて、そのインデックスを使って選択肢を配列から取り出すようにしてみる方法もあるかもしれません。

swift

1var csvArray: [String] = [] 2var quizArray: [String] = [] 3var quizOptionIndexes: [Int] = [] 4 5quizArray = csvArray[quizCount].components(separatedBy: ",") 6quizOptionIndexes = (2 ... 5).shuffled() 7 8quizNumberLabel.text = "第(quizCount + 1)問" 9quizTextView.text = quizArray[0] 10answerButton1.setTitle(quizArray[quizOptionIndexes[0]], for: .normal) 11answerButton2.setTitle(quizArray[quizOptionIndexes[1]], for: .normal) 12answerButton3.setTitle(quizArray[quizOptionIndexes[2]], for: .normal) 13answerButton4.setTitle(quizArray[quizOptionIndexes[3]], for: .normal)

上記の例では、インデックス番号 2 から 5 まで (2 ... 5)shuffled でランダムに並べ直した配列 quizOptionIndexes を用意してみました。こうすることで、例えば [2, 4, 5, 3] みたいな、選択肢の候補が格納されているインデックス番号が4つ、無作為な順番で用意できます。

あとはこれを使って quizArray[quizOptionIndexes[0]] みたいにして、quizArray の中から quizOptionIndexes` で用意した(ランダム順に並んだ)インデックス番号を使って選択肢を取り出しています。

いろいろな表現の仕方がありそう

上で紹介した方法が最適とも限りませんし、他にもいろいろな表現方法、解決方法がありそうです。

たとえば quizArray[2 ... 5].shuffled() みたいにして、quizArray から選択肢のところだけを部分配列として取り出して、それをランダムに並べなおす方法も考えられそうです。この方法の場合、あらかじめ用意されているデータの正解情報が「正解番号」であることを踏まえると、選択肢だけを取り出して並び替えてしまうと元の順番情報が失われてしまうので、正解判定で少し面倒になる可能性もありそうです。

それを意識して、上記のような「選択肢のインデックスをランダムに並べる」方法を取ってみました。この方法なら押されたボタンの番号を元に quizOptionIndexes の該当する値を取り出せばそこから「正解番号」を簡単に算出できるので、選択肢だけを並び替える方法よりはプログラムを組みやすくなりそうな気がします。

選択肢の候補を5つ以上にする場合

補足情報にあった「4つ以上の選択肢の中から4つのボタンそれぞれにランダムで割り当て、尚且正解の選択肢が含まれるように仕掛けたい」と聞いて、もう少しアイデアが膨らみました。

たとえば、今は「問題、正解番号、選択肢1、選択肢2、選択肢3、選択肢4」というデータの持ち方になっていますけど、これを「問題、正解の選択肢、間違いの選択肢1、間違いの選択肢2、間違いの選択肢3、間違いの選択肢4、⋯」みたいに持たせてみても面白いかもしれません。

そうすると「正解の選択肢」が最初にあるので、それ (quizArray[1]) はそのまま、それ以降の選択肢 (quizArray[2...]) から無作為 (shuffled()) に並べたうちの先頭3つを抽出 (prefix(3))して(表現がややこしいですが、簡単に言い換えると『無作為に3つ抽出』です)、それを正解と連結すると、正解を必ず含む4つの選択候補が出来上がります。それをさらにランダムに並べ替えれば、正解がどこにあるかわからない4つの選択候補が出来上がります。

swift

1csvArray = ["問題,正解,不正解1,不正解2,不正解3,不正解4"] 2quizArray = csvArray[quizCount].components(separatedBy: ",") 3 4let quizAnswer = quizArray[1] 5let quizWrongOptions = quizArray[2...].shuffled().prefix(3) 6let quizOptions = ([quizAnswer] + quizWrongOptions).shuffled() 7 8quizNumberLabel.text = "第(quizCount + 1)問" 9quizTextView.text = quizArray[0] 10answerButton1.setTitle(quizOptions[0], for: .normal) 11answerButton2.setTitle(quizOptions[1], for: .normal) 12answerButton3.setTitle(quizOptions[2], for: .normal) 13answerButton4.setTitle(quizOptions[3], for: .normal)

あとは、押したボタンに設定されている選択肢と、あらかじめデータに用意しておいた最初の選択肢(正解の選択肢)とが文字列的に一致しているか判定することで「正解番号」を持たせなくても、正解判定ができそうです。

投稿2021/06/05 08:03

編集2021/06/05 08:35
TomohiroKumagai

総合スコア441

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yuki0402

2021/06/05 08:27

大変ご丁寧な回答ありがとうございます。 インデックス番号 1を正解番号→正解の選択肢でインデックス番号 2 から 5を選択肢→間違いの選択肢は全く考えつかなかったアイデアです。とても参考になりました。 よりプログラマーらしい考え方ができるよう視野を広げて参ります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問