zuccinni
zuccinni

Reputation: 63

Basic JavaScript: Counting Cards - Card Counting Function with Strings

The card function has been explained multiple times, and I understand it. For those who do not know it: my function receives a card parameter, which can be a number or a string. I then increment or decrement the global count variable according to the card's value 2,3,4,5,6 increments, 7,8,9 keeps it at 0, while 10, J, Q, K, A decrements it. My function then returns a string with the current count and the string "Bet" if the count is positive, or "Hold" if it is negative.

So I understand how the function is done, and FreeCodeCamp accepted my solution as technically it meets their conditions. But have a question regarding this function:

var count = 0;

function cc(card) {
  if (card >= 2 && card <= 6) {
    count++;
  } else if (card >= 7 && card <= 9) {
    count += 0;
  } else {
    count--;
  }

  if (count <= 0) {
    return count + " Hold";
  } else {
    return count + " Bet";
  }
}

console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('A'));

As I can see, the first condition is fairly simple and easy to define, so is the else if. In the third case, there are both numbers and strings involved. Does this not mean that when I put ANY string into cc, it will decrement? As anything that is not between 2 and 6, or 7 and 9, will automatically decrement? Even if the user inputs something that is not a card or is not a value from the list?

I understand that there is a list of predefined card values and names, but nevertheless, is there any better way to condition my statement to make sure that my condition will ONLY run IF the card is either 10, J, Q, K or A, and not any other value?

Upvotes: 1

Views: 2201

Answers (8)

Efa-Iwa Eleng
Efa-Iwa Eleng

Reputation: 1

let count = 0;

function cc(card) {
  switch (card) {
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
      count++;
      break;
    case 10:
    case 'J':
    case 'Q':
    case 'K':
    case 'A':
      count--;
  }
  if (count > 0) {
    return count + " Bet";
  } else {
    return count + " Hold";
  }
}

Upvotes: 0

DanDanWill
DanDanWill

Reputation: 3

My solution, based on what we learned so far. Maybe it isn´t the best, but it also works.

var count = 0;

function cc(card) {
  // Only change code below this line
switch(card){
  case 2:
  case 3:
  case 4:
  case 5:
  case 6:
    count++;
    break
  case 7:
  case 8:
  case 9:
    count = count;
    break
  case 10:
  case 'J':
  case 'Q':
  case 'K':
  case 'A':
    count--;
    break;
}
   if (count <=0) {
    return count + ' Hold';
  }
  else {
    return count + ' Bet'
  }
  // Only change code above this line
}

console.log(cc(2)); 
console.log(cc(3)); 
console.log(cc(7)); 
console.log(cc('K'));
console.log(cc('A'));

Upvotes: 0

Valentin
Valentin

Reputation: 11

My solution for Basic JavaScript: Counting Cards

function cc(card) {
// Only change code below this line
if(card >= 2 && card <= 6) {
 count++;
} else if (card === 10 ||card === 'J' || card === 'Q' || card === 'K' || card === 'A') {
 count = count - 1;
}

if (count > 0) {
 return count + ' Bet';
}
return count + ' Hold';
// Only change code above this line
}

Upvotes: 0

robhirstio
robhirstio

Reputation: 181

You could use a regular expression at the very top of your function to skip all the conditionals and return a handy message if the argument passed in doesn't match a valid card:

// Check if card is valid
var cardRegex = /^(10|[2-9AJQK])$/i;
if (!cardRegex.test(card)) { 
    return "Invalid Card";
}

So, in the context of your code, it would look like:

var count = 0;

function cc(card) {
  
  // Check if card is valid
  var cardRegex = /^(10|[2-9AJQK])$/i;
  if (!cardRegex.test(card)) { 
    return "Invalid Card";
  }
  
  if (card >= 2 && card <= 6) {
    count++;
  } else if (card >= 7 && card <= 9) {
    count += 0;
  } else {
    count--;
  }

  if (count <= 0) {
    return count + " Hold";
  } else {
    return count + " Bet";
  }
}

// Valid inputs
console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('a'));

// Invalid inputs
console.log(cc('e'));
console.log(cc('L'));
console.log(cc(0));

Upvotes: 0

Scott Sauyet
Scott Sauyet

Reputation: 50807

Another possibility is something like the following, which explicitly lists the changes for each card:

const counter = () => {
  let count = 0
  let values = {2: 1,  3:  1,  4:  1,  5:  1,  6:  1,  7: 0,  8: 0, 
                9: 0, 10: -1,  J: -1,  Q: -1,  K: -1,  A: -1}
  
  return (card) => {
    const change = values[card] || 0 // no change if card is, say, 'XYZ' or 'Joker'
    count += change
    return count <= 0 ? 'Hold' : 'Bet'
  }
}

const cc = counter();

console.log(cc(2));
console.log(cc(3));
console.log(cc(7));
console.log(cc('K'));
console.log(cc('A'));

For a list as short as thirteen values, I think this sort of explicit list is cleaner.

This also encapsulates the count variable in a closure. I find that cleaner than a global variable.

Where the comment talks about jokers, you might want some more robust error-handling:

if (!(card in values)) {throw 'Bad card'}
const change = values[card]

Upvotes: 0

zero298
zero298

Reputation: 26909

Define a set of allowed values and check if the value you are given is within that set using .includes(). For example:

var count = 0;

function cc(card) {
  // Only change code below this line

  const up = [2,3,4,5,6];
  const no = [7,8,9];
  const down = [10, "J", "Q", "K", "A"];

  if(up.includes(card))count++;
  if(down.includes(card))count--;

  const str = count > 0 ? "Bet" : "Hold";

  return `${count} ${str}`;

  // Only change code above this line
}

// Add/remove calls to test your function.
// Note: Only the last will display
cc(2); cc(3); cc(7); cc('K'); cc('A');

Bear in mind this is type sensitive.

Upvotes: 0

Stuti Rastogi
Stuti Rastogi

Reputation: 1180

There are a number of ways you could deal with this situation. You could initially parse the input, and say assign 'J' to 11, 'Q' to 12, 'K' to 13 and 'A' to 1 (if you need to distinguish), or just a common number to that category. Everything else is an invalid input and you return immediately/post an error message. Something like:

var count = 0;

function cc(card) {

  if (card == 'J' || card == 'Q' || card == 'K' || card == 'A')
     card = 11;

  if (card >= 2 && card <= 6) {
    count++;
  } else if (card>=7 && card <=9) {
    count+= 0;
  } else if (card >= 10 && card <= 11) {
    count--;               // to keep structure cleaner we use dummy 11 value
  } else
    //error message

  if (count <= 0) {
    return count + " Hold";
  } else {
    return count + " Bet";
  }
}


cc(2); cc(3); cc(7); cc('K'); cc('A');

Also, you need to make sure to handle lower case and upper case values for the picture cards.

Upvotes: 0

Ryan Wilson
Ryan Wilson

Reputation: 10765

You can change your current else, to return and error message or just return immediately in case of the input being a non-valid card, and add another else-if to check for 10 through Ace:

if (card >= 2 && card <= 6) {
    count++;
  } else if (card>=7 && card <=9) {
    count+= 0;
  } else if (card === 10 || card === 'J' || card === 'Q' || card === 'K' || card === 'A'){
    count--;
  }else {
    //Either just return or alert an error message and return
  }

Upvotes: 2

Related Questions