user8359832
user8359832

Reputation:

Switch Statement implementation not providing expected behavior

I am developing a quizz application in vanilla JavaScript and in the interest of best practices, I want to ensure I follow the D.R.Y. principle.

I have five questions that I need to check answers for.

As a result, instead of using if statements five times, I thought I could implement a switch statement like so:

callback.js:

function submitAnswers() {
  var total = 5;
  var score = 0;
  // Get User Input
  var q1 = document.forms['quizForm']['q1'].value;
  var q2 = document.forms['quizForm']['q2'].value;
  var q3 = document.forms['quizForm']['q3'].value;
  var q4 = document.forms['quizForm']['q4'].value;
  var q5 = document.forms['quizForm']['q5'].value;

  // Validation
  for (i = 1; i <= total; i++) {
    if (eval('q'+i) == null || eval('q'+i) == '') {
      alert('You missed question '+ i);
      return false;
    }
  }

  // Set Correct Answers
  var answers = ["d","b","c","a","b"];

  // Check answers
  switch (answers) {
    case q1 == answers[0]:
      score++;
      break;
    case q2 == answers[1]:
      score++;
      break;
    case q3 == answers[2]:
      score++;
      break;
    case q4 == answers[3]:
      score++;
      break;
    case q5 == answers[4]:
      score++;
      break;
  }

  alert('You scored '+score+' out of ' +total);
}

This is the index.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" type="text/css" href="css/index.css">
        <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
        <script type="text/javascript" src="js/callback.js"></script>
        <title>Quiz About the Wonderful World of Fungi</title>

    </head>
    <body>
            <div id="container">
                <header>
                    <h1>Quiz About the Wonderful World of Fungi</h1>
                    <p>Test your knowledge</p>
                </header>
                <section>
                        <div id="results"></div>
                        <form class="myForm" name="quizForm" onSubmit="return submitAnswers()">
                            <h3>1. Roughly how many species of organisms of the kingdom of Fungi have been identified, so far?</h3>
                            <input type="radio" name="q1" value="a" id="q1a">a. 2 Million<br>
                            <input type="radio" name="q1" value="b" id="q1b">b. 37,000<br>
                            <input type="radio" name="q1" value="c" id="q1c">c. 58,000<br>
                            <input type="radio" name="q1" value="d" id="q1d">d. 73,000<br>

                            <h3>2. The process of specifically using mushrooms to break down toxic chemicals and sequester heavy metals is known as:</h3>
                            <input type="radio" name="q2" value="a" id="q2a">a. Bioremediation<br>
                            <input type="radio" name="q2" value="b" id="q2b">b. Mushremediation<br>
                            <input type="radio" name="q2" value="c" id="q2c">c. Mycoremediation<br>
                            <input type="radio" name="q2" value="d" id="q2d">d. Chitinremediation<br>

                            <h3>3. The above-ground part of the mushroom that  we typically associate with a mushroom is only a small part of the whole organism,
                                            as most of it is underground. What is the primary role of this part of the  whole organism?</h3>
                            <input type="radio" name="q3" value="a" id="q3a">a. Nutrient Absorptionn<br>
                            <input type="radio" name="q3" value="b" id="q3b">b. Protection<br>
                            <input type="radio" name="q3" value="c" id="q3c">c. Sexual Reproduction<br>
                            <input type="radio" name="q3" value="d" id="q3d">d. Oxygen Absorption<br>

                            <h3>4. What Is the primary role of a mushroom’s underground mycelium?</h3>
                            <input type="radio" name="q4" value="a" id="q4a">a. Nutrient Absorption<br>
                            <input type="radio" name="q4" value="b" id="q4b">b. Anchoring<br>
                            <input type="radio" name="q4" value="c" id="q4c">c. Asexual Reproduction<br>
                            <input type="radio" name="q4" value="d" id="q4d">d. Protection<br>

                            <h3>5. The largest living organism on earth is thought to be a mushroom (the honey fungus) and it is estimated to be what distance across?</h3>
                            <input type="radio" name="q5" value="a" id="q5a">a. 0.5 mile<br>
                            <input type="radio" name="q5" value="b" id="q5b">b. 2.4 miles<br>
                            <input type="radio" name="q5" value="c" id="q5c">c. 8 miles<br>
                            <input type="radio" name="q5" value="d" id="q5d">d. 0.7 mile<br>
                            <br><br>
                            <input type="submit" name="" value="Submit Answers">
                        </form>

                </section>
                <footer>
                    <p>Copyright &copy; 2017, All Rights Reserved</p>
                </footer>
            </div>
    </body>
</html>

Upon testing this, I continued to get an alert saying I have 0 out of 5 correct, even when choosing the correct answers.

Is the switch statement not the best solution here? Am I applying it wrong?

Upvotes: 0

Views: 72

Answers (3)

Jaco Ahmad
Jaco Ahmad

Reputation: 43

You can create a reusable function for this instead of switch statement, and use for loop to check every target value;

// Answers
var answers = ["a", "b", "c"]

// Correct increments
var correct = 0;

// checkAnswer Function
var checkAnswer = function(question, answer) {
  if (question !== answer) {
    return false;
  }
  return true;
}

var form = document.getElementById('form');

form.addEventListener('submit', function(e) {
  e.preventDefault();

  // Notice length - 1, because we have button element there
  /**
    * If you want to declare variable for each inputs, change 
    * e.target.length and e.target[i].value to your arrays of q/a 
    */
  for (var i = 0; i < e.target.length - 1; i++) {
    if (checkAnswer(e.target[i].value, answers[i]) === false) {
      alert('False answer')
      // Right answer function here
    } else {
      correct++
      alert('Right answer!')
      // False answer here
    }
  }
  alert('Your answer is ' + correct + ' correct out of ' + (e.target.length - 1) + ' questions!');
})
<form id="form">
  <input type="text" id="q1">
  <input type="text" id="q2">
  <input type="text" id="q3">
  <button type="submit">Submit answer</button>
</form>

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1073968

The switch value must match one of the case expressions. answers will never match q1 == answers[0] or similar. If you changed it to switch (true) the switch would work, but you'd still only be checking one answer, not all five (and it's not a very good use of switch).

If you use five different qX variables, you'll need five different if statements. But that's not what you should do. Instead, see *** comments:

function submitAnswers() {
  var total = 5;
  var score = 0;
  var i; // *** Note we declare `i` so it's not an implicit global
  // Get User Input
  // *** ...as an array
  var responses = [];
  for (i = 1; i <= 5; ++i) {
    responses.push(document.forms['quizForm']['q' + i].value);
  };

  // Set Correct Answers
  // *** Moved
  var answers = ["d","b","c","a","b"];

  // Validation and check answers both at once
  for (i = 0; i < responses.length; ++i) {
    // *** `value` is never `null`, we can just use ! here
    if (!responses[i]) {
      alert('You missed question '+ i);
      return false;
    }
    // *** Check response
    if (response[i] == answers[i]) {
      ++score;
    }
  }

  alert('You scored '+score+' out of ' +total);
}

A couple of notes:

  • It's important to declare your variables (you didn't declare i). If you don't, in loose mode you can end up creating global variables by mistake, which can be quite difficult to debug. More (in a post on my anemic little blog)*: The Horror of Implicit Globals
  • Any time you reach for eval to form a variable name like q1, q2, etc., you probably want an array instead. There are valid use cases for eval, but they're very few and far between.

Upvotes: 1

Vignesh Raja
Vignesh Raja

Reputation: 8731

Simple method. Form an array with all chosen answers and compare iteratively using Array#every

var correctanswers = ["d","b","c","a","b"];
var choosenanswers = [q1,q2,q3,q4,q5];
var isallcorrect = choosenanswers.every(function(item,index){
    return item == correctanswers[index];
});
console.log(isallcorrect);

Upvotes: 0

Related Questions