What is the best way to implement the Fisher-Yates Shuffle algorithm across several different arrays?

I'm looking to create a bridge deal with four players, each receiving 13 randomized cards.

To start, I plan on declaring variables for the suits, creating a deck containing these suits, and assigning the players their hands:

var deal = function() {
    var spades   = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
    var hearts   = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
    var diamonds = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];
    var clubs    = ['A', 'K', 'Q', 'J', 'T', 9, 8, 7, 6, 5, 4, 3, 2];

    var deck = [spades, hearts, diamonds, clubs];

    //Next step: dealing 13 random cards to each player
    var northHand = [ [], [], [], [] ];
    var eastHand  = [ [], [], [], [] ];
    var southHand = [ [], [], [], [] ];
    var westHand  = [ [], [], [], [] ];


}

Later, I came across a shuffle function based on the Fisher-Yates algorithm:

function shuffle(array) {
  var m = array.length, t, i;

  // While there are elements left to shuffle...
  while (m) {

    // Choose a remaining element...
    i = Math.floor(Math.random() * m--);

    // Swap it with the current element.
    t = array[m];
    array[m] = array[i];
    array[i] = t;
  }

  return array;
}

However, my skills in programming and logic are lacking when it comes to applying this algorithm to my situation involving multiple arrays.

Do you think this is a good starting point for solving my problem, or should I explore other approaches?

Answer №1

To start off, it's important to have a unique way of identifying each card in a deck. Let's assign numbers from 0 to 51 to represent the cards as follows:

  1. Hearts are numbered from 0 to 12.
  2. Spades are numbered from 13 to 25.
  3. Diamonds are numbered from 26 to 38.
  4. Clubs are numbered from 39 to 51.

Within each suit, the cards are further categorized with specific numbers:

  1. Ace through 10 are represented by numbers 0 to 9.
  2. Jack is assigned number 10.
  3. Queen is assigned number 11.
  4. King is assigned number 12.

These numerical values serve purely as identifiers and do not reflect actual card values, making them applicable across various card games. By utilizing these numbers, you can easily determine both the suit and rank of a card:

var suits = ["Hearts", "Spades", "Diamonds", "Clubs"];

var ranks = ["Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"];

function getSuite(card) {
    return suits[Math.floor(card / 13)];
}

function getRank(card) {
    return ranks[card % 13];
}

Your deck now becomes a straightforward array ranging from 0 to 51, enabling you to apply the Fischer Yates algorithm for shuffling:

function deal() {
    var deck = shuffle(range(0, 51));

    var northHand = deck.slice(0, 13);
    var eastHand = deck.slice(13, 26);
    var southHand = deck.slice(26, 39);
    var westHand = deck.slice(39, 52);
}

function range(from, to) {
    if (from > to) return [];
    else return [from].concat(range(from + 1, to));
}

And there you have it!

Answer №2

Each card's suit and value play a significant role, so it's important to keep them paired together. A more suitable representation for a card would be {suit: 'spades', value: 'A'}.

To create the deck, I suggest following this structure:

var deck = [];

var suits = ['spade', 'heart', 'club', 'diamond'];

var values = ['A', 'K', 'Q', 'J', '10', '9', '8', '7', '6', '5', '4', '3', '2'];

for (var sIdx = 0; sIdx < suits.length; sIdx++) {
    for (var vIdx = 0; vIdx < values.length; vIdx++) {
        deck.push({suit: suits[sIdx], value: values[vIdx]});
    }
}

You can then use a shuffle function to randomize the deck, and utilize slice() to divide it into 4 hands of 13 cards each.

Your original idea of using separate arrays for each suit is valid as well. However, aligning the data representation closely with the actual cards makes all operations much easier in the long run.

Answer №3

It seems like the issue lies in how your deck is being constructed. The current approach works well for sequential and logical access, but for a more randomized distribution, consider using a single 52-element array with either strings like 2H, QD, or simple objects like {'Suit': 'Hearts', 'Value': 'Q'}.

With a unified array, shuffling can be easily implemented based on the provided code.

After shuffling, you have the option to assign cards to players sequentially (0-12 for player 1, 13-25 for player 2, etc.) or distribute them strategically by accessing specific card positions for each player.

Instead of separate arrays for N/E/S/W, consider using a 2D array for easier access.

Here's an example loop through the cards:

for(var i=0; i<52; i++) {
    Pos = i % 4;
    Hands[Pos].push(Deck[i]);
}

If your hands are defined as:

var Hands = [ [], [], [], [] ];

You should be all set to proceed (untested).

Answer №4

To achieve a random distribution of values between arrays, it is not advisable to use the Fisher-Yates shuffle method in this case. The following code snippet can help achieve randomness:

var hands = [northHand, eastHand, southHand, westHand];
var numberofcards = 4*13;
for (var i=0; i<4; i++) {
    for (var j=0; j<13; j++) {
        // draw card:
        var card = Math.floor(Math.random() * numberofcards--);
        // check which card it is:
        for (var suit=4; suit-- && card > deck[suit].length; )
            card -= deck[suit].length;
        // remove from deck and assign to player
        hands[i][suit].push(deck[suit].splice(card, 1)[0]);
    }
}

It might be more convenient to represent a single card as an object with suit and value. This approach could make it easier to handle cards and utilize methods like shuffling before dividing the deck into four parts.

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

How can I retrieve data for a 2-dimensional array using a dedicated function?

I'm encountering an issue with passing an array as a function parameter. I'm struggling to understand how to access elements of an array in one function and then display them using another function. Both functions seem to have errors that are per ...

PHP question about maintaining data continuously

So, I've created this interesting JavaScript 'thing' with the help of jQuery and AJAX. The main concept behind it is that a div can be edited (contenteditable=true), which sparked the idea to develop a chatroom-like feature. It's pretty ...

Trouble With OnClick and On/Off Class Script Functionality in Chrome and Internet Explorer

I am working on a page with two iframes and a basic navigation bar. The navigation bar links are set up to target one of the iframes and replace its content when clicked. However, I am having trouble highlighting the currently selected link in the iframe - ...

Can you help me figure out how to retrieve the index of a CSS element during a 'click' event?

I have a collection of images all tagged with the class thumb. When a user clicks on one of these images, I need to determine which image was clicked within the array of thumbs. Essentially, I am looking for the index of the clicked image within the thumbs ...

Struggling to integrate data retrieved from a Vue.js API

Once I receive the API call with an attached string input, I successfully get the result. However, I am struggling to incorporate it into my frontend. I have attempted various solutions found online without success and cannot seem to grasp the concept. Her ...

Error During Array Initialization

I am faced with a situation where I have: public class SubObject { public int id; } public class Object { public SubObject[] SubObjects; } In addition, there is an array that comes into play: public Object[] Objects; Upon attempting to initia ...

Why isn't the array loading upon the initial click in AngularJS?

// CONFIGURING SERVICES app.service("PictureService", function($http) { var Service = {}; Service.pictureLinkList = []; // RETRIEVING PICTURE LINKS FOR THE PAGE $http.get("data/img_location.json") .success(function(data) { Service.pictureLinkLi ...

Issue with Material UI button not properly redirecting to specified path

Having an issue with a button that should redirect to a specific component with props on click. <Button variant="contained" color="primary" className={classes.button} endIcon={<SendIcon/>} onClick={() => { <Redirect ...

The dictionary created by FormData in Flask is poorly designed

I am encountering issues with the connection between ajax and flask when sending a FormData in a request. My goal is to send an array of files from JavaScript using ajax: dropArea.addEventListener("drop", (event)=>{ event.preventDefault(); ...

Issue with custom Javascript not executing in Internet Explorer versions 9 and 10

Initially, this script is found in the document's head section. <script> document.addEventListener("DOMContentLoaded", function () { var e, t = document.querySelectorAll("div.bounceInDown"); for (var n = 0, r = t.length; n & ...

Positioning Text in CSS/JS Navigation

Looking for assistance on aligning the text in the menu located at: 1st tab: I would like a line break after "Item". 2nd and 3rd tabs: I am seeking a line break after "This is". I have only included the section of the menu that requires adjustment, whi ...

Leveraging Numpy's advanced indexing to simultaneously apply two distinct boolean masks

Let's say I have an array called a import numpy as np a = np.array( [ [[1,2], [3,4], [5,6]], [[11,21], [31,41], [51,61]], [[12,22], [32,42], [52,62]], ] ) Additionally, I have two boolean masks named starts and ends starts = ar ...

Design a button for removing the selected value in select2

Can anyone provide some guidance on using select2? I am working with 2 select2 elements, and I want the selected value to be displayed on a button instead of in the input area of the select2. This way, the select2 will still display the placeholder text. ...

Unable to retrieve data from my json file in React

I have successfully created a menu with a submenu and a third child element. Initially, I had hard-coded the data in a local constant called json, which is now commented out. However, I am facing an issue as I now need to fetch the data from my JSON file b ...

Interactive map with AngularJS featuring dynamic markers and real-time updating of marker position

In my Angular application, I have integrated a Google Map with a marker. I am looking to make the marker move along with the map as it is being moved. Currently, the marker stays in its default position when the map is moved. How can I achieve the effect ...

What is the correct way to send an array pointer to a function?

I am currently dealing with two arrays in my code. Within the main function, I have a separate function that updates one of the arrays based on certain values from the other array. volatile float32_t raw_data[3]; //this array is updated by an interrupt ha ...

Updating the state of an object within a mapping function

I've been struggling with this issue for two days now. Despite my efforts to find a solution online, I am still stuck and starting to believe that I might be missing something. The main functionality of the app is to click a button and watch an apple ...

Transform the JSON string into a JSON object to avoid modifying the base jquery.dataTables.js script

When using ASP.net MVC on the server side, I have a model class that I usually serialize with JsonConvert.SerializeObject(DataTableModel) and send back to datatables.js. The resulting JSON data looks like this:_fnBuildAjax.baseAjax >> success as show ...

The Node.js Connect app is throwing an error stating that the object is not a function

I keep encountering an issue whenever I attempt to execute this node application: app.js: var connect = require('connect'); connect.createServer( require('./log-it')(), require('./serve-js')() ).listen(4000); log-it.js ...

Display a div when a radio button is selected

For my current project, I am developing a website that includes 2 radio buttons. When the 'Yes' radio button is checked, a specific div should be displayed on the same page immediately. However, if the 'No' radio button is checked, noth ...