前回作成したクイズアプリにクイズを追加します。
メニューを追加しています。
これがクイズを追加するためのダイアログです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
public partial class Form2 : Form { public Form2() { InitializeComponent(); button1.Click += Button1_Click; button1.DialogResult = DialogResult.OK; } private void Button1_Click(object sender, EventArgs e) { Question = textBoxQuestion.Text; Answer = textBoxAnswer.Text; List<string> vs = new List<string>(); vs.Add(textBoxChoice1.Text); vs.Add(textBoxChoice2.Text); vs.Add(textBoxChoice3.Text); vs.Add(textBoxChoice4.Text); Choices = vs.ToArray(); } public string Question = ""; public string[] Choices = null; public string Answer = ""; private void Form2_Load(object sender, EventArgs e) { } } |
メニューがクリックされたらダイアログを表示してクイズを追加します。選択肢のなかに正解が存在しない場合はエラーとなり登録できません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public partial class Form1 : Form { private void MenuItemAddQuiz_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); if(form2.ShowDialog() == DialogResult.OK) { if(form2.Choices.Any(x => x == form2.Answer)) Quizes.Add(new Quiz(form2.Question, form2.Choices, form2.Answer)); else MessageBox.Show("「正解」が正しく設定されていません!", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); } form2.Dispose(); } } |
シリアル化をするためにQuizクラスに引数なしのコンストラクタを追加します。
1 2 3 4 5 6 7 |
public class Quiz { // 空のコンストラクタを追加する public Quiz() { } } |
メニューがクリックされたら保存と読み出しの処理をおこないます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
using System.Xml.Serialization; using System.IO; public partial class Form1 : Form { private void MenuItemSaveFile_Click(object sender, EventArgs e) { XmlSerializer xml = new XmlSerializer(typeof(List<Quiz>)); SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "Quizファイル(*.quiz)|*.quiz"; dialog.DefaultExt = "quiz"; if(dialog.ShowDialog() == DialogResult.OK) { StreamWriter sw = new StreamWriter(dialog.FileName); xml.Serialize(sw, Quizes); sw.Close(); } dialog.Dispose(); } private void MenuItemOpenFile_Click(object sender, EventArgs e) { XmlSerializer xml = new XmlSerializer(typeof(List<Quiz>)); OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Quizファイル(*.quiz)|*.quiz"; dialog.DefaultExt = "quiz"; if(dialog.ShowDialog() == DialogResult.OK) { StreamReader sr = new StreamReader(dialog.FileName); Quizes = (List<Quiz>)xml.Deserialize(sr); sr.Close(); } dialog.Dispose(); } } |
あと今回は、クイズをHTMLでも出力できるようにします。HTMLとJavaScriptはここを参考にしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
<!doctype html> <html class="no-js" lang=""> <head> <meta charset="utf-8"> <title></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> <meta name="theme-color" content="#fafafa"> </head> <body> <div class="container"> <div class="jumbotron mt-5"> <div class="d-flex justify-content-center"> <div id="js-question" class="alert alert-primary" role="alert"> A simple primary alert?check it out! </div> </div> <div id="js-items" class="d-flex justify-content-center"> <div class="m-2"> <button type="button" id="js-btn-1" class="btn btn-primary choice">Primary1</button> </div> <div class="m-2"> <button type="button" id="js-btn-2" class="btn btn-primary choice">Primary2</button> </div> <div class="m-2"> <button type="button" id="js-btn-3" class="btn btn-primary choice">Primary3</button> </div> <div class="m-2"> <button type="button" id="js-btn-4" class="btn btn-primary choice">Primary4</button> </div> </div> </div> </div> <script> const quiz = [ { question: 'ゲーム史上、最も売れたゲーム機はどれ?', answers: ['スーパーファミコン', 'PlayStation 2', 'ニンテンドーDS', 'Xbox 360'], correct: 'ニンテンドーDS' }, { question: '糸井重里が企画に関わった、任天堂の看板ゲームといえば?', answers: ['MOTHER2', 'スーパーマリオブラザーズ3', 'スーパードンキーコング', '星のカービィ'], correct: 'MOTHER2' } ]; const quizLen = quiz.length; let quizIndex = 0; const $choices = document.getElementsByClassName("choice"); const $question = document.getElementById("js-question"); const init = () => { let btnIndex = 0; while (btnIndex < 4) { $choices[btnIndex].addEventListener("click", (e) => { juge(e.target.textContent); }); btnIndex++; } } const showQuiz = () => { $question.textContent = quiz[quizIndex].question; let btnIndex = 0; while (btnIndex < 4) { $choices[btnIndex].style.visibility = "hidden"; if(quiz[quizIndex].answers[btnIndex] != "") { $choices[btnIndex].style.visibility = "visible"; $choices[btnIndex].textContent = quiz[quizIndex].answers[btnIndex]; } btnIndex++; } }; let score = 0; const juge = (arg1) => { if (quiz[quizIndex].correct == arg1) { alert("正解!"); score++; } else alert("残念!"); quizIndex++; if (quizIndex < quizLen) { showQuiz(); } else { $question.textContent = "終了! " + quizLen + " 問中 " + score + " 問正解です!"; let btnIndex = 0; while (btnIndex < 4) { $choices[btnIndex].style.visibility = "hidden"; btnIndex++; } } } init(); showQuiz(); </script> </body> </html> |
const quiz = [ ]の部分を入れ替えれば自作クイズアプリの完成です。
まず出力すべきHTMLファイルに書き込む文字列を取得します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
public partial class Form1 : Form { string GetHtmlText() { StringBuilder sb = new StringBuilder(); sb.Append("<!doctype html><html class=\"no-js\" lang=\"\">\n"); sb.Append("<head>"); sb.Append("<meta charset=\"utf-8\"><title></title><meta name=\"description\" content=\"\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); sb.Append("<link rel=\"stylesheet\" href=\"https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css\"><meta name=\"theme-color\" content=\"#fafafa\">"); sb.Append("</head>"); sb.Append("<body>"); sb.Append("<div class=\"container\">"); sb.Append("<div class=\"jumbotron mt-5\"><div class=\"d-flex justify-content-center\"><div id=\"js-question\" class=\"alert alert-primary\" role=\"alert\"></div></div>\n"); sb.Append("<div id=\"js-items\" class=\"d-flex justify-content-center\">\n"); sb.Append("<div class=\"m-2\"><button type=\"button\" id=\"js-btn-1\" class=\"btn btn-primary choice\">Primary1</button></div>\n"); sb.Append("<div class=\"m-2\"><button type=\"button\" id=\"js-btn-2\" class=\"btn btn-primary choice\">Primary2</button></div>\n"); sb.Append("<div class=\"m-2\"><button type=\"button\" id=\"js-btn-3\" class=\"btn btn-primary choice\">Primary3</button></div>\n"); sb.Append("<div class=\"m-2\"><button type=\"button\" id=\"js-btn-4\" class=\"btn btn-primary choice\">Primary4</button></div>\n"); sb.Append("</div></div></div>\n"); sb.Append("<script>\n"); sb.Append("const quiz = [\n"); foreach(Quiz quiz in Quizes) { sb.Append("{"); sb.Append(String.Format("question: \"{0}\",", quiz.Question)); sb.Append(String.Format("correct: \"{0}\",", quiz.Answer)); sb.Append("answers:["); foreach(string str in quiz.Choices) sb.Append(String.Format("\"{0}\",", str)); sb.Append("],"); sb.Append("},\n"); } sb.Append("];\n"); sb.Append("const quizLen = quiz.length; let quizIndex = 0; const $choices = document.getElementsByClassName(\"choice\");"); sb.Append("const $question = document.getElementById(\"js-question\"); "); sb.Append("const init = () => { let btnIndex = 0; while (btnIndex < 4) {"); sb.Append("$choices[btnIndex].addEventListener(\"click\", (e) => { juge(e.target.textContent); }); btnIndex++; }};"); sb.Append("const showQuiz = () => { $question.textContent = quiz[quizIndex].question; let btnIndex = 0; while (btnIndex < 4) {"); sb.Append("$choices[btnIndex].style.visibility = \"hidden\";"); sb.Append("if(quiz[quizIndex].answers[btnIndex] != \"\") {"); sb.Append("$choices[btnIndex].style.visibility = \"visible\"; $choices[btnIndex].textContent = quiz[quizIndex].answers[btnIndex];} btnIndex++; }};"); sb.Append("let score = 0;\n"); sb.Append("const juge = (arg1) => { if (quiz[quizIndex].correct == arg1) { alert(\"正解!\"); score++; } else { alert(\"残念!\"); }\nquizIndex++;\n"); sb.Append("if (quizIndex < quizLen) { showQuiz(); } else { $question.textContent = \"終了! \" + quizLen + \" 問中 \" + score + \" 問正解です!\";\n"); sb.Append("let btnIndex = 0; while (btnIndex < 4) { $choices[btnIndex].style.visibility = \"hidden\"; btnIndex++; }}};init(); showQuiz();\n"); sb.Append("</script></body></html>\n"); return sb.ToString(); } } |
あとはこれをHTMLファイルとして保存すればできあがりです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class Form1 : Form { private void MenuItemOutputHTML_Click(object sender, EventArgs e) { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "htmlファイル(*.html)|*.html"; dialog.DefaultExt = "html"; if(dialog.ShowDialog() == DialogResult.OK) { StreamWriter sw = new StreamWriter(dialog.FileName); sw.Write(GetHtmlText()); sw.Close(); } dialog.Dispose(); } } |