How can i check two variables in a switch-case statement? - javascript

The question is something like this.
You are given a cubic dice with 6 faces. All the individual faces have a number printed on them. The numbers are in the range of 1 to 6, like any ordinary dice. You will be provided with a face of this cube, your task is to guess the number on the opposite face of the cube.
Ex:
Input:
N = 6
Output:
1
Explanation:
For dice facing number 6 opposite face
will have the number 1.
I did it using a normal switch-case by checking all six faces and returning the respective die face number value, which passed my test cases. However, I need to simplify the code. Is it possible for me to do so?
oppositeFaceOfDice(N) {
//code here
switch(N){
case 1:return 6;
break;
case 6:return 1;
break;
case 2:return 5;
break;
case 5:return 2;
break;
case 3:return 4;
break;
case 4:return 3;
break;
default: return -1;
}
}
oppositeFaceOfDice(N) {
switch(N){
case 1||6 : return 6?1:6;
break;
case 2||5: return 2?5:2;
break;
case 3||4: return 4?3:4;
break;
}
}

Use an object literal instead of a switch statement:
function oppositeFaceOfDice(N) {
return {1: 6, 2: 5, 3: 4, 4: 3, 5: 2, 6: 1}[N];
}
Or use #DavidThomas' suggestion above which is particularly clever:
function oppositeFaceOfDice(N) {
if(N < 1 || N > 6) return undefined;
return 7 - N;
}

Other than rewriting the codes, since in your case, the codes are very clear and easy to debug, you can remove the break statement since it's not necessary.
oppositeFaceOfDice(N) {
//code here
switch(N){
case 1:return 6;
case 6:return 1;
case 2:return 5;
case 5:return 2;
case 3:return 4;
case 4:return 3;
}
}

Related

Card Counting with Switch instead of If Else if. Why do I not need to also use RETURN?

I'm a beginner in javascript, so apologies in advanced if this is a dumb question. So, I've noticed that this question has been asked before, but that question was using IF ELSE statements. I'm trying to do it with SWITCH instead.
What i wanted to know is whether i need to also type in RETURN before count++ or count-- inside the SWITCH. I was using a website that provided this question, and my only error was that i used RETURN. The other post used IF ELSE IF and used RETURN.
Can anybody explain why i didn't need to use RETURN?
let count = 0;
function cc(card) {
switch (card){
case 2:
case 3:
case 4:
case 5:
case 6:
count++;
break;
case 7: case 8: case 9:
count;
break;
case 10: case "J": case "Q": case "K": case "A":
return count--;
break;
}
if (count>0){
return count+" Bet";
} else {
return count+" Hold";
}
}
Update
Do not add return to a switch()'s case block
Interrupting the flow gives you no advantage and more than likely error prone code that will not log any runtime errors.
In Example C are three functions:
Function
Description
Icon
A(card)
The original version of cc(card) without the added returns
👍
B(card)
The modified version of cc(card) with returns short circuiting each case
⛔
C(card)
The modified version of B(card) with prefixed operators that fix B(card)
⚠️
switch() is Fragile
A return before the break is a short circuit. Short circuit in programming context is inserting an early termination of a function/method when a condition is meet. I use this technique frequently but never in a switch(). switch() is a very readable yet bulky function if you deviate from how it's normally used it will usually cause a hiccup -- something inaccurate or incorrect and too slight to notice since it's not a runtime error.
Take for instance the line marked with a warning sign ⚠️ in Example A (also abstracted in Figure I)
Figure I
return count--;
break;
So any 10 or face card is short circuited so it never reaches break nor will it reach the last condition that determines whether to bet
or hold which is the whole point of this function. Now if we were to pass an A♤:
Figure II
cc('A');
// returns a 0 / expected -1
Why did it not decrement count? Because it never got the chance to be evaluated due to being short circuited. Originally, all cards went through the switch got it's value then when it reached the last condition, it would be evaluated and it's current values set to 1, 0, or -1. If you have your heart set on using returns before a break, change the counters from post to pre (see Figure III).
Figure III
return ++counter;
When the in/decrement is prefixed to the value, it is evaluated before it's stored so you'll get accurate results. Like I said, there's no point in using the switch() if return is used within it.
Example A is the OP (Original Post)
Example B is a refactor of OP
Example C is a side-by-side comparison between OP with short circuit 👎 and OP without short circuit 👍
Example A
Original Answer
let count = 0;
function cc(card) {
switch (card) {
case 2:
case 3:
case 4:
case 5:
case 6:
count++;
break;
case 7:
case 8:
case 9:
count;
break;
case 10:
case "J":
case "Q":
case "K":
case "A":
return count--; // ⚠️
break;
}
if (count > 0) {
return count + " Bet";
} else {
return count + " Hold";
}
}
console.log(cc('A'));
Example B
More Blackjack Rules Applied
/**
* #desc - Formats output to console
* #param {any} data - Limited like JSON
*/
const msg = data => console.log(JSON.stringify(data));
/**
* #desc - Given an unknown amount of numbers and
* strings that represent a set of 52 playing
* cards, it'll calculate:
* score points[0]
* hint points[1]
* aces points[2]
* #param {array<rest>} cards - One or more numbers and
strings.
* #return {array<number>} An array of 3 numbers
* see #desc
*/
const score = (...cards) => {
let tuple = [...cards].reduce((points, current) => {
points[0] += current === 'A' ? 11 : typeof current == 'string' ? 10 : current;
points[1] += current < 7 ? 1 : current > 9 ? -1 : 0;
return points;
}, [0, 0]);
let aces = [...cards].filter(c => c === 'A').length;
tuple.push(aces);
return tuple;
}
/**
* #desc - Given an array of 3 numbers, it calculates,
* adjusts, and determines the flow of a
* blackjack game
* #param {array<number>} score - The output of score()
* #return {string} A msg to inform the player of
* current score, a suggestion of what
* to do next, or when the player busts
*/
const hand = score => {
while (score[0] > 21) {
if (score[2] > 0) {
score[2] -= 1;
score[1] += 1;
score[0] -= 10;
} else {
return msg(`${score[0]}, bust!`);
}
}
if (score[0] === 21) {
return msg('BLACKJACK!');
}
let action = score[1] > 0 ? 'make a wager' : 'stand';
return msg(`${score[0]}, you should ${action}.`);
}
hand(score('A', 4, 10));
hand(score(2, 9, 3, 9));
hand(score(10, 'K'));
hand(score(6, 2));
hand(score('A', 'K'));
Example C
Wrong vs. Right
let count = 0;
let countA = 0;
let countB = 0;
let countC = 0;
function A(card) {
console.info('Test ' + count + ' ============================');
console.log('------------A👍-------------');
console.log('inA: ' + countA + ' Card: ' + card);
switch (card) {
case 2:
case 3:
case 4:
case 5:
case 6:
countA++; // 👍
console.log('A++: ' + countA);
break;
case 7:
case 8:
case 9:
countA; // 👍
console.log('A: ' + countA);
break;
case 10:
case "J":
case "Q":
case "K":
case "A":
countA--; // 👍
console.log('A--: ' + countA);
break;
}
if (countA > 0) {
return countA + " Bet";
} else {
return countA + " Hold";
}
}
function B(card) {
console.log('------------B⛔-------------')
console.log('inB: ' + countB + ' Card: ' + card);
switch (card) {
case 2:
case 3:
case 4:
case 5:
case 6:
console.log('B++: ' + countB);
return countB++; // ⛔
break;
case 7:
case 8:
case 9:
console.log('B: ' + countB);
return countB; // ⛔
break;
case 10:
case "J":
case "Q":
case "K":
case "A":
console.log('B--: ' + countB);
return countB--; // ⛔
break;
}
if (countB > 0) {
return countB + " Bet";
} else {
return countB + " Hold";
}
}
function C(card) {
console.log('------------C⚠️-------------');
console.log('inC: ' + countC + ' Card: ' + card);
switch (card) {
case 2:
case 3:
case 4:
case 5:
case 6:
console.log('--C: ' + countC + '⚠️');
return ++countC; // ⚠️
break;
case 7:
case 8:
case 9:
console.log('C: ' + countC);
return countC; // ⚠️
break;
case 10:
case "J":
case "Q":
case "K":
case "A":
console.log('--C: ' + countC + '⚠️');
return --countC; // ⚠️
break;
}
if (countC > 0) {
return countC + " Bet";
} else {
return countC + " Hold";
}
}
document.forms.bj.oninput = hit;
document.forms.bj.onreset = reset;
function hit(e) {
const IO = this.elements;
let draw = IO.draw.value;
let card = isNaN(draw) ? draw : +draw;
let a = A(card);
let b = B(card);
let c = C(card);
IO.A.value = a;
IO.B.value = b;
IO.C.value = c;
count++;
}
function reset(e) {
count = 0;
countA = 0;
countB = 0;
countC = 0;
}
html {
font: 300 1.5ch/1.2 'Segoe UI';
}
#table {
display: flex;
max-width: max-content;
}
legend {
font-size: 1.25rem;
}
select,
input {
display: inline-flex;
font: inherit;
}
label,
select,
input,
output {
display: block;
margin-bottom: 0.5rem;
}
output {
font-weight: 900;
text-align: center;
}
#B {
color: red;
}
.as-console-row::after {
width: 0;
font-size: 0;
}
.as-console-row-code {
width: 100%;
word-break: break-word;
}
.as-console-wrapper {
min-height: 100% !important;
max-width: 50%;
margin-left: 50%;
}
<form id='bj'>
<fieldset id='table'>
<legend>Blackjack</legend>
<label class='IN'>
<select id='draw'>
<option selected>Draw</option>
<option value='2'>2</option>
<option value='3'>3</option>
<option value='4'>4</option>
<option value='5'>5</option>
<option value='6'>6</option>
<option value='7'>7</option>
<option value='8'>8</option>
<option value='9'>9</option>
<option value='10'>10</option>
<option value='J'>Jack</option>
<option value='Q'>Queen</option>
<option value='K'>King</option>
<option value='A'>Ace</option>
</select>
<input type='reset'>
</label>
<fieldset>
<label>
Original: 👍<br>
<output id='A'> </output>
</label>
<label>
Short Circuits: ⛔<br>
<output id='B'> </output>
</label>
<label>
Short Circuits<br>Prefixed Operators: ⚠️<br>
<output id='C'> </output>
</label>
</fieldset>
</fieldset>
</form>

Problem with a string: how to do a rating with javascript

I can't implement the function tipPercentage that takes the argument rating as a string and return the values:
terrible or poor, then returns 3
good or great, then returns 10
excellent, returns 20
none of the above, returns 0
the input format for custom testing must be that the first line contains a integer, n, denoting the value of rating
HELP FOR A BEGGINNER!!!
You can use a switch statement to do this relatively easily, we check the input rating, then return the relevant tip percentage.
If we don't have a tip percentage for the rating, we'll fall back to the default condition, and return 0.
One could also use a map, though a switch statement is probably more flexible.
// Takes rating as a string and return the tip percentage as an integer.
function tipPercentage(rating) {
switch ((rating + "").toLowerCase()) {
case "terrible":
case "poor":
return 3;
case "good":
case "great":
return 10;
case "excellent":
return 20;
default:
return 0;
}
}
let ratings = ["excellent", "good", "great", "poor", "terrible", "meh", null];
for(let rating of ratings) {
console.log(`tipPercentage(${rating}):`, tipPercentage(rating))
}
function tipPercentage(rating) {
switch(rating) {
case "terrible":
case "poor":
return 3; break;
case "good":
case "great":
return 10; break;
case "excellent":
return 20; break;
default:
return 0;
}
}
Instead of a switch statement you could simply use an object:
const tipPercentage = {
'excellent': 20,
'good': 10,
'great': 10,
'terrible': 3,
'poor': 3,
}
const myRatings = [
"excellent",
"good",
"great",
"terrible",
"whatever",
undefined
];
for (let rating of myRatings) {
// Tip percentage, or 0 if it doesn't exist
console.log(rating, tipPercentage[rating] || 0)
}

How to find maximum between two numbers in javascript using switch case?

I am trying to run with this code block but it does not work
Switch (num1>num2) {
case 0:
document.write(num2);
break;
case 1:
document.write(num1);
break;
}
You could use something simple as Math.max(5, 10);
const numOne = 5;
const numTwo = 10;
console.log(`Bigger number is: ${Math.max(numOne, numTwo)}`);
Or if you absolutely 'have to' use switch statement, you can try something like this:
const numOne = 5;
const numTwo = 10;
switch(true) {
case (numOne > numTwo):
console.log(`Bigger number is ${numOne}`);
break;
case (numOne < numTwo):
console.log(`Bigger number is ${numTwo}`);
break;
case (numOne === numTwo):
console.log(`${numOne} is equal to ${numTwo}`);
break;
default: console.log(false, '-> Something went wrong');
}
Logical operations return boolean on Javascript.
document.write writes HTML expressions or JavaScript code to a document, console.log prints the result on the browser console.
switch (num1>num2) {
case true:
console.log(num1);
break;
case false:
console.log(num2);
break;
}
switch (with a lower case s) uses strict comparison === so the value of a boolean like 11 > 10 will never === 0 or 1.
You need to test for the boolean if you want to do it this way:
let num1 = 10
let num2 = 20
switch (num1>num2) {
case false:
console.log(num2);
break;
case true:
console.log(num1);
break;
}
If for some reason you were given numbers you could explicitly cast them to booleans with something like case !!0: but that starts to get a little hard on the eyes.
If your goal is to find the max of two numbers, Math.max(num1, num2) is hard to beat for readability.
You would just use the greater than / less than inside of the switch statement.
var x = 10;
var y = 20;
switch(true) {
case (x > y):
console.log(x);
break;
case ( y > x):
console.log(y);
break;
}

javascript for loop to use a function for several objects

I am working on a game that has three dice cubes that show random faces upon clicking a button.
Images are by css image sprite. If the random number gets 1 the dice cube is assigned to a css class that has its image sprite.
function diceroll (){
var randomnumber = Math.floor(Math.random() * (6 - 1 + 1)) + 1;
switch (randomnumber) {
case 1:
document.getElementById("dice1").setAttribute("class", "face1");
break;
case 2:
document.getElementById("dice1").setAttribute("class", "face2");
break;
case 3:
document.getElementById("dice1").setAttribute("class", "face3");
break;
case 4:
document.getElementById("dice1").setAttribute("class", "face4");
break;
case 5:
document.getElementById("dice1").setAttribute("class", "face5");
break;
case 6:
document.getElementById("dice1").setAttribute("class", "face6");
break;
}
}
I have a separate button, when clicked it should run the above diceroll function to the three divs with ids dice1, dice2 and dice3.
I want to use
function gotoloop (){
for (i = 0; i < 2; i++) {
// the code that affects dice(n) and n=1 and then diceroll function
// affects dice1 n+1
}
}
I researched and could not find a way to implement the code for the last commented two lines. Please let me know if my approach is correct and help me with the code.
If I understood your question correcly, you want something like this:
function diceroll (diceId){
var randomnumber = Math.floor(Math.random() * 6) + 1;
switch (randomnumber) {
case 1: document.getElementById(diceId).setAttribute("class", "face1"); break;
case 2: document.getElementById(diceId).setAttribute("class", "face2"); break;
case 3: document.getElementById(diceId).setAttribute("class", "face3"); break;
case 4: document.getElementById(diceId).setAttribute("class", "face4"); break;
case 5: document.getElementById(diceId).setAttribute("class", "face5"); break;
case 6: document.getElementById(diceId).setAttribute("class", "face6"); break;
}
}
function gotoloop (){
// Start loop at i=1 because the first ID is dice1
for (var i = 1; i <= 3; i++) {
// the code that affects dice(n) and n=1 and then diceroll function affects dice1
// n+1
diceroll("dice" + i);
}
}
Or as per Marc Baumbach's comment, you could write:
function diceroll (diceId){
var randomnumber = Math.floor(Math.random() * 6) + 1;
document.getElementById(diceId).setAttribute("class", "face" + randomnumber);
}

Javascript: for, switch and Math.rand in one and not working right

I'm currently working on an idle game and have encountered a problem.
I'm trying to create a function that will lessen the value of 1 of 6 variables (each represents a type of worker) a number of times. However, if one of these 6 variables is at 0, I need it to pick one of the other 5, and I can't get that to work.
With fiddling around, I have gotten this:
function killWorker(amount){
var job;
for (var i=0;i<amount;i++){
job = Math.floor((Math.random()*6)+1);
switch (job){
case 1:
if(unass_workers>0){
unass_workers -= 1;
}else{
i-=1;
}
case 2:
if(farm_workers>0){
farm_workers -= 1;
}else{
i-=1;
}
break;
case 3:
if(tree_workers>0){
tree_workers -= 1;
}else{
i-=1;
}
break;
case 4:
if(metMine_workers>0){
metMine_workers -= 1;
}else{
i-=1;
}
break;
case 5:
if(golMine_workers>0){
golMine_workers -= 1;
}else{
i-=1;
}
break;
case 6:
if(paper_workers>0){
paper_workers -= 1;
}else{
i-=1;
}
break;
default:
console.log("error: killWorker() didn't work properly");
break;
}
}
}
This worked when I did low amounts, but when I increased the amount higher the whole thing crashed. I'd be quite happy to drastically change the function if it would work better, and I am using jquery too if that could help get an easier or more effective solution.
As i said, what probably happens is that amount is larger than the sum of X_workers, resulting in an infinite loop.
A fix that keeps your logic correct would be to check that enough workers can be killed:
function killWorker(amount){
if (amount < unass_workers + farm_workers + ...) return "Genocide";
var job;
for (var i=0;i<amount;i++){
...
}
A better way to organize your data structures could be:
var workerNames = [ 'unass', 'farm', 'tree', 'metMine', 'golMine', 'paper' ];
var workers = {
unass : 23,
farm : 45,
tree : 6,
metMine : 99,
golMine : 3,
paper: 43
}
function getRandomLiveJobName() {
var jobs = workerNames.filter(function(name) {
return workers[name] > 0;
});
return jobs[Math.floor(Math.random()*jobs.length)];
}
function killWorkers(amount) {
for (;amount--;) {
var job = getRandomLiveJobName();
if (!job) return "Genocide";
workers[job]--;
}
}
killWorkers(150);
console.log(workers); // { farm: 0, golMine: 0, metMine: 64, paper: 5, tree: 0, unass: 0 }
Of course it could be optimized by not creating a new array each time you need a random live job by updating a single array inside killWorkers, but i think it's easier to read now.

Categories

Resources