#前提・実現したいこと
C# WPFにてクイズゲームを開発しています。
以下のコードを改善したいです。
プログラムの内容としては、
【mainクラス】
- ローカルファイルからテキスト、画像、音声ファイルパスを取得する。
- txtファイルはテキストに変換、jpg,mp3ファイルはファイルパスのままstring型変数に格納
し、インスタンス化、これをListの1要素とする。 - 1,2,をフォルダ内に存在する分繰り返す。
※カテゴリーごとにA_フォルダ、B_フォルダ,C_フォルダで分かれており、
A_フォルダはA_List,B_フォルダはB_List,C_フォルダはC_Listに格納
【categoryクラス】
- ボタンが3つあり、それぞれのクリックイベントでquizクラスページに遷移。
遷移時に渡すパラメータにより、カテゴリーを識別、対応したListを操作。
【quizクラス】
- mainクラスのListを参照し、要素の順番と、要素内 配列 の順番をシャッフルする。
- 対応したコントロールのプロパティに代入。
長いコードなので、コードの内容を説明しながら、改善したい箇所を書いていきたいと思います。
まず、次のような、テキスト、ファイルパスを格納するためのクラスがあります。
C#
1 public class QuizData 2 { 3 public QuizData(string quizText, string[] choiceText, string answerText, string imgFilePath, string voiceFilePath) 4 { 5 QuestionText = quizText; 6 ChoiceText = choiceText; 7 AnswerText = answerText; 8 QuizImage = imgFilePath; 9 QuizVoice = voiceFilePath; 10 } 11 public string QuestionText = "";//テキスト(問題文) 12 public string[] ChoiceText = null;//テキストの配列(選択肢) 13 public string AnswerText = null;//テキスト(答え) 14 public string QuizImage = "";//ファイルパス(画像ファイルパス) 15 public string QuizVoice = "";//ファイルパス(音声ファイルパス) 16 } 17
下記のコードは、ローカルファイルからテキスト、ファイルパスを取得し、上記QuizDataクラスに格納、1問ずつインスタンス化してListに格納するコードです。
C#
1public partial class MainWindow : Window 2{ 3 public List<QuizData> A_QuizData = new List<QuizData>(); //1要素につき、下記 QuizData classのインスタンスを格納 4 public List<QuizData> B_QuizData = new List<QuizData>(); //同上 5 public List<QuizData> C_QuizData = new List<QuizData>(); //同上 6 7 public void CreateQuizDataList() 8 { 9 string[] A_quizFilePath = Directory.GetFiles(@"C:\Users...\category_A", "Question*.txt", SearchOption.AllDirectories); 10 string[] A_quizText = new string[A_quizFilePath.Length]; 11 for (var i = 0; i < A_quizFilePath.Length; i++) 12 { 13 A_quizText[i] = File.ReadAllText(A_quizFilePath[i]); 14 } 15 string[] A_answerFilePath = Directory.GetFiles(@"C:\Users...\category_A", "Answer*.txt", SearchOption.AllDirectories); 16 for (var i = 0; i < A_answerFilePath.Length; i++) 17 { 18 var j = 0; 19 foreach (var line in File.ReadAllLines(A_answerFilePath[i])) 20 { 21 A_answerText[i, j] = line; 22 j++; 23 } 24 } 25 string[] A_imgFilePath = Directory.GetFiles(@"C:\Users...\category_A", "Img*.jpg", SearchOption.AllDirectories); 26 27 string[] A_voiceFilePath = Directory.GetFiles(@"C:\Users...\category_A", "Question.mp3", SearchOption.AllDirectories); 28 for (var i = 0; i < A_quizFilePath.Length; i++) 29 { 30 A_QuizData.Add(new QuizData(A_quizText[i], new string[] { A_answerText[i, 0], A_answerText[i, 1], A_answerText[i, 2] }, A_answerText[i, 3], A_imgFilePath[i], A_voiceFilePath[i])); 31 } 32 }
次は、カテゴリー選択画面についてのコードです。
押下されたボタンによってカテゴリーを決定し、遷移先のページは同一のものですが、
遷移時に渡すパラメータによって、表示する内容が変化します。
C#
1 public partial class CategoryPage : Page 2 { 3 public CategoryPage() 4 { 5 InitializeComponent(); 6 } 7 8 private void ButtomAtA__Click(object sender, RoutedEventArgs e) //Quizページ遷移時、"A_"を渡す。 9 { 10 var category = "A_"; 11 var quiz = new Quiz(category); 12 NavigationService.Navigate(quiz); 13 } 14 private void ButtomAtB__Click(object sender, RoutedEventArgs e) //Quizページ遷移時、"B_"を渡す。 15 { 16 var category = "B_"; 17 var quiz = new Quiz(category); 18 NavigationService.Navigate(quiz); 19 } 20 private void ButtomAtC__Click(object sender, RoutedEventArgs e) //Quizページ遷移時、"C_"を渡す。 21 { 22 var category = "C_"; 23 var quiz = new Quiz(category); 24 NavigationService.Navigate(quiz); 25 } 26 }
次が、改善したいコードとなります。
下記のQuizクラスは、mainクラスを生成し、List要素の順番と、要素内の
string[] choiceText の順番をランダムにシャッフルし、画面に表示するものですが、
3つあるうちのListのどれをシャッフルするかを、switch文にて指定している形になっています。
C#
1public partial class Quiz : Page 2{ 3 readonly MainWindow _main = new MainWindow(); 4 private readonly string _category = ""; //switch分岐用. 5 public QuizPage(string category) 6 { 7 InitializeComponent(); 8 _category = category; //生成時、受け渡される "A" or "B" or "C". 9 ShuffleOrderQuizData(_category); 10 } 11 12 public void ShuffleOrderQuizData(string _category) 13 { 14 switch (_category) 15 { 16 case "A": 17 ShuffuleOrder_A_QuizData(); 18 break; 19 20 case "B": 21 ShuffleOrder_B_QuizData(); 22 break; 23 24 case "C": 25 ShuffleOrder_C_QuizData(); 26 break; 27 } 28 } 29 30 void ShuffuleOrderA_QuizData() 31 { 32 _main.A_QuizData = _main.A_QuizData.OrderBy(a => Guid.NewGuid()).ToList(); 33 for (var i = 0; i < _main.A_QuizData.Count; i++) 34 { 35 _main.A_QuizData[i].ChoiceText = _main.A_QuizData[i].ChoiceText.OrderBy(a => Guid.NewGuid()).ToArray(); 36 } 37 } 38 39 void ShuffleOrderB_QuizData() 40 { 41 _main.B_QuizData = _main.B_QuizData.OrderBy(a => Guid.NewGuid()).ToList(); 42 for (var i = 0; i < _main.B_QuizData.Count; i++) 43 { 44 _main.B_QuizData[i].ChoiceText = _main.B_QuizData[i].ChoiceText.OrderBy(a => Guid.NewGuid()).ToArray(); 45 } 46 } 47 48 void ShuffleOrderC_QuizData() 49 { 50 _main.C_QuizData = _main.C_QuizData.OrderBy(a => Guid.NewGuid()).ToList(); 51 for (var i = 0; i < _main.C_QuizData.Count; i++) 52 { 53 _main.C_QuizData[i].ChoiceText = _main.C_QuizData[i].ChoiceText.OrderBy(a => Guid.NewGuid()).ToArray(); 54 } 55 } 56}
質問するに至った経緯ですが、現状だと、項目が増えた場合や処理に変更があった場合などに、caseひとつひとつを修正しなければならないことと、インスタンスに引数を持たせ、遷移先のコンストラクタで分岐する、というやり方が、適切ではないように感じたためです。
開発経験が浅い為、的外れかもしれませんが、どのように改善すればよいか、ご意見を頂けないでしょうか。
宜しくお願い致します。
##追記・修正
質問の仕方が悪く、申し訳ありませんでした。
おもにお聞きしたい内容としては、「ページ遷移時、インスタンスに引数を持たせ、遷移先のコンストラクタで分岐する」というやり方について、別の方法があるならばご教示頂きたい。といったものがメインとなります。
このやり方が最適ではないように感じ、調べたところstateパターンというのが理想に近いと感じましたが、具体的な実装方法に詰まってしまい、教えて頂きたく、質問を致しました。
回答5件
あなたの回答
tips
プレビュー