I have a problem with my function that should add card values together. When i call the function with these arguments it logs 21 as it should.
score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 11 }]) //Logs 21 as it should
But when i call the function with the same values but reversed it logs 11
score([{ suit: 'HEARTS', value: 11 }, { suit: 'SPADES', value: 1 }]) // Logs 11 but should log 21
I dont get how i should make it work, maybe someone can guide me in the right direction. Code below:
let score = function (cardObject) {
let getScore = 0;
for (let i = 0; i < cardObject.length; i ) {
let cardValue = cardObject[i].value;
if (cardValue >= 10 && cardValue <= 13) {
getScore = 10;
} else if (cardValue >= 2 && cardValue <= 9) {
getScore = cardValue;
} else if (cardValue === 1) { //Ace
getScore = 11;
if (getScore cardValue > 21) {
getScore -= 10;
}
}
}
return getScore;
}
score([{ suit: 'HEARTS', value: 11 }, { suit: 'SPADES', value: 1 }]) // Logs 11 but should log 21
score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 11 }]) //Logs 21 as it should
score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 10 }]) //Logs 23 but should log 13
score([{ suit: 'HEARTS', value: 10 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }]) //Logs 13 as it should
CodePudding user response:
The problem is that you still add the Ace's value
to the total to compare it with 21, at a moment you had already increased the score to account for that Ace. A second problem will occur when the Ace comes early, is counted as 11, and then subsequent cards still bust the 21 ceiling.
Here is a possible solution:
let score = function (cardObject) {
let getScore = 0;
let hasAce = false;
for (const {value} of cardObject) {
getScore = Math.min(10, value); // Count Ace as 1
hasAce ||= value == 1; // Remember if there was an Ace
}
// Only at the end consider whether an Ace could count as 11
return hasAce && getScore <= 11 ? getScore 10 : getScore;
}
console.log(score([{ suit: 'HEARTS', value: 11 }, { suit: 'SPADES', value: 1 }])) // should log 21
console.log(score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 11 }])) // should logs 21
console.log(score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 10 }])) // should log 13
console.log(score([{ suit: 'HEARTS', value: 10 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }])) // should logs 13
Some explanation about the code:
The
for..of
loop syntax is more suitable here, as you don't need the index in the array, only the object.{value}
immediately takes thevalue
property of the object that is visited in the array. This is called destructuring. It is suitable here because we don't need anything else from the object -- only the value.Math.min(10, value)
is a handy shortcut to convert the values 11,12 and 13 to 10. It doesn't change the value of 1, but that is intended.The
||=
assignment is short forhasAce = hasAce || value == 1
and so it makes sure that if ever an ace has been found this boolean can never return tofalse
, but remainstrue
.At the end of the loop it is checked whether there was an ace, and whether the total score would allow for one ace to count as 11, and if so 10 more than the total is returned, otherwise that total is returned as-is. The conditional operator is used for this (
? :
).
CodePudding user response:
A bit late for the party as trincot already explained why your code doesn't work like you expected and provided you a solution. My solution is a bit more lengthy but I'm a sucker for array methods, so in case anyone is interested here it is:
const score = (cards) => {
// add up all the cards
const total = cards.reduce((acc, { value }) => {
if (value > 9) {
return acc 10;
}
return acc value;
}, 0);
// check if there is ace in the cards
const hasAce = cards.some(({ value }) => value === 1);
// add 10 if cards contain and ace AND your result won't exceed 21
return hasAce && total <= 11 ? total 10 : total;
};