Rock, Paper, Scissors Project - Step 3: Why can't I invert if/else in the function

I’m not really stuck at the project, as I eventually peeked into the hint section. But I desperatly want to know why my inital code does not work, since in my eyes it only inverts the if / else statement. I really want to understand what is going on, to make sure not to repeat the mistake. In the end, there is no hint in the wild, right.

Link to the complete exercise. My problem is linked to step 3

The insctructions are to create a function and within formulate an if / else statement, to check wheter the user input is valid. If not, an error message should be logged, else the value should be returned and we can go on.

The correct code, which does what it is supposed to do, looks like this:

const getUserChoice = (userInput) => {
  userInput = userInput.toLowerCase();
  if (
    userInput === "rock" ||
    userInput === "scissors" ||
    userInput === "paper"
  ) {
    return userInput;
  } else {
    console.log("Bitte richtigen Wert eingeben");
  }
};

Initally I wrote

const getUserChoice = (userInput) => {
  userInput = userInput.toLowerCase();
  if (
    userInput !== "rock" ||
    userInput !== "scissors" ||
    userInput !== "paper"
  ) {
    console.log("Bitte richtigen Wert eingeben");
  } else {
    return userInput;
  }
};

The solution does return rock, paper or scissor when the input is accordingly, else the error message is logged. My original code always logs the error message no matter the input.

I wrote it anew so many times and I slept over it, still I don’t see where my mistake could be. Why doesn’t it work. The logic still aplies in my mind.

It is highly appreciated it anyone could explain what is going on or forward me to a source of information, since I was not able to find an answer to this issue. Thank you!

Your condition is not the inverse of the solution condition.

// Your code:
if (
    userInput !== "rock" ||
    userInput !== "scissors" ||
    userInput !== "paper"
  )

Suppose userInput is rock, then the first comparison will be false, but the second comparison userInput !== "scissors" will be true. No matter the value of userInput, regardless of whether it is a valid choice or not, at least two of those expressions are going to be true. The or || will evaluate to true if even one of the operands is true. That is why, your code always logs the error message.

If we want to invert the condition and flip the corresponding blocks, then for a simple equality comparison, we can do something similar to your code.

if (a == b) {
    console.log("Equal");
} else {
    console.log("Not Equal");
}

// Inverting the above:
if (a != b) {
    console.log("Not Equal");
} else {
    console.log("Equal");
}
// or
if (!(a == b)) {
    console.log("Not Equal");
} else {
    console.log("Equal");
}

Both of the above versions will correctly flip the original statement.

However, when you have have other operators such as || and &&, then inverting/negating the operands doesn’t capture the same logic as negating the whole expression.

This will work:

if (!(
    userInput === "rock" ||
    userInput === "scissors" || 
    userInput === "paper"
  )) {
    console.log("Bitte richtigen Wert eingeben");
  } else {
    return userInput;
  }

Another version that will do the same is:

if (
    userInput !== "rock" &&
    userInput !== "scissors" && 
    userInput !== "paper"
  ){
    console.log("Bitte richtigen Wert eingeben");
  } else {
    return userInput;
  }

The above version will only print the error message when ALL of the three choices don’t match.

Basically, just negating the operands doesn’t necessarily negate the original expression.

Related (see section titled DeMorgan’s Laws): A definitive guide to conditional logic in JavaScript

2 Likes

@mtrtmk Thank you so much for the explanation and further solutions! I it get now. And also thank you for the link, I’ll dig into it. Much appriciated!

1 Like