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

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

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

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

1回答

776閲覧

JavaScriptのsetTimeOutメソッドの挙動がおかしい

ren.w

総合スコア42

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

1クリップ

投稿2021/12/09 09:22

前提・実現したいこと

現在制作中のクイズゲームで、選択肢をクリックしてから数秒後に次の問題が表示されるという仕組みを作りたいのですが上手くいきません。

194行目のif文で正誤判定をし、206行目でsetTimeOutを呼び出していていて、187行目にsetTimeOutに渡すための関数を定義しています。(関数の中身はquizIndex++;で次の問題に進めるための変数の値を増やしています)
しかしテストしてみると、「1問目だけ2回クリックしないと次の問題に進めず、2問目以降は処理が遅延されず、クイズが終了した後アラートも表示されない」という結果になりました。
解決策をお願いします。

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

Uncaught TypeError: Cannot read properties of undefined (reading 'correct') at clickHandlerE (quiz.js:194) at HTMLDivElement.<anonymous> (quiz.js:227)

該当のソースコード

JavaScript

1const $question=document.getElementById("question")//問題文の親要素 2const $answer=document.getElementById("answer")//選択肢の親要素 3const $button=document.getElementById("button-d")//難易度 4const $easy=document.getElementById("easy")//初級 5const $middle=document.getElementById("middle") 6const $difficult=document.getElementById("difficult") 7const $hell=document.getElementById("hell") 8let $smile=document.getElementById("smile") 9let $sleep=document.getElementById("sleep") 10let $good=document.getElementById("good") 11let $bad=document.getElementById("bad") 12 13 14let $questionText=document.getElementById("questionText")//問題文 15let $answerW=document.getElementsByClassName("answer")//選択肢 16 17const answerLength=$answerW.length//選択肢の数 18 19 20 21const questionOriginal=$question.style.visibility; 22const answerOriginal=$answer.style.visibility; 23 24//表示用 25 26$question.style.visibility = "hidden"; 27$answer.style.visibility = "hidden"; 28 29//非表示 30 31 32$button.onclick = function() { 33 $button.style.visibility ="hidden"; 34 $question.style.visibility=questionOriginal; 35 $answer.style.visibility=answerOriginal; 36 $smile.style.bottom = 87+"px"; 37 $sleep.style.bottom = 87+"px"; 38 }; 39 //画面切り替え 40 41 42 const quizE=[ 43 { 44 questionBox:"ミラ様のフルネームは?", 45 answerBox:[ 46 "ミラ・フェンリエッタ", 47 "ミラ・フェンリス", 48 "ミラ・フェンリエヌト", 49 "ミラ・フェルート" 50 ], 51 correct:"ミラ・フェンリエッタ" 52 53 },{ 54 questionBox:"ミラ様の種族は?", 55 answerBox:[ 56 "サキュバス", 57 "悪魔", 58 "人間", 59 "ヴァンパイア" 60 ], 61 correct:"悪魔" 62 },{ 63 questionBox:"今まで登場したミラ様の職業の中で、一番多いのは次の内どれ?", 64 answerBox:[ 65 "剣士", 66 "アーチャー", 67 "魔導士", 68 "ルーンセイバー" 69 ], 70 correct:"魔導士" 71 } 72 ]; 73 74 //問題箱 75 const quizLengthE=quizE.length; 76 const quizLengthM=quizM.length; 77 const quizLengthD=quizD.length; 78 const quizLengthH=quizH.length; 79 let quizIndex=0; 80 81 82 const setUpQuizE=()=>{ 83 $questionText.innerHTML=quizE[quizIndex].questionBox 84 let answerIndex = 0; 85 while(answerIndex<answerLength){ 86 $answerW[answerIndex].innerHTML = quizE[quizIndex].answerBox[answerIndex]; 87 answerIndex++; 88 //answer.lengthで省略 89 } 90 }; 91 92 const reset = () =>{ 93 quizIndex++; 94 95 } 96 //setTimeOutに渡すため関数化 97 98 const clickHandlerE =(e)=>{ 99 if(quizE[quizIndex].correct===e.target.innerHTML){ 100 101 $good.style.bottom = 87+"px"; 102 $good.classList.add("plus"); 103 } 104 else{ 105   106 $bad.style.bottom = 87+"px"; 107 $bad.classList.add("plus"); 108 109 } 110 111 setTimeout(reset,1000); 112 113 114 if(quizIndex<quizLengthE){ 115 setUpQuizE(); 116 } 117 else{ 118 window.alert("終了!"); 119 } 120 }; 121 //選択肢をクリックしたときの動作 122 123 let handlerIndex=0;//関数内で使えるようにするため 124 125 $easy.onclick = function(){ 126 setUpQuizE(); 127 128 let handlerIndex=0; 129 130 while(handlerIndex<answerLength){ 131 $answerW[handlerIndex].addEventListener("click",(e)=>{ 132 clickHandlerE(e); 133 }); 134 handlerIndex++; 135 }; 136 //clickHandlerEを全ての選択肢に設定 137 }; 138

HTML

1<!doctype html> 2<html class="no-js" lang=""> 3 4<head> 5 <meta charset="utf-8"> 6 <title></title> 7 <meta name="description" content=""> 8 <meta name="viewport" content="width=device-width, initial-scale=1"> 9 10 <meta property="og:title" content=""> 11 <meta property="og:type" content=""> 12 <meta property="og:url" content=""> 13 <meta property="og:image" content=""> 14 15 <link rel="manifest" href="site.webmanifest"> 16 <link rel="apple-touch-icon" href="icon.png"> 17 <!-- Place favicon.ico in the root directory --> 18 19 <!-- CSS only --> 20<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> 21 22 <meta name="theme-color" content="#fafafa"> 23 24</head> 25<body> 26 27 <style> 28 29 .container{ 30 margin-right: auto; 31 margin-left: auto; 32 max-width: 700px; 33 34 background-image:url(haikei.png); 35 background-size:cover; 36 background-position:center center; 37 background-repeat: no-repeat; 38 object-fit: cover; 39 position: relative; 40 } 41 42 .question{ 43 text-align:center; 44 position:absolute; 45 border: solid 2px gray; 46 } 47 48 .fixed-bottom{ 49 margin: 0; 50 position:absolute; 51 text-align:center; 52 } 53 54 .answer{ 55 border: solid 2px gray; 56 } 57 58 .smile{ 59 position: absolute; 60 left: 30px; 61 bottom: 47px; 62 animation: 63 name1 3s step-end 0s infinite normal; 64 z-index: 2; 65 } 66 67 .sleep{ 68 position: absolute; 69 left: 30px; 70 bottom: 47px; 71 z-index: 1; 72 } 73 74 .good{ 75 position: absolute; 76 left: 30px; 77 bottom: 47px; 78 z-index: 3; 79 opacity:0; 80 } 81 82 #good.plus{ 83 84 animation: 85 1s step-end 0s 1 normal plus; 86 } 87 88 @keyframes plus{ 89 0% { opacity:1; } 90 100% { opacity:1; } 91 } 92 93 .bad{ 94 position: absolute; 95 left: 30px; 96 bottom: 47px; 97 z-index: 3; 98 opacity:0; 99 } 100 101 #bad.plus{ 102 animation: 103 1s step-end 0s 1 normal plus; 104 } 105 106 @keyframes plus{ 107 0% { opacity:1; } 108 100% { opacity:1; } 109 } 110 111 @keyframes name1{ 112 0%{ opacity:1; } 113 114 35%{ opacity:0; } 115 116 40%{ opacity:1; } 117 118 80%{ opacity:0; } 119 120 85%{ opacity:1; } 121 122 95%{ opacity:0; } 123 124 100%{ opacity:1; } 125 } 126 127 @media screen and (min-width: 481px) { 128 /* 481px以上に適用されるCSS(タブレット用) */ 129 .smile{ 130 position: absolute; 131 left: 50px; 132 bottom: 47px; 133 animation: 134 name1 3s step-end 0s infinite normal; 135 z-index: 2; 136 } 137 138 .sleep{ 139 position: absolute; 140 left: 50px; 141 bottom: 47px; 142 z-index: 1; 143 } 144 145 .good{ 146 position: absolute; 147 left: 50px; 148 bottom: 47px; 149 z-index: 3; 150 opacity:0; 151 } 152 153 .bad{ 154 position: absolute; 155 left: 50px; 156 bottom: 47px; 157 z-index: 3; 158 opacity:0; 159 } 160 161 } 162 @media screen and (min-width: 960px) { 163 /* 960px以上に適用されるCSS(PC用) */ 164 .smile{ 165 position: absolute; 166 left: 90px; 167 bottom: 47px; 168 animation: 169 name1 3s step-end 0s infinite normal; 170 z-index: 4; 171 } 172 173 .sleep{ 174 position: absolute; 175 left: 90px; 176 bottom: 47px; 177 z-index: 3; 178 } 179 180 .good{ 181 position: absolute; 182 left: 90px; 183 bottom: 47px; 184 z-index: 3; 185 opacity:0; 186 } 187 188 .bad{ 189 position: absolute; 190 left: 90px; 191 bottom: 47px; 192 z-index: 3; 193 opacity:0; 194 } 195 196 } 197 </style> 198 199<div class="p-4"> 200</div><!---- space --> 201 202 <div id="top"class="container mt-5 py-5 px-0"> 203 204 <div id="question" class="row justify-content-center"> 205 <div id=questionText class="question fixed-top">問題文</div> 206 </div><!---- question --> 207 208 <div id="button-d"class="row flex-column d-flex align-items-center justify-content-center" style="margin:0;"> 209 <h1 class="col-3 text-center mb-5">クイズ</h1> 210 <button type="button" id="easy"class="col-2 btn btn-primary mb-3 w-25">初級</button> 211 <button type="button" id="middle"class="col-2 ml-1 btn btn-primary mb-3 w-25">中級</button> 212 <button type="button" id="difficult"class="col-2 ml-1 btn btn-primary mb-3 w-25">上級</button> 213 <button type="button" id="hell"class="col-2 ml-1 btn btn-primary w-25">冥府級</button> 214 </div> <!---- difficulty level --> 215 216 <div id="answer"class="row fixed-bottom flex-row row-cols-2 justify-content-center"> 217 <div type="button" id="choiseF" class="answer col py-2 px-0">選択肢1</div> 218 <div type="button" id="choiseS" class="answer col py-2 px-0">選択肢2</div> 219 <div type="button" id="choiseT" class="answer col py-2 px-0">選択肢3</div> 220 <div type="button" id="choiseFo" class="answer col py-2 px-0">選択肢4</div> 221 </div> <!---- answer --> 222 223 <img id="smile" class="smile position-absolute " src="smile.png" alt=""> 224 <img id="sleep" class="sleep position-absolute " src="sleep.png" alt=""> 225 <img id="good" class="good position-absolute " src="good.png" alt=""> 226 <img id="bad" class="bad position-absolute " src="bad.png" alt=""> 227 228 </div><!---- container --> 229 230 <script src="quiz.js"></script> 231 232</body> 233 234</html> 235

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

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

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

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

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

guest

回答1

0

ベストアンサー

setTimeout()の動作を勘違いしていると思われます。

js

1const reset = () => { 2 // コードT 3}; 4 5const clickHandlerE =(e) => { 6 7 // コードA 8 9 setTimeout(reset,1000); 10 11 // コードB 12};

という構成のとき、実行される順番は、コードA → コードB → 1秒休み → コードT です。

コードBをreset()の中に移動したものが期待する動作でしょうか。

js

1const reset = () => { 2 // コードT 3 // コードB 4}; 5 6const clickHandlerE =(e) => { 7 8 // コードA 9 10 setTimeout(reset,1000); 11};

投稿2021/12/09 09:47

int32_t

総合スコア21695

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

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

ren.w

2021/12/10 14:02

ありがとうございます。 期待通りの動作を作ることができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問