完成手前で欠陥に気がつきました・・・
プログラミング言語(JavaScript)を勉強して1ヶ月ほどの初心者です。噛み砕いてご説明いただけると助かりますm(_ _)m
この度、アキネーターのように、質問に答えることであらかじめ用意された正解が非表示⇨絞られていくプログラムを設計しております。
皆様のお助けをいただき、質問の回答内容に応じて「不正解となる答え」と「不要な設問」が非表示となる、以下のコードを組むことができました。
HTML
1<body> 2 3 <div id="Questions"><h1>質問</h1> 4 5 <div id="Q1"> 6 <p>Q. 生きていますか?</p> 7 <label><input type="radio" name="RadGrpA1" id="A1Yes">YES</label> 8 <label><input type="radio" name="RadGrpA1" id="A1No">No</label> 9 <label><input type="radio" name="RadGrpA1">わからない</label> 10 </div> 11 12 <div id="Q2"> 13 <p>Q. 首が長いですか?</p> 14 <label><input type="radio" name="RadGrpA2" id="A2Yes">YES</label> 15 <label><input type="radio" name="RadGrpA2" id="A2No">No</label> 16 <label><input type="radio" name="RadGrpA2">わからない</label> 17 </div> 18 19 <div id="Q3"> 20 <p>Q. 植物ですか?</p> 21 <label><input type="radio" name="RadGrpA3" id="A3Yes">YES</label> 22 <label><input type="radio" name="RadGrpA3" id="A3No">No</label> 23 <label><input type="radio" name="RadGrpA3">わからない</label> 24 </div> 25 26 <div id="Q4"> 27 <p>Q. トゲがありますか?</p> 28 <label><input type="radio" name="RadGrpA4" id="A4Yes">YES</label> 29 <label><input type="radio" name="RadGrpA4" id="A4No">No</label> 30 <label><input type="radio" name="RadGrpA4">わからない</label> 31 </div> 32 33 <div id="Q5"> 34 <p>Q. 人間ですか?</p> 35 <label><input type="radio" name="RadGrpA5" id="A5Yes">YES</label> 36 <label><input type="radio" name="RadGrpA5" id="A5No">No</label> 37 <label><input type="radio" name="RadGrpA5">わからない</label> 38 </div> 39 40 <div id="Q6"> 41 <p>Q. ミュージシャンですか?</p> 42 <label><input type="radio" name="RadGrpA6" id="A6Yes">YES</label> 43 <label><input type="radio" name="RadGrpA6" id="A6No">No</label> 44 <label><input type="radio" name="RadGrpA6">わからない</label> 45 </div> 46 47 <div id="Q7"> 48 <p>Q. 実在しますか?</p> 49 <label><input type="radio" name="RadGrpA7" id="A7Yes">YES</label> 50 <label><input type="radio" name="RadGrpA7" id="A7No">No</label> 51 <label><input type="radio" name="RadGrpA7">わからない</label> 52 </div> 53 54 </div> 55 56 <h1>正解可能性</h1> 57 <p id="Cabbage">キャベツ</p> 58 <p id="Cactus">サボテン</p> 59 <p id="Elephant">象</p> 60 <p id="Giraffe">キリン</p> 61 <p id="MichaelJackson">マイケルジャクソン</p> 62 <p id="NobunagaOda">織田信長</p> 63 64</body>
JavaScript
1const AutoJudgement = () => { 2 3 let Judge = {Cabbage:"", Cactus:"", Elephant:"", Giraffe:"", MichaelJackson:"", NobunagaOda:""}; 4 let JudgeArray = ["Cabbage", "Cactus", "Elephant", "Giraffe", "MichaelJackson", "NobunagaOda"]; 5 6 //各選択肢(Response)を選択した際に、正解可能性リストから除外する項目をOmitにまとめています 7 const ResponseAndProcess = [ 8 {Response:"A1Yes", Omit:["Cabbage","Cactus"]}, 9 {Response:"A1No", Omit:["Elephant","Giraffe","MichaelJackson","NobunagaOda"]}, 10 {Response:"A2Yes", Omit:["Cabbage","Cactus","Elephant","MichaelJackson","NobunagaOda"]}, 11 {Response:"A2No", Omit:["Giraffe"]}, 12 {Response:"A3Yes", Omit:["Elephant","Giraffe","MichaelJackson","NobunagaOda"]}, 13 {Response:"A3No", Omit:["Cabbage","Cactus"]}, 14 {Response:"A4Yes", Omit:["Cabbage","Elephant","Giraffe","MichaelJackson","NobunagaOda"]}, 15 {Response:"A4No", Omit:["Cactus"]}, 16 {Response:"A5Yes", Omit:["Cabbage","Cactus","Elephant","Giraffe"]}, 17 {Response:"A5No", Omit:["MichaelJackson","NobunagaOda"]}, 18 {Response:"A6Yes", Omit:["Cabbage","Cactus","Elephant","Giraffe","NobunagaOda"]}, 19 {Response:"A6No", Omit:["MichaelJackson"]}, 20 {Response:"A7Yes", Omit:[""]}, 21 {Response:"A7No", Omit:["Cabbage", "Cactus", "Elephant", "Giraffe", "MichaelJackson", "NobunagaOda"]}, 22 ]; 23 24 //各Responseが選択された場合に、対応するOmitの各コンテンツに対して「不正解」という値を付与する 25 for (let i=0; i<ResponseAndProcess.length; i++) { 26 if (document.getElementById(ResponseAndProcess[i].Response).checked) { 27 for (let j=0; j<ResponseAndProcess[i].Omit.length; j++) { 28 Judge[ResponseAndProcess[i].Omit[j]] = "不正解"; 29 } 30 } 31 } 32 33 //「不正解」値を持つ正解可能性リストに対して「ZeroPossibility」クラスを付与する(CSSで非表示にします) 34 for (let i = 0; i < JudgeArray.length; i++) { 35 if (Judge[JudgeArray[i]] == "不正解") { 36 document.getElementById(JudgeArray[i]).classList.add("ZeroPossibility"); 37 } else { 38 document.getElementById(JudgeArray[i]).classList.remove("ZeroPossibility"); 39 } 40 } 41 42 //Omitの持つコンテンツを、これ以上正解可能性リストから除外することができない場合(回答を絞り込むうえで質問が役に立たなくなった場合)に、設問のdiv自体にも「ZeroPossibility」クラスを付与し、CSSで非表示にする 43 document.querySelectorAll('#Questions > div').forEach(el => el.classList.remove("ZeroPossibility")) 44 const Possibilities = Object.entries(Judge).flatMap(e => e[1] === "不正解" ? [] : e[0]); 45 const ZeroPossibilityResponses = ResponseAndProcess.flatMap(e => Possibilities.every(x => !e.Omit.includes(x)) ? e.Response : []) 46 ZeroPossibilityResponses.forEach(opt => { 47 const $Options = document.getElementById(opt); 48 if(!$Options.checked){ 49 $Options.closest('div').classList.add('ZeroPossibility') 50 } 51 }); 52 53}; 54 55document.getElementById("Questions").addEventListener("change", () => { 56 AutoJudgement(); 57});
上記により、どの質問からも回答することができ、なおかつ不要な質問には答えなくて済むので、最短手数でユーザーを正解に導くUIができました。
しかし、完成手前でひとつの欠陥に気がつきました。それは、**「Omitが空っぽ("")となる選択肢が存在する場合に、有無を言わさずその設問が非表示にされてしまう」**という問題です。
例えば、例示用に追記した「実在しますか?」という問いの「A7Yes」は、Omitが空です。そのため、仮に「A7No」が問題の切り分けに有効な質問であったとしても、「A7Yes」が空であることに引っ張られて、どのラジオボタンを選択しても常に問7が非表示にされてしまいます。
teratail用に記載したこの質問例とは別のシチュエーションで、「Yes」なら一切の切り分けができないけれども「No」ならば正解の切り分けに有効な質問に、実際に直面しております。
「Omitが空っぽである」という理由で、設問が丸ごと非表示にされてしまうのを防ぐにはどうすれば良いでしょうか?
「設問自体を変えよう」という回答はなしで、上記をプログラム的に実現する方法をご教示いただければ幸いです。
皆様のお助けに心から感謝いたします!
回答1件
あなたの回答
tips
プレビュー