The challenge of combining card values in Black Jack

Having an issue with my function that's meant to add card values together. When I use the function with these arguments, it correctly logs 21.

score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 11 }]) //Logs 21 as it should

However, when I try the function with the same values but in reverse order, it logs 11 instead.

score([{ suit: 'HEARTS', value: 11 }, { suit: 'SPADES', value: 1 }]) // Logs 11 but should log 21

I'm struggling to figure out how to fix this. Any guidance would be greatly appreciated. Here is the code:

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

Answer №1

An issue arises when you mistakenly add the Ace's value to the total before accounting for it properly. This can lead to exceeding 21 due to subsequent cards causing a bust.

One potential solution is as follows:

let score = function (cardObject) {
  let getScore = 0;
  let hasAce = false;

  for (const {value} of cardObject) {
    getScore += Math.min(10, value); // Treating Ace as 1
    hasAce ||= value == 1; // Keeping track of Ace presence
  }
  // Evaluating if an Ace could be counted as 11 only at the end
  return hasAce && getScore <= 11 ? getScore + 10 : getScore;
}

console.log(score([{ suit: 'HEARTS', value: 11 }, { suit: 'SPADES', value: 1 }])) // expects 21

console.log(score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 11 }])) // expects 21

console.log(score([{ suit: 'HEARTS', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 10 }])) // expects 13

console.log(score([{ suit: 'HEARTS', value: 10 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }, { suit: 'SPADES', value: 1 }])) // expects 13

The code breakdown is as follows:

  • Using the for..of loop simplifies iteration without requiring array indices.

  • The {value} syntax extracts the value property directly during object visitation, known as destructuring, making it ideal for this scenario.

  • Math.min(10, value) efficiently handles values above 10 by converting them to 10, leaving 1 unchanged intentionally.

  • The ||= operator ensures that once an ace is found, the flag remains true throughout.

  • Ultimately, the function checks if an Ace was encountered and if adjusting the score for it to count as 11 is permissible, returning the modified total or the original based on these conditions using the conditional operator (? :).

Answer №2

Arriving a bit fashionably late to the discussion, as trincot has already delved into why your code may not be functioning as expected and offered a solution. I tend to gravitate towards using array methods in my solutions, so here's a slightly more verbose approach for those who are curious:

const calculateScore = (cards) => {
  // Calculate total score of all cards
  const totalScore = cards.reduce((acc, { value }) => {
    if (value > 9) {
      return acc + 10;
    } else {
      return acc + value;
    }
  }, 0);

  // Check if there is an ace card in the hand
  const hasAceCard = cards.some(({ value }) => value === 1);

  // Add 10 to the total score if an ace card is present and doing so won't exceed 21
  return hasAceCard && totalScore <= 11 ? totalScore + 10 : totalScore;
};

Answer №3

One effective strategy could involve adding a points property to each object, restricting it within the range of 2 to 11:

{suit: '♠', face: 'ACE', points: 11}

A hand could then be represented as an array of objects that are processed through a function like this:

function score(hand) {
  let ace = 0; // Counting variable for aces 
  // total accumulates sum of points
  // current represents the current card (object)
  return hand.reduce((total, current) => {
    // Increment ace if object.points is 11
    if (current.points === 11) ace++;
    // Adjust total and object's points under certain conditions involving aces
    while (total + current.points > 21 && ace > 0) {
      total = total - 10;
      ace--;
    }
    // Return updated total with added points
    return total + current.points;
  }, 0);
} 

More insights provided in examples above

/* For illustrative purposes */
/* Generates a shuffled array of objects representing cards
   Example: {suit: '♠', face: 'ACE', points: 11}
*/
function deck() {
  const suits = ['♠', '♣', '♥', '♦'];
  const faces = ['TWO', 'THREE', 'FOUR', 'FIVE', 'SIX', 'SEVEN', 'EIGHT', 'NINE', 'TEN', 'JACK', 'QUEEN', 'KING', 'ACE'];
  const points = [2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 11];
  let deck = [];
  for (let s=0; s < suits.length; s++) {
    for (let f=0; f < faces.length; f++) {
      deck.push({suit: suits[s], face: faces[f], points: points[f]});
    }
  }
  return shuffle(deck); // Shuffle deck before returning
}

/* For demonstration purpose */
/* Shuffles an array randomly */
function shuffle(array) {
  let qty = array.length, temp, i;
  while (qty) {
    i = Math.floor(Math.random() * qty--);
    temp = array[qty];
    array[qty] = array[i];
    array[i] = temp;
  }
  return array;
}

/* For exemplification */
/* Returns specified number of cards from given array */
function draw(cards, qty) {
  return [...Array(qty)].map(_ => cards.pop());
}

/**
 * Calculates total points from an array of objects
 * @param {array<object>} hand - Array of card objects
 * @return {number} - Total points obtained
 */
function score(hand) {
  let ace = 0; // Counter for aces
  return hand.reduce((total, current) => {
    if (current.points === 11) ace++; // Check for aces
    while (total + current.points > 21 && ace > 0) { // Ace adjustment condition
      total = total - 10;
      ace--;
    }
    return total + current.points; // Final point calculation
  }, 0);
}

let D = deck(); // Create shuffled deck
console.log("========ROUND 1========");
let handA = draw(D, 2); // Player A draws initial 2 cards
let scoreA = score(handA); // Calculate score of Player A
console.log("Player A draws: ");
console.log(handA);
console.log("Player A score: "+scoreA);
console.log("=======================");
let handB = draw(D, 2); // Player B draws initial 2 cards
let scoreB = score(handB); // Calculate score of Player B
console.log("Player B draws: ");
console.log(handB);
console.log("Player B score: "+scoreB);
console.log("=======================");

console.log("========ROUND 2========");
let hitA = draw(D, 1); // Player A draws another card
handA = [...handA, ...hitA]; // Merge new card with existing hand
scoreA = score(handA); // Calculate updated score of Player A
console.log("Player A draws: ");
console.log(hitA);
console.log("Player A score: "+scoreA);
console.log("=======================");
let hitB = draw(D, 1); // Player B draws another card
handB = [...handB, ...hitB]; // Merge new card with previous hand
scoreB = score(handB); // Calculate updated score of Player B
console.log("Player B draws: ")
console.log(hitB);
console.log("Plater B score: "+scoreB);
console.log("=======================");

console.log("========TEST ACE========");
let handC = [{points: 11}, {points: 4}];
let scoreC = score(handC);
console.log(JSON.stringify(handC));
console.log(scoreC);
let hitC = [{points: 8}];
handC = [...handC, ...hitC];
scoreC = score(handC);
console.log(JSON.stringify(handC));
console.log(scoreC);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Nodemon may have failed to install correctly

When trying to install nodemon globally, I encountered an error. How can I resolve this issue? C:\Users\nipuna\Desktop\nodejs>npm install -g nodemon npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules\ ...

There appears to be a malfunction with WebRupee

I have incorporated the new rupee sign into my website to represent Indian currency. Below is the code snippet I used: For the script, I included " and also added the following: <span class="WebRupee">Rs.</span> 116,754.00 To style it using ...

Implementing Jquery to Identify the Matching Indices of Two Arrays

I need to find the indices of similar values in array1 and array2, and then save them in a variable named stored_index. array1 = ["50","51","52","53","54","55","56","57","58","59"]; array2 = ["59","55","51"]; The desired result for stored_index is: sto ...

Using Arrays in PHP for Dynamic Content Rotation

UPDATE: Read on to discover how I resolved my issues. I'm not very knowledgeable about arrays, but I want to try something new. My goal is to incorporate advertisements into my website. I thought of using multidimensional arrays to manage the conte ...

Is splitting a PHP array after sorting it your next step?

Below is a var_dump of the array I'm working with: array(6) { [0]=> string(4) "quack" ["DOG"]=> string(4) "quack" [1]=> string(4) "quack" ["CAT"]=> string(4) "quack&quo ...

Update the unique identifier when saving a new object

Seeking assistance on updating the objectId of a foreign key in my schema post-saving router.post('/add/:id', (req,res)=>{ const newMenu = new Menu() newMenu.menu_name = req.body.menu_name const restaurantId = req.params.id ...

Transmitting the Flag between PHP and JavaScript

I need help with setting a flag in PHP and accessing it in JavaScript. Currently, I have the following code: PHP if ($totalResults > MAX_RESULT_ALL_PAGES) { $queryUrl = AMAZON_SEARCH_URL . $searchMonthUrlParam . ...

Guide on generating a video thumbnail using JavaScript Application

Searching for a way to easily create a thumbnail from a video for uploading alongside the video itself to a server? I've been looking for JavaScript libraries to simplify the process without much luck. The scenario involves the user selecting a video ...

Generate a string that will be utilized to interpret a JSON response

I can't seem to extract a specific element from a json using a dedicated function. Can someone please assist me with this issue? Here is the fiddle that I have created for reference: http://jsfiddle.net/jonigiuro/N5TTM/2/ CODE: var data = { "res ...

"AngularJS Bi-Directional Data Binding Issue: Unexpected 'Undefined

Recently, I've been tackling a project that involves using a directive. Initially, everything was smooth sailing as I had my directive set up to bind to ngModel. However, I hit a roadblock when I needed to bind multiple values. Upon making the necessa ...

Utilizing the MediaRecorder API: Creating a Media Stream by capturing content from a canvas and combining it with audio from an audio file

I have successfully managed to extract the video from the canvas, but now I need to combine it with an audio stream. After researching a bit, I discovered that I need to use the AudioDestinationNode object in some way. I attempted a couple of methods, bu ...

Tips for making an input field that overlays text

I am currently working on a project that involves creating multiple cards using Bootstrap. Each card consists of a header, body, and footer. When a card is clicked on, I want an input field to appear in the header, footer, and body sections, overlaying the ...

Tips for transferring variables as arguments in javascript

Currently, I am immersed in a test project aimed at expanding my knowledge of web development. Unexpectedly, I have encountered an issue that has left me puzzled on how to proceed. Within this project, there exists a table consisting of 11 cells. While 9 ...

Problems encountered when using Vue.js codes with Webpack

I am utilizing Webpack along with Vue.js. I have a very straightforward code that looks like this: <div id="msg"> <h1>{{msg}}</h1> </div> new Vue({ el: '#msg', data:{ msg:'Hello' } }); When ...

Divide PHP array by its key

I have an array with ordered but non-consecutive numerical keys: Array ( [4] => 2 [5] => 3 [6] => 1 [7] => 2 [8] => 1 [9] => 1 [10] => 1 ) My goal is to split this array into two separate arrays. One shoul ...

What is the best way to display JSON within a partial?

Within my Rails app, I have implemented a JavaScript graph. Whenever I click on a circle in the graph, it displays the name of the corresponding user. Now, my goal is to retrieve additional information from the related database table based on this user&apo ...

When attempting to incorporate JSX or markup within React.js, the closing tags are mysteriously transformed into unreachable code

I am currently learning react-js and I have encountered a problem with my code. Whenever I try to add markup or JSX in the designated area 'write code', my text editor displays syntax errors, disables closing div tags, and even throws unreachable ...

"In the most recent version of THREE.js (r82), the shadow is not detectable

I am having trouble casting a shadow from a cube onto a plane using MeshLambertMaterial in my code. Despite setting up the scene correctly, the shadows are not appearing as expected. Most solutions I have come across suggest that objects should be within ...

Struggling with ajax: Converting a JavaScript variable to a PHP variable

I'm trying to convert a JavaScript variable into a PHP variable in order to use it in an SQL query, but for some reason it's not working as expected. Here is the HTML code: <select id = "dep_ID" name = "dep_ID" onchange="myFunction()"> A ...

What causes the cleanup function in React hooks to be triggered upon reopening a previously closed tab?

There seems to be an issue with closing a tab and then undoing that action. This causes all the cleanup functions in the component to execute, resulting in the abortion of new fetches needed to load the component. This behavior is observed only on Safari ...