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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

306閲覧

Unity(2D)問題を重複なく出題する方法がわかりません。

Meron_

総合スコア2

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2024/03/26 13:08

実現したいこと

Unityでクイズゲームを作成しています。
現在できていること
CSVファイルを読み込み問題をUIに反映させ、正誤判定、スクリプト間のデータを受け渡してスコアを表示させるというところまででき、クイズゲームとしては完成に近いのですが、問題が重複して出題されてしまい困っております。

発生している問題・分からないこと

QuizMgrというスクリプトを使ってCSVの問題を取得してUIに表示させています。下記補足ソースコードを追加すると問題と答えがバラバラにUIに反映されるようになってしまいました。

該当のソースコード

QuizMgr

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5using System.IO; 6using System.Linq; 7 8public class QuizMgr : MonoBehaviour 9{ 10 public string dataName; 11 public string title; 12 public TextAsset csvFile; 13 public List<string[]> csvDatas = new List<string[]>(); 14 public int height = 0; 15 public int i, j = 0; 16 public int k = 0; 17 internal Text ansLabel; 18 public string AnswerText; 19 const int size = 5; 20 private static string correctAnswer; 21 22 void Awake() 23 { 24 25 title = "theme_"; 26 csvFile = Resources.Load("CSV/CSVDatas") as TextAsset; 27 StringReader reader = new StringReader(csvFile.text); 28 29 while (reader.Peek() > -1) 30 { 31 string line = reader.ReadLine(); 32 csvDatas.Add(line.Split(',')); 33 Debug.Log("reading:" + height); 34 height++; 35 } 36 37 for (i = 0; i < height; i++) 38 { 39 for (j = 0; j < size; j++) 40 { 41 Debug.Log("csvDatas[" + i + "][" + j + "]:" + csvDatas[i][j]); 42 } 43 } 44 45 QuestionLabelSet(); 46 AnswerLabelSet(); 47 AnswerSet(); 48 } 49 50 51 public void QuestionLabelSet() 52 { 53 csvDatas[k] = csvDatas[Random.Range(0, 10)]; 54 //特定の名前のオブジェクトを検索してアクセス 55 Text qLabel = GameObject.Find("Quiz/QLabel").GetComponentInChildren<Text>(); 56 //データをセットすることで、既存情報を上書きできる 57 qLabel.text = csvDatas[k][0]; 58 } 59 60 public void AnswerLabelSet() 61 { 62 //問題文に対応した答えをそれぞれのuGUIボタンにセット 63 string[] array = new string[] { csvDatas[k][1], csvDatas[k][2], csvDatas[k][3], csvDatas[k][4] }; 64 65 //問題文をシャッフル 66 array = array.OrderBy(x => System.Guid.NewGuid()).ToArray(); 67 68 //ボタンが4つあるのでそれぞれ代入 69 for (int i = 1; i <= 4; i++) 70 { 71 Text ansLabel = GameObject.Find("Quiz/AnsButton" + i).GetComponentInChildren<Text>(); 72 ansLabel.text = array[i - 1]; 73 } 74 } 75 76 public void AnswerSet() 77 { 78 //答えとなるcsvデータを変数として型に代入する 79 AnswerText = csvDatas[k][1]; 80 Debug.Log(AnswerText); 81 82 correctAnswer = csvDatas[k][1]; 83 } 84 85 public static string GetCorrectAnswer() 86 { 87 return correctAnswer; 88 } 89 90 void Update() { } 91}
//追加したもの一覧 public List<string[]> shuffledCsvDatas = new List<string[]>(); shuffledCsvDatas = csvDatas.OrderBy(x => Random.value).ToList(); public void QuestionLabelSet() { // シャッフルしたデータを順番に表示 Text qLabel = GameObject.Find("Quiz/QLabel").GetComponentInChildren<Text>(); qLabel.text = shuffledCsvDatas[k][0]; } public void AnswerSet() { //答えとなるcsvデータを変数として型に代入する AnswerText = shuffledCsvDatas[k][1]; correctAnswer = shuffledCsvDatas[k][1]; }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

問題とクイズのそれぞれがシャッフルされ本来の問題とその答えがバラバラになってしまいました。

補足

特になし

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

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

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

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

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

Refrain

2024/03/26 13:11

問題視しているのは"重複すること"でしょうか。 それとも"問題と回答がバラバラになること"でしょうか。
Meron_

2024/03/26 13:28

重複することです。
juner

2024/03/27 01:37 編集

csvDatas[k] = csvDatas[Random.Range(0, 10)]; の様に直接元のデータ上書きしてしまうと既にあったデータが別のデータに上書きされ、滅茶苦茶になると思うのですが意図していますでしょうか? せめてやるなら入れ替えであるべきではないでしょうか?
fana

2024/03/27 01:47

「これがコードです.できません」だけじゃなくて,まず「どういう方法でやろうとしているのか」という実装しようとしているアルゴリズムの話をするべきなんじゃないかなぁ. 例えば,コードだけ見せられると, [k] が頻繁に出てくる様子だけどこの k というのは一体何のための存在なのか? とか疑問に思う. 例えば「複数の問題がある中から,k番目の問題を出題する」といったような意図なのであれば,やるべきことは「 k の値を何かしらの方法で(重複しないように)決定していくこと」になると思うのだけど,提示コードを見る限り k の値は常に 0 であるように見えるから,そういう物ではないのですよね?きっと.
Meron_

2024/03/27 02:41

確かにその通りです。ご指摘ありがとうございます。 Kの値はcsvのリスト内のk番目の要素を表していて、[k][1]だったらk行目の2番目の要素です。 作ろうとしているのは、CSVのデータを一次元配列に入れてそれをシャッフルし上から順番に読み込んで重複しないようにするというものです。
fana

2024/03/27 03:02

> 作ろうとしているのは、CSVのデータを一次元配列に入れてそれをシャッフルし上から順番に読み込んで重複しないようにするというものです。 であれば, * データをシャッフルすること * k の値を出題する毎に更新していくこと が必要となるであろうと想像しますが,前述のように後者に相当する部分がコード内に見当たりません. その点はどうなのでしょう? 本当に k の値の更新が必要なのであれば,「それ(必要な処理の実装)が無いコードでは所望の動作をしないのは当たり前」という話にしかならない気がするのですが.
fana

2024/03/27 03:08

とりあえず 「データをCSVファイルから読込んだら,その場で即シャッフルする」だけをまずは実装し,想定通りにシャッフルできることが確認できたならば(その時点で「問題とその答えがバラバラ」という問題は無いハズであるから), 次に「それを順番に使う」という部分を実装する, というステップを経るのが良さそうかな,と思います. また,そういう原理確認をする場合には Unity みたいな要素は 不要/余計 であろうと思うので,適当なコンソールアプリとかで試して→できたら Unityの本番コードに移植する みたいな手順を経るのが良いのではないか,とか思います.
Meron_

2024/03/27 03:15

該当のソースコードにある、QUizMgrだけなら想定通りにシャッフルできているのですが補足コードを追加すると問題と回答がバラバラになるということです。 ですので現時点では想定通りにシャッフルするというのはできています。 QuizMgrに以下のコードを追加したところ問題と解答がバラバラになってしまったということです。 public List<string[]> shuffledCsvDatas = new List<string[]>(); shuffledCsvDatas = csvDatas.OrderBy(x => Random.value).ToList(); public void QuestionLabelSet() { // シャッフルしたデータを順番に表示 Text qLabel = GameObject.Find("Quiz/QLabel").GetComponentInChildren<Text>(); qLabel.text = shuffledCsvDatas[k][0]; } public void AnswerSet() { //答えとなるcsvデータを変数として型に代入する AnswerText = shuffledCsvDatas[k][1]; correctAnswer = shuffledCsvDatas[k][1]; }
Meron_

2024/03/27 03:16

コメント、回答をご丁寧にありがとうございました。ベストアンサーにさせていただきます。
fana

2024/03/27 03:20 編集

いや,あなたが考えている方法と私の回答の内容は若干違いますよね? 「それはそれ,これはこれ」としてご自身の方法で行くような回答を待っても(あるいはご自身で検討を続けても)良くないですか? ※ベストアンサーを付けてしまうと,以降,回答等が付きにくくなる気がします. 本当に「もういい」となったのでなければ特に急ぐ必要は無いと思いますよ.
Meron_

2024/03/27 03:20

確かにそうですね。回答を待っている間、もっといろいろ試してみようと思います。ありがとうございます。
guest

回答1

0

ベストアンサー

どういう方法で やりたい/やろうとしている のか? というのが読み取れませんが……

例えば私なら,「ファイルから読込んだデータ」というのを処理の進行に応じてごちゃごちゃといじくり回したくはない(読込んだままの状態で保持したい)気がするので,↓のような方法を考えるかもしれません.

これが (何らかの意味で)良い方法か否か? みたいな話は何かしらあり得るでしょうけども,
まず最初はこんな感じの 最もシンプルな部類の/限りなく混乱する要素のない 方法でトライしてみればどうでしょうか.

C#

1//何かこういう(CSVファイルから読込んだ)データがあって…… 2List< string[] > csvDatas = new List<string[]> 3{ 4 new string[]{ "A0", "A1", "A2", "A3" }, 5 new string[]{ "B0", "B1", "B2", "B3" }, 6 new string[]{ "C0", "C1", "C2", "C3" }, 7 new string[]{ "D0", "D1", "D2", "D3" }, 8 new string[]{ "E0", "E1", "E2", "E3" } 9}; 10 11//例えば,データの個数 (この例だと5) 回だけ出題を行うことを考えるとき, 12//「各回にどのデータを用いるのか?」というのを乱数で決めておくのが簡単ではなかろうか. 13int[] RandomOrderedDataIndexes; 14{ 15 var Rnd = new Random(); //※ この例で使っているのは .NET Framework の Random 16 RandomOrderedDataIndexes = Enumerable.Range( 0, csvDatas.Count ).OrderBy( x => Rnd.Next() ).ToArray(); 17} 18 19//---------- ↑の RandomOrderedDataIndexes[] の使い方の例: 20 21//少なくともデータの個数回だけ出題を行う範囲においては,「重複」はしないよね. 22for( int iTimes=0; iTimes<csvDatas.Count; ++iTimes ) 23{ 24 int DataIndexForThisTime = RandomOrderedDataIndexes[ iTimes ]; 25 var DataForThisTime = csvDatas[ DataIndexForThisTime ]; 26 ... 27}

CSVのデータを一次元配列に入れてそれをシャッフルし上から順番に読み込んで重複しないようにする

データ自体をシャッフルして良いのであれば,より単純になる:

C#

1//何かこういう(CSVファイルから読込んだ)データがあって…… 2List< string[] > csvDatas = new List<string[]> 3{ 4 new string[]{ "A0", "A1", "A2", "A3" }, 5 new string[]{ "B0", "B1", "B2", "B3" }, 6 new string[]{ "C0", "C1", "C2", "C3" }, 7 new string[]{ "D0", "D1", "D2", "D3" }, 8 new string[]{ "E0", "E1", "E2", "E3" } 9}; 10 11{//↑の csvDatas 自体をシャッフルしてよいならば,CSV読込直後にシャッフルしておけよい. 12 var Rnd = new Random(); //※ この例で使っているのは .NET Framework の Random 13 csvDatas = csvDatas.OrderBy( x => Rnd.Next() ).ToList(); 14} 15 16//--- 17 18//あとはシャッフル済みの csvDatas を先頭から順に使うだけだ 19for( int iTimes=0; iTimes<csvDatas.Count; ++iTimes ) 20{ 21 var DataForThisTime = csvDatas[ iTimes ]; 22 23 //※↓コレは確認用に DataForThisTime の中身をコンソールに出力してみているだけ 24 Console.WriteLine( (iTimes+1).ToString() + "回目:" ); 25 foreach( var str in DataForThisTime )Console.Write( str + ", " ); 26 Console.WriteLine(); 27}

このコードの出力結果例:

1回目: C0, C1, C2, C3, 2回目: B0, B1, B2, B3, 3回目: A0, A1, A2, A3, 4回目: E0, E1, E2, E3, 5回目: D0, D1, D2, D3,

質問文のコードでは,この例とは異なり, shuffledCsvDatas という別の変数にシャッフルした結果を受けているが,

問題とその答えがバラバラ

になるのは,コードの各所でこの shuffledCsvDatas を用いている個所と,元の(順序がシャッフルされていない)csvDatas を用いている個所とがあって整合性が取れていない,みたいな話なのではなかろうか? と推測する.

投稿2024/03/27 02:39

編集2024/03/27 04:21
fana

総合スコア11658

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

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

Meron_

2024/04/14 02:32

データ自体をシャッフルする方法でコードを書かせて頂きました。ご丁寧にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問