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

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

ただいまの
回答率

90.34%

  • JavaScript

    17506questions

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

  • HTML

    9552questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • CSS

    6189questions

    CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

JS:score計算、radio/buttonイベント、コード短縮

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 151

mo__fumi

score 3

JS練習のため簡易クイズアプリを製作しています。
クイズが3問あり、各設問にはradioボタン、”回答する”ボタンがあります。
また最後には”スコアを見る”ボタンがあり合計スコアが表示されると同時に、console.logでコメントが表示されます。

問題点は以下の三つです(他にもありそうですが・・・)

(1)score1, score2, score3を足す計算が上手くいかない。
score1+score2+score3だと例えば1点+1点+0点=2点となる場合もあるが全ての場合において答えが0で計算されてしまう。

(2)radioボタン選択時とbuttonクリック時、各々でconsole.logでコメントを出したいが上手く両立されない(現在はradioボタン選択時のみ正常に動いています)。
"回答する"ボタンを押すと console.log('不正解です。', '現在のトータルスコア:' + score) となるようにしたいが script.js:37 Uncaught ReferenceError: value1 is not defined at answerQuiz1 (script.js:37) at HTMLButtonElement.onclick (index.html:21) といったエラーが出る。

(3)もう少しまとめて短いコードにできる気がするがやり方がわからない。例えば、

function quiz1() {
 function selectQuiz1() {
 ...
 }
 function answerQuiz1() {
 ...
 }
}

のように書いて見たがエラーになった。
コードは以下です。

        let score = 0;
        let score1 = 0;
        let score2 = 0;
        let score3 = 0;
        score = score1 + score2 + score3; //この式が機能していない?


        function selectQuiz1() {
            const quiz_1 = document.getElementById('quiz-1');
            const value1 = quiz_1.answer.value;

            switch (value1) {
                case 'a':
                    console.log('1問目の' + value1 + 'を選択しました')
                    break;
                case 'b':
                    console.log('1問目の' + value1 + 'を選択しました')
                    break;
                case 'c':
                    console.log('1問目の' + value1 + 'を選択しました')
                    break;
            }
        }

        function answerQuiz1() {
            switch (value1) {
                case 'a':
                    score1 = 0;
                    console.log('不正解です。', '現在のトータルスコア:' + score)
                    break;
                case 'b':
                    score1 = 1;
                    console.log('正解です。', '現在のトータルスコア:' + score)
                    break;
                case 'c':
                    score1 = 0;
                    console.log('不正解です。', '現在のトータルスコア:' + score)
                    break;
            }
        }

        function selectQuiz2() {
            const quiz_2 = document.getElementById('quiz-2');
            const value2 = quiz_2.answer.value;

            switch (value2) {
                case 'a':
                    console.log('2問目の' + value2 + 'を選択しました')
                    break;
                case 'b':
                    console.log('2問目の' + value2 + 'を選択しました')
                    break;
                case 'c':
                    console.log('2問目の' + value2 + 'を選択しました')
                    break;
            }
        }

        function answerQuiz2() {
            switch (value2) {
                case 'a':
                    score2 = 1;
                    console.log('正解です。', '現在のトータルスコア:' + score)
                    break;
                case 'b':
                    score2 = 0;
                    console.log('不正解です。', '現在のトータルスコア:' + score)
                    break;
                case 'c':
                    score2 = 0;
                    console.log('不正解です。', '現在のトータルスコア:' + score)
                    break;
            }
        }

        function selectQuiz3() {
            const quiz_3 = document.getElementById('quiz-3');
            const value3 = quiz_3.answer.value;

            switch (value3) {
                case 'a':
                    console.log('3問目の' + value3 + 'を選択しました')
                    break;
                case 'b':
                    console.log('3問目の' + value3 + 'を選択しました')
                    break;
                case 'c':
                    console.log('3問目の' + value3 + 'を選択しました')
                    break;
            }
        }

        function answerQuiz3() {
            switch (value3) {
                case 'a':
                    score3 = 0;
                    console.log('不正解です。', '現在のトータルスコア:' + score)
                    break;
                case 'b':
                    score3 = 0;
                    console.log('不正解です。', '現在のトータルスコア:' + score)
                    break;
                case 'c':
                    score3 = 1;
                    console.log('正解です。', '現在のトータルスコア:' + score)
                    break;
            }
        }

        function showScore() {
            document.getElementById('score-message').innerHTML = score;

            if (score === 3) {
                console.log('3点:すばらしい!');
            } else if (score === 2) {
                console.log('2点;おしい!');
            } else if (score === 1) {
                console.log('1点;まあまあ');
            } else {
                console.log('0点;残念');
            }
        }
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css" />
<script src="script.js"></script>
</head>
<body>
<div class="quizzes-container">
<h1>Quiz</h1>
  <div class="quiz-container">
    <h2>1問目</h2>
    <div>
    <p>モロッコの首都は次のうちのどれ</p>
    </div>
    <form id="quiz-1" onclick="selectQuiz1();">
        <input name="answer" type="radio" value="a">カサブランカ</input>
      <!--正解はBのラバト---->
        <input name="answer" type="radio" value="b">ラバト</input>
        <input name="answer" type="radio" value="c">マラケシュ</input>
    </form>
    <button class="btn" type="button" onclick="answerQuiz1();">回答する</button>
  </div>
  <div class="quiz-container">
    <h2>2問目</h2>
    <div>
    <p>世界でもっとも深い湖は次のうちのどれ</p>
    </div>
    <form id="quiz-2" onclick="selectQuiz2();">
      <!--正解はAのバイカル湖---->
        <input name="answer" type="radio" value="a">バイカル湖</input>
        <input  name="answer" type="radio" value="b">カスピ海</input>
        <input name="answer" type="radio" value="c">ビクトリア湖</input>
    </form>
    <button class="btn" type="button" onclick="answerQuiz2();">回答する</button>
  </div>
  <div class="quiz-container">
    <h2>1問目</h2>
    <div>
    <p>絵画「夜警」を描いた画家は次のうちのどれ</p>
    </div>
    <form id="quiz-3" onclick="selectQuiz3();">
        <input name="answer" type="radio" value="a">フェルメール</input>
        <input name="answer" type="radio" value="b">カラバッジオ</input>
      <!--正解はCのレンブラント---->
        <input name="answer" type="radio" value="c">レンブラント</input>
    </form>
    <button class="btn" type="button" onclick="answerQuiz3();">回答する</button>
</div>
<div id="score-container">
    <button class="btn" type="button" onclick="showScore();">スコアを見る</button>
  <!--pタグ内にスコアを表示-->
  <p id="score-message"></p>
</div>
</body>
.quizzes-container{
  width: 400px;
}

.quiz-container{
  border-bottom:1px solid black;
  padding-bottom: 20px;
}


#score-container{
  border: 1px solid black;
}

どなたかアドバイス頂けたら幸いです。よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2018/07/27 20:28

    「うまく動作しない」「うまくいかない」では何が起きているか伝わりません。「○○のようになるはずなのに××となってしまう」のような形で「ゴール」と「現象(エラーメッセージなども含む)」を明確にしてください。https://teratail.com/help/question-tips#questionTips3-4-1

    キャンセル

  • mo__fumi

    2018/07/28 17:23

    コメントありがとうございます! (1)socre1+score2+score3だと例えば1点+1点+0点=2点となる場合もあるが全ての場合において答えが0で計算されてしまう。 (2)"回答する"ボタンを押すと console.log('不正解です。', '現在のトータルスコア:' + score) となるようにしたいが script.js:37 Uncaught ReferenceError: value1 is not defined at answerQuiz1 (script.js:37) at HTMLButtonElement.onclick (index.html:21) といったエラーが出る。という状況です。慣れておらずすみません今後気をつけます!

    キャンセル

  • mts10806

    2018/07/28 21:13

    質問は編集できるので適宜追記してください。ここのコメント欄はデフォルト非表示のため、目につきにくいです。

    キャンセル

  • mo__fumi

    2018/07/28 23:47

    おお!!機能についても勉強になりました^^;ありがとうございました!!

    キャンセル

回答 1

checkベストアンサー

+2

ざっと見てみてみましたが、selectQuiz1()などで値を取り出すのは、
document.getElementById('quiz-1').elements["answer"].value
のようにする必要がありそうです。

値を取り出す例だと https://developer.mozilla.org/ja/docs/Web/API/HTMLFormElement ですね。

また、selectQuiz1()などについてはそもそも使わなくても良くて、answerQuiz1()などを呼び出す時に値を取ってくればよいかと思います。

そしてanswerQuiz1()などの方ですが、正解を別のオブジェクトに入れておいて、answerQuiz(quizId)といったようにformのIDを指定するようにすれば、3つではなく1つにまとめられます。個別のscoreについてもグローバルなオブジェクトに入れておく感じですね。

というわけで、ざっくり直すとこんな感じでしょうか。

const correctAnswers = {"quiz-1":"b", "quiz-2":"a", "quiz-3": "c"};
let scores = {"quiz-1":0, "quiz-2":0, "quiz-3":0};

function answerQuiz(quizId) {
  const value1 = document.getElementById(quizId).elements["answer"].value;
  const correctAnswer = correctAnswers[quizId];
  if (value1 === correctAnswer) {
    scores[quizId] = 1;
    console.log('正解です。', '現在のトータルスコア:' + calcScore())
  } else {
    scores[quizId] = 0;
    console.log('不正解です。', '現在のトータルスコア:' + calcScore())
  }
}

function calcScore() {
  return scores["quiz-1"] + scores["quiz-2"] + scores["quiz-3"];
}

function showScore() {
  const score = calcScore();
  document.getElementById('score-message').innerHTML = score;

  if (score === 3) {
    console.log('3点:すばらしい!');
  } else if (score === 2) {
    console.log('2点;おしい!');
  } else if (score === 1) {
    console.log('1点;まあまあ');
  } else {
    console.log('0点;残念');
  }
}

点数の計算にはcalcScore()という関数を追加しています。
HTMLも以下のように直しておいてください。

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="styles.css" />
<script src="script.js"></script>
</head>
<body>
<div class="quizzes-container">
<h1>Quiz</h1>
  <div class="quiz-container">
    <h2>1問目</h2>
    <div>
    <p>モロッコの首都は次のうちのどれ</p>
    </div>
    <form id="quiz-1">
        <input name="answer" type="radio" value="a">カサブランカ</input>
      <!--正解はBのラバト---->
        <input name="answer" type="radio" value="b">ラバト</input>
        <input name="answer" type="radio" value="c">マラケシュ</input>
    </form>
    <button class="btn" type="button" onclick="answerQuiz('quiz-1');">回答する</button>
  </div>
  <div class="quiz-container">
    <h2>2問目</h2>
    <div>
    <p>世界でもっとも深い湖は次のうちのどれ</p>
    </div>
    <form id="quiz-2">
      <!--正解はAのバイカル湖---->
        <input name="answer" type="radio" value="a">バイカル湖</input>
        <input  name="answer" type="radio" value="b">カスピ海</input>
        <input name="answer" type="radio" value="c">ビクトリア湖</input>
    </form>
    <button class="btn" type="button" onclick="answerQuiz('quiz-2');">回答する</button>
  </div>
  <div class="quiz-container">
    <h2>1問目</h2>
    <div>
    <p>絵画「夜警」を描いた画家は次のうちのどれ</p>
    </div>
    <form id="quiz-3">
        <input name="answer" type="radio" value="a">フェルメール</input>
        <input name="answer" type="radio" value="b">カラバッジオ</input>
      <!--正解はCのレンブラント---->
        <input name="answer" type="radio" value="c">レンブラント</input>
    </form>
    <button class="btn" type="button" onclick="answerQuiz('quiz-3');">回答する</button>
</div>
<div id="score-container">
    <button class="btn" type="button" onclick="showScore();">スコアを見る</button>
  <!--pタグ内にスコアを表示-->
  <p id="score-message"></p>
</div>
</body>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/28 18:59

    丁寧に書いてくださって心から感謝です・・・!!!ちょっと理解に時間がかかる脳みそなので一つずつじっくり読んでいます・・・正解を別のオブジェクトに入れるなど目から鱗でした。そしてこんなにJSが短くなるなんて感動です!全て理解してからお返事しようと思ったのですが時間かかりそうなのでお先にお礼だけお伝えしたく・・・もし質問あればまたコメントさせてください;ひとまずは、ありがとうございました!!

    キャンセル

  • 2018/07/28 19:32

    answerQuiz(quizId) の quizIdとは、例えば <form id="quiz-1" onclick="selectQuiz1();"> の id="quiz-1" のことでしょうか?

    キャンセル

  • 2018/07/28 21:29

    それですね。修正したHTMLの方の、
    <button class="btn" type="button" onclick="answerQuiz('quiz-1');">
    の'quiz-1'がanswerQuiz()関数に渡されて、それがdocument.getElementById(quizId)やcorrectAnswers[quizId]などで使われる、という流れです。

    キャンセル

  • 2018/07/28 21:39

    なるほど。ここで quizId = "quiz-1", "quiz-2", "quiz-3" のように書かなくてもquizIdが何を指しているかわかるのは、htmlで onclick="answerQuiz('quiz-1') のように()に quiz-1, quiz-2, quiz-3 がそれぞれ入っており、function answerQuiz(quizId) ここで()の中に quizId を代入?したためということでしょうか?

    キャンセル

  • 2018/07/28 22:14

    はい、そうやって引数として渡しているからです。

    キャンセル

  • 2018/07/28 22:18

    わかりました!!ありがとうございます^^

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    17506questions

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

  • HTML

    9552questions

    HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

  • CSS

    6189questions

    CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。