Switch case break and undefined value in JS - javascript

I'm creating a little game in HTML/JS/CSS for an exercise, and I've created a board game of 100 squares with <tr></tr and <td></td>.
There are two players on my board and, on each round, I check the squares around the two players, to see if there is a weapon or a player on this square.
But to check if there is a player on the square, I need to check if the square exist first. That' why I use a lot of switch case statements:
switch (true) {
case (squareAround != undefined): //I check if a square around is not undefined
switch (true) { //if the square exists, let's check if there is a player on it
case (playerOnIt === true):
//start the fight if there is a player on it
}
}
This is of course a simplified version. The break and default statements are not here.
The problem is, sometimes the square is "undefined" and the program doesn't go further, just as I want. But some other times, the square is detected as "undefined" but the program continues anyways. The case is clearly "false" but the switch case isn't working.
I used the console, and this exemple where it doesn't work : in the two first cases the square exist, and then it shows me the two HTML element.
But in the third cases, it's false, but the switch case works anyway, goes further, and gives me the HTML element... which is "undefined" !
What can possibly go wrong ?
Thanks for the help
Edit : here is some original code, ton answer the question of someone. But I don't know if it can help :
switch (true) {
case ($('td')[numberCasePlayer + i + l] != undefined):
switch (true) {
case ($('td')[numberCasePlayer + i + l].getAttribute('playeronit') === playeronitCheck):
fight()
break
}
case ($('td')[numberCasePlayer + i + m] != undefined):
switch (true) {
case ($('td')[numberCasePlayer + i + m].getAttribute('playeronit') === playeronitCheck):
fight()
break
}
case ($('td')[numberCasePlayer + i + n] != undefined):
switch (true) {
case ($('td')[numberCasePlayer + i + n].getAttribute('playeronit') === playeronitCheck):
fight()
break
}
case ($('td')[numberCasePlayer + i].getAttribute('weapon') === 'true'):
$('#' + $('td')[numberCasePlayer + i].getAttribute('weapontype')).css('display', 'none')
}
break

The right format for the switch statement is like:
switch(someVariable) {
case value1: doSomething; break;
case value2: doSomething; break;
case value3: doSomething; break;
...
default: doSomething;
}
It's straight forward if you do it with just if statements.
if(squareAround) {
if(playerOnIt) {
//start the fight if there is a player on it
}
}

Related

Using switch statement and regex to match the format of url path?

I am trying to use switch-statements with regex conditions to set 'direction' variable depending on the 'url'. I have these sample 'url':
1) a. /meat/chicken/C/1/edit
b. /meat/chicken/c/2/edit
c. /meat/chicken/new
2) a. /meat/beef/B/1/edit
b. /meat/beef/b/2/edit
c. /meat/beef/new
Type of meat could vary.
My regex conditions/code are true for these urls:
if(/[a-zA-Z]+.[a-zA-Z]+.[a-zA-Z]+.\d+.[edit]+/.test(url)){
switch (true) {
case /chicken/.test(url):
direction = 'chicken/edit'
break;
case /beef/.test(url):
direction = 'beef/edit';
break;
default:
direction = 'edit';
break;
}
} else if(/[a-zA-Z]+.[a-zA-Z]+.[new]+/.test(url)){
switch (true) {
case /chicken/.test(url):
direction = 'chicken/new'
break;
case /beef/.test(url):
direction = 'beef/new';
break;
default:
direction = 'new';
break;
}
}
However, it is true for other urls as well which I do not want, such as:
/meat/beef/
If 'url' is '/meat/beef/', this is currently returning true on the else if-statement, "(else if(/[a-zA-Z]+.[a-zA-Z]+.[new]+/.test(url)){", which I do not want it to be true because it doesn't have the word 'new'.
I just want my if-statements and switch-statements to match and be true for formats of 1) and 2) above.
I am not very fluent in regular expressions and still learning switch-statements. Can anyone help me?
I think this may be simpler.
const urlParts = url.split('/');
const [base, type] = urlParts;
const action = urlParts[urlParts.length - 1]; // get the last
if (base === 'meat' && (action === 'edit' || action === 'new')) {
direction = [type, action].join('/');
}
Routing libs are hard to get right. I'd use some of the ones that already exist or at least read them for ideas. something like find-my-way would be a great read.

How does that switch case work in JS? What does mean switch(true)?

I am currently working on project, where are parts of code that I don't understand. One of them you can see below (written in JS):
switch (true) {
case parseInt(data):
return 'data';
case parseInt(row):
return 'row';
default:
return 'default';
}
I created JSFiddle to test this switch(true) statement and to see how it behaves. It always returns 'default' string. Can someone explain to me what is happening there, please?
JSFiddle switch test
A switch in JavaScript simply compares if the value of the case is strictly equal (===) to what’s inside the switch (in this case true). This is usually used to compare strings, but booleans would also work, although it is less common. Take the following example:
switch (true) {
case 1 + 1 === 3:
return 'A';
case 2 * 2 === 4:
return 'B';
default:
return 'C';
}
This code would return 'B' as it is the first case to match true. If none of the cases would match true, it would return 'C'.
Regarding your specific scenario; I would recommend rewriting your code to the following:
if (parseInt(data) === true) {
return 'data';
}
if (parseInt(row) === true) {
return 'row';
}
return 'default';
This code does the exact same thing as yours, but it is immediately clear to the reader what is happening.
I am not sure what your goal is with this function, so I cannot recommend the best way to solve your problem. Although, I can explain to you why it might not be working.
The parseInt function will always return a number or NaN (in case the input cannot be parsed). Although a number can be truthy, it will never be strictly true. That's why your function always returns 'default'. Again, I don't know what your goal is, but you might want to check if the value is truthy instead of true:
if (parseInt(data)) {
// Data can be parsed to a number and is not 0
return 'data';
}
if (parseInt(row)) {
// Row can be parsed to a number and is not 0
return 'row';
}
return 'default';
It'll execute the first case that evaluates to true. If no case is true, it'll execute the default block
For example:
switch (true) {
case 1 === 1:
console.log('ok1');
break;
case 2 === 2:
console.log('ok2');
break;
default:
console.log('not ok');
}
will console.log('ok1')

Replace with the regular expression

What regular expression I need to use to correct
if (text.indexOf("+") != -1) {
action = "+";
} else if (text.indexOf("-") != -1) {
action = "-";
} else if (text.indexOf("*") != -1) {
action = "*";
} else if (text.indexOf("/") != -1) {
action = "/";
}
this code
?
EDIT:
and how can I improve this code:
switch (action) {
case "+":
result = parseInt(array[0]) + parseInt(array[1]);
break;
case "-":
result = parseInt(array[0]) - parseInt(array[1]);
break;
case "*":
result = parseInt(array[0]) * parseInt(array[1]);
break;
case "/":
result = parseInt(array[0]) / parseInt(array[1]);
break;
default:
break;
}
Sorry for dull questions I am new in js.
You can use either of these:
var action = text.replace(/.*([+*/-]).*/,'$1');
var match = /[*+/-]/.exec(text);
var action = match && match[0];
If there's the possibility of newlines in your text then change the first to:
var action = text.replace(/[\d\D]*([+*/-])[\d\D]*/,'$1');
Edit: You can improve your switch statement by using, e.g.
// allow floating point values, and also
// don't accidentally interpret "011" as octal
array[0]*1 + array[1]*1;
For more details on why parseInt is probably bad, see this answer.
You can also remove the superfluous default section of your case statement. However, I suspect that your desired "improvement" was making fewer lines. Given that =-*/ are operators in JavaScript (and not methods), I cannot think of any way to avoid having four calculations (i.e. a switch or if/else if).
Whereas in Ruby you could, for example, use array[0].send(action,array[1]) to cover all four cases ;)

Can I use a case/switch statement with two variables?

I am a newbie when it comes to JavaScript and it was my understanding that using one SWITCH/CASE statements is faster than a whole bunch of IF statements.
However, I want to use a SWITCH/CASE statement with two variables.
My web app has two sliders, each of which have five states. I want the behavior to be based on the states of these two variables. Obviously that is a whole heck of a lot of IF/THEN statements.
One way I thought about doing it was concatenating the two variables into one and then I could SWITCH/CASE that.
Is there a better way of accomplishing a SWITCH/CASE using two variables ?
Thanks !
Yes you can also do:
switch (true) {
case (var1 === true && var2 === true) :
//do something
break;
case (var1 === false && var2 === false) :
//do something
break;
default:
}
This will always execute the switch, pretty much just like if/else but looks cleaner. Just continue checking your variables in the case expressions.
How about a bitwise operator? Instead of strings, you're dealing with "enums", which looks more "elegant."
// Declare slider's state "enum"
var SliderOne = {
A: 1,
B: 2,
C: 4,
D: 8,
E: 16
};
var SliderTwo = {
A: 32,
B: 64,
C: 128,
D: 256,
E: 512
};
// Set state
var s1 = SliderOne.A,
s2 = SliderTwo.B;
// Switch state
switch (s1 | s2) {
case SliderOne.A | SliderTwo.A :
case SliderOne.A | SliderTwo.C :
// Logic when State #1 is A, and State #2 is either A or C
break;
case SliderOne.B | SliderTwo.C :
// Logic when State #1 is B, and State #2 is C
break;
case SliderOne.E | SliderTwo.E :
default:
// Logic when State #1 is E, and State #2 is E or
// none of above match
break;
}
I however agree with others, 25 cases in a switch-case logic is not too pretty, and if-else might, in some cases, "look" better. Anyway.
var var1 = "something";
var var2 = "something_else";
switch(var1 + "|" + var2) {
case "something|something_else":
...
break;
case "something|...":
break;
case "...|...":
break;
}
If you have 5 possibilities for each one you will get 25 cases.
First, JavaScript's switch is no faster than if/else (and sometimes much slower).
Second, the only way to use switch with multiple variables is to combine them into one primitive (string, number, etc) value:
var stateA = "foo";
var stateB = "bar";
switch (stateA + "-" + stateB) {
case "foo-bar": ...
...
}
But, personally, I would rather see a set of if/else statements.
Edit: When all the values are integers, it appears that switch can out-perform if/else in Chrome. See the comments.
I don't believe a switch/case is any faster than a series of if/elseif's. They do the same thing, but if/elseif's you can check multiple variables. You cannot use a switch/case on more than one value.
If the action of each combination is static, you could build a two-dimensional array:
var data = [
[1,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20],
[21,22,23,24,25]
];
The numbers in above example can be anything, such as string, array, etc. Fetching the value is now a one-liner (assuming sliders have a value range of [0,5):
var info = data[firstSliderValue][secondSliderValue];
You could give each position on each slider a different binary value from 1 to 1000000000
and then work with the sum.
Yeah, But not in a normal way. You will have to use switch as closure.
ex:-
function test(input1, input2) {
switch (true) {
case input1 > input2:
console.log(input1 + " is larger than " + input2);
break;
case input1 < input2:
console.log(input2 + " is larger than " + input1);
default:
console.log(input1 + " is equal to " + input2);
}
}
I did it like this:
switch (valueA && valueB) {
case true && false:
console.log(‘valueA is true, valueB is false’)
break;
case ( true || false ) && true:
console.log(‘valueA is either true or false and valueB is true’)
break;
default:
void 0;
}

trouble with SWITCH javascript always executing default case

well i have this trouble and ive been dealing with but i just cant get it to work
i have this function
function getDirections(dir)
{
var img;
switch(dir)
{
case 0:
img+='N.png';
break;
case 1:
img+='NE.png';
break;
case 2:
img+='E.png';
break;
case 3:
img+='SE.png';
break;
case 4:
img+='S.png';
break;
case 5:
img+='SO.png';
break;
case 6:
img+='O.png';
break;
case 7:
img+='NO.png';
break;
default:
alert('enetered default but direction='+dir);
}
return img;
}
quite simple right? now i have this interval set to 5000 ms to call getDirections(variable), the function works well the first time its called but after that , it always enter in the default clause and it also alerts the 'entered default but direction=dirvalue' , i mean even if dir is a value between 0-7 it will always enter to default: but it would alert the value so it was supossed to enter to one of the cases.
i made the same using else if and it worked so i dont know what its wrong with SWITCH
if(dir==0){img+='N.png';}
else if(dir==1){img+='NE.png';}
else if(dir==2){img+='E.png';}
else if(dir==3){img+='SE.png';}
else if(dir==4){img+='S.png';}
else if(dir==5){img+='SO.png';}
else if(dir==6){img+='O.png';}
else if(dir==7){img+='NO.png';}
That is weird... try to make sure that dir is an int, do this before the switch:
dir = parseInt(dir);
If the alert shows the value correctly it should enter the switch, but still it can "look" correct but be of a different data type. Do the conversion manually to ensure it's an int
I know I'm a bit late to the party, but I thought it might be important for anyone who doesn't understand why the "ifs" worked and the switch didn't. It's likely no one will read this answer, but I found it while searching for something else, so perhaps someone will find this helpful anyway:
Your switch is this:
function getDirections(dir) {
var img;
switch(dir) {
case 0:
img+='N.png';
break;
case 1:
img+='NE.png';
break;
case 2:
img+='E.png';
break;
case 3:
img+='SE.png';
break;
case 4:
img+='S.png';
break;
case 5:
img+='SO.png';
break;
case 6:
img+='O.png';
break;
case 7:
img+='NO.png';
break;
default:
alert('enetered default but direction='+dir);
}
return img;
}
This is not the same as a series of double equals (==) but a series of triple equals (===). It would be equivalent to:
if (dir === 0) {
img+='N.png';
} else if (dir === 1) {
img+='NE.png';
} else if (dir === 2) {
img+='E.png';
} else if (dir === 3) {
img+='SE.png';
} else if (dir === 4) {
img+='S.png';
} else if (dir === 5) {
img+='SO.png';
} else if (dir === 6) {
img+='O.png';
} else if (dir === 7) {
img+='NO.png';
} else {
alert('enetered default but direction='+dir);
}
In the world of "==", the integer 2 IS the same as the string "2", but not in the land of "===".
I'd guess that for some reason dir is being passed in as a string. Try changing case 1: to case '1':
Using an array instead of a chain of if/else blocks or a giant switch statement will be faster, more flexible and less error-prone. Also, you wouldn't have to worry if dir is a number or a string. Instead of:
if(dir==0){img+='N.png';}
else if(dir==1){img+='NE.png';}
else if(dir==2){img+='E.png';}
else if(dir==3){img+='SE.png';}
else if(dir==4){img+='S.png';}
else if(dir==5){img+='SO.png';}
else if(dir==6){img+='O.png';}
else if(dir==7){img+='NO.png';}
you can store the file names in an array:
var images = [
'N.png', 'NE.png', 'E.png', 'SE.png', 'S.png', 'SO.png', 'O.png', 'NO.png'
];
or arguably more readable:
var images = "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
and then use just:
img = images[dir];
Full implementation of getDirections using an array would be:
var images = "N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
function getDirections(dir) {
var img = images[dir];
if (!img) {
alert("something");
}
return img;
}
Does it work for you?
If images is used only in that one function then you may want to store it as a property of the function to avoid your namespace pollution like this:
function getDirections(dir) {
var img = getDirections.images[dir];
if (!img) {
alert("something");
}
return img;
}
getDirections.images =
"N.png NE.png E.png SE.png S.png SO.png O.png NO.png".split(' ');
or use a closure.
Hard to explain why, but the default: case also need a break; statement after it like all the other cases.
I just ran the code in FireFox/FireBug and called the function this way
getDirections(0);
getDirections('1');
getDirections("2");
The first one does it correctly and the next two enter default.
They are strings and not integer which is what the cases are looking for.
I added
case "2":
img+='NO2.png';
break;
and then only the middle one entered the default. Obviously there is an issue with the way you are calling the function. It is likely passing a string.
I also used your if-else block (added an else{alert(dir);} and that returned the correct value for each call.
Javascript can do on the fly conversion (I think there's a better word for that) between strings and ints (and others). This is occuring when you do the comparrison using ==. If you change the comparison in the ifs to === you get the same behavior as with the switch block.
I pasted your code into an HTML file and ran it with the following buttons:
<button onclick="alert(getDirections(2))">Switch / Int</button>
<button onclick="alert(getDirections('2'))">Switch / String</button>
<button onclick="alert(getDirections2(2))">If-Else / Int</button>
<button onclick="alert(getDirections2('2'))">If-Else / String</button>
When calling the switch-version with a plain 2, it works as expected. Calling it with '2' makes it drop through to the default line. The if-else version works as expected in both cases. So the issue is probably that switch doesn't do an implicit conversion and == does.

Categories

Resources