Data structure for representing decks (of cards) based on Immutable.js Stacks.
- Add elements to the deck
- ...to the top,
- bottom,
- at an arbitrary place,
- or at a random place.
- Draw one or more elements from the deck
- ...from the top,
- bottom,
- or at an arbitrary place,
- or at a random place.
- Move items from one deck to another.
- Deal an arbitrary number of items from the Deck into an arbitrary number of groups.
- ... from the top
- from the bottom
- deal out all the items in the deck to the groups.
- Split/cut the deck
- ...in half
- At an arbitrary point
- Count the number of items in the deck.
- Shuffle the contents of the deck.
- Unshuffle (sort) the contents of the deck.
- Reverse order of deck.
- Random methods are deterministic (can be reproduced with the same random seed).
Since there is technically no difference between a hand and a deck the same data structure can be used for both. Therefore, methods like draw()
return items drawn as a new Deck.
Yes. In fact, Deck doesn't make any assumptions about what kind of values you put inside it. You can use strings, numbers, complex card objects, or anything else.
Immutability offers many benefits but if you're looking for a mutable version, card-deck looks like a pretty good one.
This library is all about organizing the elements (cards) in the deck but it doesn't provide any definition of what the card should be. You will need to define your own way to render the elements inside.
Important: Deck
extends Immutable.Stack so be sure to familiarize yourself with Immutable's API. it can do everything that a Stack
can do plus the following...
Property (inherited from Stack). Get the number of itmes in the deck.
const deck = new Deck(["a", "b", "c"]);
deck.size; // 3
(inherited from Stack). Get the value of the item at the index.
const deck = new Deck(["a", "b", "c"]);
deck.get(1); // "b"
Sets a value at the given index.
const deck = new Deck(["a", "😐", "c"]);
deck.set(1, "b"); // ["a", "b", "c"]
These functions add one or more items to the deck. Returns a new Deck with the items added. Items which are collections are not automatically flattened, that is, they are added as collections.
alias add( ...items )
add()
and addToTop()
add items to the top (front) of the deck.
const deck = new Deck(["c", "d"]);
deck.add("a", "b"); // ["a", "b", "c", "d"]
// Collections are not flattened.
deck.add(["a", "b"]); // [["a", "b"], "c", "d"]
// Use spread to flatten collections.
deck.add(...["a", "b"]); // ["a", "b", "c", "d"]
Adds items to the bottom (back) of the deck.
const deck = new Deck(["c", "d"]);
deck.addToBottom("e", "f"); // ["c","d","e","f"]
Add items at a specific index.
const deck = new Deck(["c", "d"]);
deck.addAt(1, "c.5"); // ["c","c.5","d"]
These functions remove n
items from the deck (if n
is undefined
, it defaults to 1
). Returns an array whose first element is a Deck of items drawn and the second element is the original Deck without the items drawn.
alias draw( n )
Draw n
items from the top (front) of the deck.
const deck = new Deck([0, 1, 2, 3, 4]);
const [hand, newDeck] = deck.draw(3);
hand; // [0, 1, 2]
newDeck; // [3, 4]
// Defaults to drawing 1 item.
deck.draw(); // [ [0], [1, 2, 3, 4] ]
// Drawing more items than the size of the deck returns
// an empty collection for the new deck.
deck.draw(1000); // [ [0, 1, 2, 3, 4], [] ]
Draw n
items from the bottom (back) of the deck.
const deck = new Deck([0, 1, 2, 3, 4]);
const [hand, newDeck] = deck.drawFromBottom(3);
hand; // [4, 3, 2] note order is reversed
newDeck; // [0, 1]
Draw n
items from a specific index.
const deck = new Deck([0, 1, 2, 3, 4]);
const [hand, newDeck] = deck.drawFrom(1, 3);
hand; // [1, 2, 3] note order is reversed
newDeck; // [0, 4]
Shuffles the items. Returns a new Deck with elements randomly reordered.
const deck = new Deck([0, 1, 2, 3, 4, 5]);
deck.shuffle(); // Deck([3, 5, 4, 0, 2, 1])
alias shuffleInto( ...items )
Returns a new deck with one or more values added at random positions. Each item is given a random location in the deck.
let deck = new Deck([0,1,2,3,4,5,6,7,8,9]);
let newDeck = deck.addRandom("a", "b", "c"); // [0,1,2,3,4,"a",5,6,7,"c","b",8,9]
Draw n
cards from n
random positions in the deck. A new random position is chosen for each card.
const deck = new Deck([0, 1, 2, 3, 4]);
const [hand, newDeck] = deck.drawRandom(3);
hand; // [4, 3, 0] note order is random
newDeck; // [1, 2]
Returns a random index in the deck.
const deck = new Deck(["a", "b", "c", "d", "e", "f", "g"]);
deck.getRandomIndex(); // 1
deck.getRandomIndex(); // 5
deck.getRandomIndex(); // 3
All randomized functions use a special deterministic random number generator, random-seed. This allows you to produce repeatable sequences of random numbers that guarantee the same order of random numbers when you use the same seed. This is useful for testing or, for example, if you want to have a global challenge mode in a card game where the cards are shuffled identically for every player.
setRandomSeed()
sets the random seed for the random number sequence used by functions like shuffle()
. Set to a constant value to create the same sequence of random numbers every time your app is run. Set to undefined to create an unpredictable sequence. See random-seed for more details.
You don't need to call setRandomSeed()
to use the other functions. By default, the random seed is a random value.
let numbers = new Deck([0,1,2,3,4,5]);
// Set a random seed.
numbers.setRandomSeed(1);
numbers.shuffle(); // [ 5, 2, 4, 0, 3, 1 ]
numbers.shuffle(); // [ 3, 2, 5, 1, 0, 4 ]
numbers.shuffle(); // [ 2, 4, 1, 0, 5, 3 ]
// Set the random seed again to repeat the sequence.
numbers.setRandomSeed(1);
numbers.shuffle(); // [ 5, 2, 4, 0, 3, 1 ]
numbers.shuffle(); // [ 3, 2, 5, 1, 0, 4 ]
numbers.shuffle(); // [ 2, 4, 1, 0, 5, 3 ]
// Set to a different seed to change the sequence.
numbers.setRandomSeed(2);
numbers.shuffle(); // [ 5, 0, 1, 2, 3, 4 ]
// Use undefined to use a random sequence
numbers.setRandomSeed();
numbers.shuffle(); // [ 4, 2, 0, 1, 5, 3 ]
numbers.setRandomSeed();
numbers.shuffle(); // [ 1, 0, 3, 5, 2, 4 ]
numbers.setRandomSeed();
numbers.shuffle(); // [ 5, 2, 0, 1, 3, 4 ]
These funcitons distribute the elements of a deck into one or more groups in a cyclical fashion, in other words, they deal out the elements like cards. You can specify the number of groups (hands) to deal out and the number of items to deal to each group. If itemsPerGroup
is undefined, all remaining items are dealt (this may result in some groups having 1 more item than other groups).
Results are returned as an array with the last element being the new deck and the remaining elements being the groups.
alias deal( groups, itemsPerGroup )
Deals from the top (front) of the deck.
let hand0, hand1, hand2, newDeck;
let deck = new Deck([0,1,2,3,4,5,6,7,8,9]);
// Deal 3 cards to 2 hands
[hand0, hand1, newDeck] = deck.deal(2, 3);
hand0; // [0, 2, 4]
hand1; // [1, 3, 5]
newDeck; // [6, 7, 8, 9]
// Deal all cards to 3 hands
[hand0, hand1, hand2, newDeck] = deck.deal(3);
hand0; // [0, 3, 6, 9]
hand1; // [1, 4, 7]
hand2; // [2, 5, 8]
newDeck; // []
Deals from the bottom (back) of the deck.
let deck = new Deck([0,1,2,3,4,5,6,7,8,9]);
deck.dealFromBottom(2,2); // [ [9, 7], [8, 6], [0, 1, 2, 3, 4, 5] ]
alias split( index )
Splits the deck into two decks. If index is undefined
, the deck is split right down the middle (if there are an odd number of items, the extra item is added to the first deck).
Returns an array containing two deck objects.
const deck = new Deck([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
deck.cut(); // [ [0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10] ]
deck.cut(3); // [ [0, 1, 2], [3, 4, 5, 6, 7, 8, 9, 10] ]
If you'd like to make this project better, here are ways you can help.
- Give your feedback
- Log bugs
- Fix bugs
- Suggest a feature
- Improve the documentation
- Improve the examples
- Mims H. Wright - Owner