I'm trying to develop a simplified poker game through Javascript. I've listed all possible card combinations a given player might have in its hand ordered by its value, like this:
switch(sortedHand)
{
//Pair
case [1,1,4,3,2]: sortedHand.push(1,"Pair"); break;
case [1,1,5,3,2]: sortedHand.push(2,"Pair"); break;
case [1,1,5,4,2]: sortedHand.push(3,"Pair"); break;
case [1,1,5,4,3]: sortedHand.push(4,"Pair"); break;
case [1,1,6,3,2]: sortedHand.push(5,"Pair"); break;
case [1,1,6,4,2]: sortedHand.push(6,"Pair"); break;
case [1,1,6,4,3]: sortedHand.push(7,"Pair"); break;
case [1,1,6,5,2]: sortedHand.push(8,"Pair"); break;
case [1,1,6,5,3]: sortedHand.push(9,"Pair"); break;
case [1,1,6,5,4]: sortedHand.push(10,"Pair"); break;
Even though the "sortedHand" array stores values succesfully (as I've seen through console.log), the switch() statement always returns the default case, and everyone gets an straight flush. I fear this is a matter of the literal approach I've used to declare possible array values to be compared with the whole of "sortedHand", but I don't know any better. Is it even possible to use switch() in such a manner?
You can try switching on a textual representation of the array.
switch(sortedHand.join(' '))
{
//Pair
case '1 1 4 3 2': sortedHand.push(1,"Pair"); break;
case '1 1 5 3 2': sortedHand.push(2,"Pair"); break;
case '1 1 5 4 2': sortedHand.push(3,"Pair"); break;
case '1 1 5 4 3': sortedHand.push(4,"Pair"); break;
// etc.
}
As an alternative to specifying every case directly, perhaps build a function dispatch table using an object and get rid of the switch entirely.
var dispatch = {};
// Build the table however you'd like, for your application
for (var i = 0; i < 10; i++) {
(function(i) {
var hand = ...; // Add your hand logic here
dispatch[hand] = function() { sortedHand.push(i, "Pair"); };
})(i);
}
// Execute your routine
dispatch[sortedHand.join(' ')]();
the switch() statement always returns the default case
That's because the comparison doesn't check the array contents, but the array object itself. Objects are considered equal by their identity, so nothing will be equal to an object instantiated by a literal.
Is it even possible to use switch() in such a manner?
Yes, one can use objects in switch statements, but you would have to use references in the cases. Not applicable to your problem.
In your case, I'd suggest a stringification:
switch(sortedHand.join())
{
//Pair
case "1,1,4,3,2": sortedHand.push(1,"Pair"); break;
case "1,1,5,3,2": sortedHand.push(2,"Pair"); break;
case "1,1,5,4,2": sortedHand.push(3,"Pair"); break;
case "1,1,5,4,3": sortedHand.push(4,"Pair"); break;
case "1,1,6,3,2": sortedHand.push(5,"Pair"); break;
case "1,1,6,4,2": sortedHand.push(6,"Pair"); break;
case "1,1,6,4,3": sortedHand.push(7,"Pair"); break;
case "1,1,6,5,2": sortedHand.push(8,"Pair"); break;
case "1,1,6,5,3": sortedHand.push(9,"Pair"); break;
case "1,1,6,5,4": sortedHand.push(10,"Pair"); break;
but I guess there's an even better, arithmetic solution to detect the patterns you're after. That would be shorter and faster, but I'm not sure what exactly this snippet is supposed to do.
a faster, potentially reusable, and more flexible way of doing it is to use an object instead of case:
var ok= {
'1 1 4 3 2':1,
'1 1 5 3 2':2,
'1 1 5 4 2':3,
'1 1 5 4 3':4
}[ sortedHand.join(' ') ] ;
if(ok){ sortedHand.push( ok ,"Pair"); }
objects work great when one output is hinged on one input. if you need to do five things in each case, then you have to use case, but if you just need X to turn into Y, (a 1:1), Look Up Tables in the shape of Objects are ideal.
i imagine a RegExp can work here, i used them on a connect4 game to identify 4 in a row, but the above logic table should work as well or better than what you describe.
That will not quite work as you have it, but you can use sortedHand.join(',') and compare it with [1,1,1,2,5].join(',') which will compare the two arrays and should be true if their contents were the exact same (Be careful with numbers typed as strings!)
To be fair, though, I can't imagine why you would design your logic like that. Even a simple card game has hundreds of thousands of possible hands. You might do better using underscore.js's collection managing functions as it will be simpler, and just a better practice.
There are 1274 possible combinations of 5 cards in a regular deck. Listing them all out in a switch statement is completely ridiculous. Why not just have a function count any duplicates to check for 2,3,4-of-a-kinds and then check for straights? (Your array doesn't show suit so I'm assuming you are leaving it out).
But if you really want to do it that way, you could use a string. Strings work with switches, and you can even use them like arrays. e.g. "123"[0] == '1'. You can change them back and forth user functions like parseInt.
Since no one suggested this, use a for loop and count the number of cards with exactly the given value. Having such a function you can call 'cardCount = count(sortedHand, cardNumber)'. And of cause looping through all possible card-numbers will give you the hands.
Since a given player can only have 1x2, 2x2, 1x3, 1x3+1x2, 1x4 or straights/streets, you can return an array of all hits being arrays/objects stating the count and the cardNumber involved. So [{2, 5}, {3, 6}] for a full house.
Related
This question already has answers here:
Can I use a case/switch statement with two variables?
(9 answers)
Closed 2 years ago.
I'm coding a Discord bot with the javascript API, and I have an idea that I'm not sure would work, but would be a massive optimization.
Right now i'm adding a Rock Paper Scissors minigame into my bot, and I need it comparing the users guess (A sent emoji in the chat) to its own guess (A random number between 0-2 to represent the emoji of choice), and for now i have a line of if else doing that.
e.g, instead of
if(botGuess == 0 && msg.content.includes("/*unicode fist*/"){
//tie
}
I put it in a Switch statement... kinda like this??
switch(botGuess, msg){
case botGuess = 0, msg.content.includes("/*unicode fist*/"):
//tie
break;
}
I've just been wondering for a while, is this possible, and if so am I doing it right? As of now I have alot of if else statements, and switching to an advanced switch statement like the one I thought of above would give me ease of mind.
EDIT: I've found a workaround thanks to Simperfy. I'm concatenating both variables into a string and treating them both as one variable.
e.g.
var guesses = botGuess + "|" + msg.content;
switch(guesses){
case guesses.contains("0" && "/*unicode_fist*/"):
//tie
break;
}
A switch statement can only support a single unit of data. What you could do however, is concatenate two units of data into one. In javascript you can do this by basic multiplication:
switch (i + 1000 * j)
{
case 1002: ... // i = 2, j = 1
case 3004: ... // i = 4, j = 3
}
Note that this requires that i < 1000 and no negative numbers etc. Generally speaking a pattern like this isn't recommended. It is also simply not a clean style in any way, and I find it hard to imagine a situation where you would ever need something like this. I suggest editing your question to specify your scenario.
I have a code to generate math problems with random numbers. I am using switch statement to choose which task should be generated.
function genTask(taskid) {
switch (taskid) {
case 1:
// generate some numbers
return numbers;
break;
case 2:
// generate some numbers
return numbers;
break;
// ...
}
}
I think there may be some performance issues when I add 150+ cases. Does this code go trough every case? Wouldnt it be faster if there are separate functions for every task?
function task1() {
// generate some numbers
return numbers;
}
function task2() {
// ...
}
function genTask(taskid) {
switch (taskid) {
case 1:
return task1();
break;
case 2:
return task2();
break;
// ...
}
}
Is there a faster way to do this?
First of all, you need to know where you need to use if/else or switch/case.
When you need to check 2 to 3 conditions then you can use if/elseif/else
When you need to check 5 or above then definitely use switch/case
And based on speed switch/case is faster then if/else
Let's get back to the original point,
In your case, you have 2 choices
Write all code in one switch case.
Make functions in chunk and call-in switch case.
I suggest you go with the second choice because switch case also a faster way of execution compared to other conditional checks, But when you make different functions then you can easily modify it and debug it which more help in development, and performance not compromised in that case.
One more approach is you can use a object lookup
function task1() {
// generate some numbers
return numbers;
}
function task2() {
// some task
}
const taskMap = { 1: task1, 2: task2 };
function genTask(taskid, defaultVal) {
return (taskMap[taskid] && taskMap[taskid]()) || defaultVal;
}
This will be simple object lookup, though in terms of performance it might be slower than switch case but it increases resuability and readability of the code.
In general, I think the performance of "array" is better than "if/else" or "switch". See the reference below. In your specific case, if you comparing if/else to switch, then switch is better.
Using functions will not affect the performance ( I think ), but it is better and preferable as the code will be cleaner and readable.
Reference : https://www.oreilly.com/library/view/high-performance-javascript/9781449382308/ch04.html
Below code is just initializing two variables, depending on cloudType passed, which can be assigned by either of approaches. In JavaScript less number of lines of code is recommended so I like the second approach also it removes duplication.
Approach one gives me flexibility to add operations in specific case if required in future where as 2nd approach is saving me good amount of bytes also helping me reduce duplication.
switch (cloudType) {
case "aws":
value = this._resetMessageDefaultValues.aws
resetText = this._messages.current.aws
break;
case "private":
value = this._resetMessageDefaultValues.private;
resetText = this._messages.current.private
break;
case "azure":
value = this._resetMessageDefaultValues.azure;
resetText = this._messages.current.azure
break;
}
Or
value = this._resetMessageDefaultValues[cloudType];
resetText = this._messages.current[cloudType]
By all means, I prefer the second code.
If your cloudType variable has a one-to-one mapping to properties of those two other objects, why not make it clear? This also avoids duplicate code.
To be safe, add these checks to your code:
value = this._resetMessageDefaultValues[cloudType];
resetText = this._messages.current[cloudType]
if (typeof value == "undefined" || typeof resetText == "undefined") {
// throw some error
}
This way you'll know that when a new cloudType is added to your system, you should add relevant properties to those other objects.
Amplifying #Mohammad's answer
The second code is already industry standard of referring to object properties through its keys via brackets foo['bar']. If you want to add extra operations, just put in the switch case block below. Still saving you a few bytes than the first solution you wrote
value = this._resetMessageDefaultValues[cloudType];
resetText = this._messages.current[cloudType];
switch (cloudType) {
case "aws": break;
case "private": break;
case "azure": break;
}
Considering the keys truly matches directly to the cloudType variable, and even if it isn't, I advise matching it.
I want to ask about switch case statement in javascript.
switch(ch){
case 0:
//do something, if condition match ,so go to case 2 and 3 (no need to go case 1)
//if not match, go to case 1, 2, and 3
break;
case 1:
//..
break;
case 2:
//..
break
case 3:
//...
}
In my code has 4 cases . There is a condition in case 0 that will skip case 1 and go to case 2. How can I do that?
The switch statement is an alternative to long if else statements (See the docs here). In your case, I believe that you should use the regular if statements.
// check if it passes case1
if (condition === case1) {
// check if it passes case1
if (condition === case2) {
// check if it passes case1
if (condition === case3) {
// do something here...
}
}
}
You may also use ternary operator, although it might be a bit hard to read as you add more conditions.
i think if else statement better suit your requirement. if you still want to do it in switch here's example :) :
var sw = function(cs){
switch(cs){
case 1:
console.log("case 1 !!!");
sw(3);
break;
case 2:
console.log("case 2 !!!");
break;
case 3:
console.log("case 3 !!!");
break;
}
};
sw(1);
I believe this's what you are looking for:
function Switcher(choice){
switch(choice){
case 1: console.log(1);;
case 4: console.log(4); break;
case 2: console.log(2); break;
case 3: console.log(3); break;
}
}
and then call Switcher(1) and see the O/P
I was looking at some logic related to switches in JavaScript today, the code I was looking at used a series of if and else statements however there were a bunch of shared logic cases which could be consolidated.
Additionally if and else statements are not exactly equal to switch statements because the runtime may implement them with jump tables making the order of execution faster than if and else.
Because you can only continue iteration patterns in ECMAScript you can hack up a solution which looks like jumping by encapsulating the logic in a fake loop like so:
(function(){
//In some function use this code
var test = 2;
Switch: while(true) switch(test){
case 2: test = 1; continue Switch;
case 1: test = 0; continue Switch;
default:alert(test);return;
};
//End code example
})();
The condition for while(true) can be changed to use another variable for state if you need to.
This gets the code as close to using jump tables as you can in other languages and a similar pattern can implement things like goto or duffs device
See also How can I use goto in Javascript?
Or Porting duff's device from C to JavaScript
Or this GIST https://gist.github.com/shibukawa/315765020c34f4543665
I have a while loop and my requirement is to pass data to a variable based on first three characters of a string and another data into another variable based on last three characters of a string. So, I used two switch statements in a while loop and it looks like below
while (condition) {
switch (firstThreeChars) {
case 'a':
do this;
break;
case 'b':
do this...;
break;
}
switch (lastThreeChars) {
case 'x':
do this;
break;
case 'y':
do this...;
break;
}
}
I realized that code never reaches second switch because break in first switch-case releases control to while statement. Is there a way I can have multiple switch-case statements in a while loop? Perhaps something alternative to break statement..
That's incorrect; the break keywords terminate the switch statements, not the while. The problem here is that you're comparing your strings to single characters, so you're likely never matching any of the case statements.