Playing cards: Difference between revisions
Walterpachl (talk | contribs) (Added Rexx) |
(→{{header|REXX}}: changed Rexx to REXX in the header definition. -- ~~~~) |
||
Line 2,310: | Line 2,310: | ||
deck <- deal(deck, FALSE)</lang> |
deck <- deal(deck, FALSE)</lang> |
||
=={{header| |
=={{header|REXX}}== |
||
<lang rexx>/* REXX *************************************************************** |
<lang rexx>/* REXX *************************************************************** |
||
* 1) Build ordered Card deck |
* 1) Build ordered Card deck |
Revision as of 04:12, 17 August 2012
You are encouraged to solve this task according to the task description, using any language you may know.
Create a data structure and the associated methods to define and manipulate a deck of playing cards. The deck should contain 52 unique cards. The methods must include the ability to make a new deck, shuffle (randomize) the deck, deal from the deck, and print the current contents of a deck. Each card must have a pip value and a suit value which constitute the unique value of the card.
ACL2
<lang Lisp>(defun remove-nth (i xs)
(if (or (zp i) (endp (rest xs))) (rest xs) (cons (first xs) (remove-nth (1- i) (rest xs)))))
(defthm remove-nth-shortens
(implies (consp xs) (< (len (remove-nth i xs)) (len xs))))
- set-state-ok t
(defun shuffle-r (xs ys state)
(declare (xargs :measure (len xs))) (if (endp xs) (mv ys state) (mv-let (idx state) (random$ (len xs) state) (shuffle-r (remove-nth idx xs) (cons (nth idx xs) ys) state))))
(defun shuffle (xs state)
(shuffle-r xs nil state))
(defun cross-r (x ys)
(if (endp ys) nil (cons (cons x (first ys)) (cross-r x (rest ys)))))
(defun cross (xs ys)
(if (or (endp xs) (endp ys)) nil (append (cross-r (first xs) ys) (cross (rest xs) ys))))
(defun make-deck ()
(cross '(ace 2 3 4 5 6 7 8 9 10 jack queen king) '(hearts diamonds clubs spades)))
(defun print-card (card)
(cw "~x0 of ~x1~%" (car card) (cdr card)))
(defun print-deck (deck)
(if (endp deck) nil (progn$ (print-card (first deck)) (print-deck (rest deck)))))
(defun draw-from-deck (deck)
(mv (first deck) (rest deck)))
</lang>
Example (first 4 cards of a shuffled deck):
> (mv-let (deck state) (shuffle (make-deck) state) (mv (print-deck (take 4 deck)) state)) 5 of CLUBS ACE of DIAMONDS 6 of HEARTS 4 of DIAMONDS (NIL <state>)
Ada
ALGOL 68
The scoping rules of ALGOL 68 tend to make object oriented coding in ALGOL 68 difficult. Also as invoking PROC is done before members of a STRUCT are extracted the programmer one quickly finds it is necessary to use numerous brackets.
e.g. compare "(shuffle OF deck class)(deck)" with python's simple "deck.shuffle()"
For further details:
- Ross, D.T., "Features Essential for a Workable Algol X," ALGOL Bulletin, No. 26, August 1967, pp. 6-12, and ACM SIGPLAN Notices, Vol.2, No.11, November 1967.
- LOC was essential; Algol 68's REF was a mistake.
<lang algol68>MODE CARD = STRUCT(STRING pip, suit); # instance attributes #
- class members & attributes #
STRUCT(
PROC(REF CARD, STRING, STRING)VOID init, FORMAT format, PROC(REF CARD)STRING repr, []STRING suits, pips
) class card = (
- PROC init = # (REF CARD self, STRING pip, suit)VOID:(
pip OF self:=pip; suit OF self :=suit ),
- format = # $"("g" OF "g")"$,
- PROC repr = # (REF CARD self)STRING: (
HEAP STRING out; putf(BOOK out,(format OF class card,self)); out ),
- suits = # ("Clubs","Hearts","Spades","Diamonds"),
- pips = # ("2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace")
);
MODE DECK = STRUCT(REF[]CARD deck); # instance attributes #
- class members & attributes #
STRUCT(
PROC(REF DECK)VOID init, shuffle, PROC(REF DECK)STRING repr, PROC(REF DECK)CARD deal
) class deck = (
- PROC init = # (REF DECK self)VOID:(
HEAP[ UPB suits OF class card * UPB pips OF class card ]CARD new; FOR suit TO UPB suits OF class card DO FOR pip TO UPB pips OF class card DO new[(suit-1)*UPB pips OF class card + pip] := ((pips OF class card)[pip], (suits OF class card)[suit]) OD OD; deck OF self := new ),
- PROC shuffle = # (REF DECK self)VOID:
FOR card TO UPB deck OF self DO CARD this card = (deck OF self)[card]; INT random card = random int(LWB deck OF self,UPB deck OF self); (deck OF self)[card] := (deck OF self)[random card]; (deck OF self)[random card] := this card OD,
- PROC repr = # (REF DECK self)STRING: (
FORMAT format = $"("n(UPB deck OF self-1)(f(format OF class card)", ")f(format OF class card)")"$; HEAP STRING out; putf(BOOK out,(format, deck OF self)); out ),
- PROC deal = # (REF DECK self)CARD: (
(shuffle OF class deck)(self); (deck OF self)[UPB deck OF self] )
);
- associate a STRING with a FILE for easy text manipulation #
OP BOOK = (REF STRING string)REF FILE:(
HEAP FILE book; associate(book, string); book
);
- Pick a random integer between from [lwb..upb] #
PROC random int = (INT lwb, upb)INT:
ENTIER(random * (upb - lwb + 1) + lwb);
DECK deck;
(init OF class deck)(deck);
(shuffle OF class deck)(deck);
print (((repr OF class deck)(deck), new line))</lang>
Example output:
((King OF Clubs), (6 OF Hearts), (7 OF Diamonds), (Ace OF Hearts), (9 OF Spades), (10 OF Clubs), (Ace OF Spades), (8 OF Clubs), (4 OF Spades), (8 OF Hearts), (Jack OF Hearts), (3 OF Clubs), (7 OF Hearts), (10 OF Hearts), (Jack OF Clubs), (Ace OF Clubs), (King OF Spades), (9 OF Clubs), (7 OF Spades), (5 OF Spades), (7 OF Clubs), (Queen OF Clubs), (9 OF Diamonds), (2 OF Spades), (6 OF Diamonds), (Ace OF Diamonds), (Queen OF Diamonds), (5 OF Hearts), (4 OF Clubs), (5 OF Clubs), (4 OF Hearts), (3 OF Diamonds), (4 OF Diamonds), (3 OF Hearts), (King OF Diamonds), (2 OF Clubs), (Jack OF Spades), (2 OF Diamonds), (5 OF Diamonds), (Queen OF Spades), (10 OF Diamonds), (King OF Hearts), (Jack OF Diamonds), (Queen OF Hearts), (8 OF Spades), (2 OF Hearts), (8 OF Diamonds), (10 OF Spades), (9 OF Hearts), (6 OF Clubs), (3 OF Spades), (6 OF Spades))
AutoHotkey
<lang AutoHotkey> Loop, 52 {
Random, card%A_Index%, 1, 52 While card%A_Index% Random, card%A_Index%, 1, 52 card%A_Index% := Mod(card%A_Index%, 12) . " of " . ((card%A_Index% <= 12) ? "diamonds" : ((card%A_Index%) <= 24) ? "hearts" : ((card%A_Index% <= 36) ? "clubs" : "spades"))) allcards .= card%A_Index% . "`n"
} currentcard = 1 Gui, Add, Text, vcard w500 Gui, Add, Button, w500 gNew, New Deck (Shuffle) Gui, Add, Button, w500 gDeal, Deal Next Card Gui, Add, Button, w500 gReveal, Reveal Entire Deck Gui, Show,, Playing Cards Return New: Reload GuiClose: ExitApp Deal: GuiControl,, card, % card%currentcard% currentcard++ Return Reveal: GuiControl,, card, % allcards Return </lang>
BASIC
Most BASICs aren't object-oriented (or anything even resembling such) and can't do a deck of cards as a single cohesive unit -- but we can fake it.
<lang qbasic>DECLARE SUB setInitialValues (deck() AS STRING * 2) DECLARE SUB shuffle (deck() AS STRING * 2) DECLARE SUB showDeck (deck() AS STRING * 2) DECLARE FUNCTION deal$ (deck() AS STRING * 2)
DATA "AS", "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "TS", "JS", "QS", "KS" DATA "AH", "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "TH", "JH", "QH", "KH" DATA "AC", "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "TC", "JC", "QC", "KC" DATA "AD", "2D", "3D", "4D", "5D", "6D", "7D", "8D", "9D", "TD", "JD", "QD", "KD"
RANDOMIZE TIMER
REDIM cards(51) AS STRING * 2 REDIM cards2(51) AS STRING * 2
setInitialValues cards() setInitialValues cards2() shuffle cards() PRINT "Dealt: "; deal$(cards()) PRINT "Dealt: "; deal$(cards()) PRINT "Dealt: "; deal$(cards()) PRINT "Dealt: "; deal$(cards()) showDeck cards() showDeck cards2()
FUNCTION deal$ (deck() AS STRING * 2)
'technically dealing from the BOTTOM of the deck... whatever DIM c AS STRING * 2 c = deck(UBOUND(deck)) REDIM PRESERVE deck(LBOUND(deck) TO UBOUND(deck) - 1) AS STRING * 2 deal$ = c
END FUNCTION
SUB setInitialValues (deck() AS STRING * 2)
DIM L0 AS INTEGER
RESTORE FOR L0 = 0 TO 51 READ deck(L0) NEXT
END SUB
SUB showDeck (deck() AS STRING * 2)
FOR L% = LBOUND(deck) TO UBOUND(deck) PRINT deck(L%); " "; NEXT PRINT
END SUB
SUB shuffle (deck() AS STRING * 2)
DIM w AS INTEGER DIM shuffled(51) AS STRING * 2 DIM L0 AS INTEGER
FOR L0 = 51 TO 0 STEP -1 w = INT(RND * (L0 + 1)) shuffled(L0) = deck(w) IF w <> L0 THEN deck(w) = deck(L0) NEXT
FOR L0 = 0 TO 51 deck(L0) = shuffled(L0) NEXT
END SUB</lang>
Sample output:
Dealt: 7D Dealt: 6D Dealt: KD Dealt: 8S 5D QH JC JH KC 3S QD 4D 9H 2C JD KH 7H 4H AD 7S 3D 2H 3H 5C 4S AS TD 7C QS 9S 9D KS 8H 4C 6H 5H 5S 8D TC AH TS 9C 3C 8C TH 2D QC 6C AC 2S JS 6S AS 2S 3S 4S 5S 6S 7S 8S 9S TS JS QS KS AH 2H 3H 4H 5H 6H 7H 8H 9H TH JH QH KH AC 2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC AD 2D 3D 4D 5D 6D 7D 8D 9D TD JD QD KD
BBC BASIC
<lang bbcbasic> DIM Deck{ncards%, card&(51)}, Suit$(3), Rank$(12)
Suit$() = "Clubs", "Diamonds", "Hearts", "Spades" Rank$() = "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", \ \ "Eight", "Nine", "Ten", "Jack", "Queen", "King" PRINT "Creating a new deck..." PROCnewdeck(deck1{}) PRINT "Shuffling the deck..." PROCshuffle(deck1{}) PRINT "The first few cards are:" FOR card% = 1 TO 8 PRINT FNcardname(deck1.card&(card%)) NEXT PRINT "Dealing three cards from the deck:" FOR card% = 1 TO 3 PRINT FNcardname(FNdeal(deck1{})) NEXT PRINT "Number of cards remaining in the deck = " ; deck1.ncards% END REM Make a new deck: DEF PROCnewdeck(RETURN deck{}) LOCAL N% DIM deck{} = Deck{} FOR N% = 0 TO 51 deck.card&(N%) = N% deck.ncards% += 1 NEXT ENDPROC REM Shuffle a deck: DEF PROCshuffle(deck{}) LOCAL N% FOR N% = 52 TO 2 STEP -1 SWAP deck.card&(N%-1), deck.card&(RND(N%)-1) NEXT ENDPROC REM Deal from the 'bottom' of the deck: DEF FNdeal(deck{}) IF deck.ncards% = 0 THEN ERROR 100, "Deck is empty" deck.ncards% -= 1 = deck.card&(deck.ncards%) REM Return the name of a card: DEF FNcardname(card&) = Rank$(card& >> 2) + " of " + Suit$(card& AND 3)</lang>
Output:
Creating a new deck... Shuffling the deck... The first few cards are: King of Spades Four of Diamonds Six of Spades Four of Clubs Six of Diamonds Jack of Clubs Nine of Clubs Ace of Clubs Dealing three cards from the deck: Three of Spades Three of Diamonds Four of Hearts Number of cards remaining in the deck = 49
C
<lang C>#include <stdio.h>
- include <stdlib.h>
- include <locale.h>
int locale_ok = 0;
wchar_t s_suits[] = L"♠♥♦♣"; /* if your file can't contain unicode, use the next line instead */ //wchar_t s_suits[] = L"\x2660\x2665\x2666\x2663";
char *s_suits_ascii[] = { "S", "H", "D", "C" }; char *s_nums[] = { "WHAT", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "OVERFLOW" };
typedef struct { int suit, number, _s; } card_t, *card; typedef struct { int n; card_t cards[52]; } deck_t, *deck;
void show_card(card c) { if (locale_ok) printf(" %lc%s", s_suits[c->suit], s_nums[c->number]); else printf(" %s%s", s_suits_ascii[c->suit], s_nums[c->number]); }
deck new_deck() { int i, j, k; deck d = malloc(sizeof(deck_t)); d->n = 52; for (i = k = 0; i < 4; i++) for (j = 1; j <= 13; j++, k++) { d->cards[k].suit = i; d->cards[k].number = j; } return d; }
void show_deck(deck d) { int i; printf("%d cards:", d->n); for (i = 0; i < d->n; i++) show_card(d->cards + i); printf("\n"); }
int cmp_card(const void *a, const void *b) { int x = ((card)a)->_s, y = ((card)b)->_s; return x < y ? -1 : x > y; }
card deal_card(deck d) { if (!d->n) return 0; return d->cards + --d->n; }
void shuffle_deck(deck d) { int i; for (i = 0; i < d->n; i++) d->cards[i]._s = rand(); qsort(d->cards, d->n, sizeof(card_t), cmp_card); }
int main() { int i, j; deck d = new_deck();
locale_ok = (0 != setlocale(LC_CTYPE, ""));
printf("New deck, "); show_deck(d);
printf("\nShuffle and deal to three players:\n"); shuffle_deck(d); for (i = 0; i < 3; i++) { for (j = 0; j < 5; j++) show_card(deal_card(d)); printf("\n"); } printf("Left in deck "); show_deck(d);
/* freeing the data struct requires just free(), but it depends on the * situation: there might be cards dealt out somewhere, which is not * in the scope of this task. */ //free(d); return 0; }</lang>output
New deck, 52 cards: ♠A ♠2 ♠3 ♠4 ♠5 ♠6 ♠7 ♠8 ♠9 ♠10 ♠J ♠Q ♠K ♥A ♥2 ... Shuffle and deal to three players: ♦3 ♦Q ♥2 ♣J ♣9 ♥3 ♠5 ♣5 ♠A ♦6 ♣8 ♥J ♠4 ♠3 ♣A Left in deck 37 cards: ♥8 ♣10 ♣K ♦2 ♦A ♥10 ♥6 ♥Q ♠6 ♦4 ♥9 ♠9 ♣6 ♦K ♦8 ♠7 ♣7 ♠K ♠2 ♣4 ...
See also Playing Cards/C
C++
Since all the functions are quite simple, they are all defined inline <lang cpp>#ifndef CARDS_H_INC
- define CARDS_H_INC
- include <deque>
- include <algorithm>
- include <ostream>
- include <iterator>
namespace cards {
class card { public: enum pip_type { two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace }; enum suite_type { hearts, spades, diamonds, clubs };
// construct a card of a given suite and pip card(suite_type s, pip_type p): value(s + 4*p) {}
// construct a card directly from its value card(unsigned char v = 0): value(v) {}
// return the pip of the card pip_type pip() { return pip_type(value/4); }
// return the suit of the card suite_type suite() { return suite_type(value%4); }
private: // there are only 52 cards, therefore unsigned char suffices unsigned char value; };
char const* const pip_names[] = { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "jack", "queen", "king", "ace" };
// output a pip std::ostream& operator<<(std::ostream& os, card::pip_type pip) { return os << pip_names[pip]; };
char const* const suite_names[] = { "hearts", "spades", "diamonds", "clubs" };
// output a suite std::ostream& operator<<(std::ostream& os, card::suite_type suite) { return os << suite_names[suite]; }
// output a card std::ostream& operator<<(std::ostream& os, card c) { return os << c.pip() << " of " << c.suite(); }
class deck { public: // default constructor: construct a default-ordered deck deck() { for (int i = 0; i < 52; ++i) cards.push_back(card(i)); }
// shuffle the deck void shuffle() { std::random_shuffle(cards.begin(), cards.end()); }
// deal a card from the top card deal() { card c = cards.front(); cards.pop_front(); return c; }
// iterators (only reading access is allowed) typedef std::deque<card>::const_iterator const_iterator; const_iterator begin() const { return cards.begin(); } const_iterator end() const { return cards.end(); } private: // the cards std::deque<card> cards; };
// output the deck inline std::ostream& operator<<(std::ostream& os, deck const& d) { std::copy(d.begin(), d.end(), std::ostream_iterator<card>(os, "\n")); return os; }
}
- endif</lang>
C#
<lang csharp>using System; using System.Linq; using System.Text; using System.Collections.Generic;
class Card {
string pip; string suit;
public static string[] pips = { "Two","Three","Four","Five","Six","Seven","Eight", "Nine","Ten","Jack","Queen","King","Ace"};
public static string[] suits = { "Diamonds", "Spades", "Hearts", "Clubs" };
public Card(string pip, string suit) { this.pip = pip; this.suit = suit; }
public override string ToString() { return String.Format("{0} of {1}", pip, suit); }
}
class Deck {
public List<Card> deck = new List<Card>();
public Deck() { foreach (string pip in Card.pips) { foreach (string suits in Card.suits) { deck.Add(new Card(pip, suits)); } } }
public void Shuffle() { // using Knuth Shuffle (see at http://rosettacode.org/wiki/Knuth_shuffle) Random random = new System.Random(); Card temp; int j; for (int i = 0; i < deck.Count; i++){ j = random.Next(deck.Count); temp = deck[i]; deck[i] = deck[j]; deck[j] = temp; } }
public Card Deal() { Card r = this.deck[0]; this.deck.RemoveAt(0); return r; }
public override string ToString() { return String.Join(Environment.NewLine, this.deck.Select(x => x.ToString()).ToArray()); }
}</lang>
Clojure
<lang Clojure>(defrecord Card [pip suit]
Object (toString [this] (str pip " of " suit)))
(defprotocol pDeck
(deal [this n]) (shuffle [this]) (newDeck [this]) (print [this]))
(deftype Deck [cards]
pDeck (deal [this n] [(take n cards) (Deck. (drop n cards))]) (shuffle [this] (Deck. (shuffle cards))) (newDeck [this] (Deck. (for [suit ["Clubs" "Hearts" "Spades" "Diamonds"]
pip ["2" "3" "4" "5" "6" "7" "8" "9" "10" "Jack" "Queen" "King" "Ace"]] (Card. pip suit))))
(print [this] (dorun (map (comp println str) cards)) this))
(defn new-deck []
(.newDeck (Deck. nil)))</lang>
Common Lisp
A card is a cons of a suit and a pip. A deck is a list of cards, and so dealing is simply popping off of a deck. Shuffling is naïve, just a sort with a random predicate. Printing is built in.
<lang lisp>(defconstant +suits+
'(club diamond heart spade) "Card suits are the symbols club, diamond, heart, and spade.")
(defconstant +pips+
'(ace 2 3 4 5 6 7 8 9 10 jack queen king) "Card pips are the numbers 2 through 10, and the symbols ace, jack,
queen and king.")
(defun make-deck (&aux (deck '()))
"Returns a list of cards, where each card is a cons whose car is a
suit and whose cdr is a pip."
(dolist (suit +suits+ deck) (dolist (pip +pips+) (push (cons suit pip) deck))))
(defun shuffle (list)
"Returns a shuffling of list, by sorting it with a random
predicate. List may be modified."
(sort list #'(lambda (x y) (declare (ignore x y)) (zerop (random 2)))))</lang>
Delphi
<lang d> program Cards;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
TPip = (pTwo, pThree, pFour, pFive, pSix, pSeven, pEight, pNine, pTen, pJack, pQueen, pKing, pAce); TSuite = (sDiamonds, sSpades, sHearts, sClubs);
const
cPipNames: array[TPip] of string = ('2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'); cSuiteNames: array[TSuite] of string = ('Diamonds', 'Spades', 'Hearts', 'Clubs');
type
TCard = class private FSuite: TSuite; FPip: TPip; public constructor Create(aSuite: TSuite; aPip: TPip); function ToString: string; override;
property Pip: TPip read FPip; property Suite: TSuite read FSuite; end;
TDeck = class private FCards: TList; public constructor Create; destructor Destroy; override; procedure Shuffle; function Deal: TCard; function ToString: string; override; end;
{ TCard }
constructor TCard.Create(aSuite: TSuite; aPip: TPip); begin
FSuite := aSuite; FPip := aPip;
end;
function TCard.ToString: string; begin
Result := Format('%s of %s', [cPipNames[Pip], cSuiteNames[Suite]])
end;
{ TDeck }
constructor TDeck.Create; var
pip: TPip; suite: TSuite;
begin
FCards := TList.Create; for suite := Low(TSuite) to High(TSuite) do for pip := Low(TPip) to High(TPip) do FCards.Add(TCard.Create(suite, pip));
end;
function TDeck.Deal: TCard; begin
Result := FCards[0]; FCards.Delete(0);
end;
destructor TDeck.Destroy; var
i: Integer; c: TCard;
begin
for i := FCards.Count - 1 downto 0 do begin c := FCards[i]; FCards.Delete(i); c.Free; end; FCards.Free; inherited;
end;
procedure TDeck.Shuffle; var
i, j: Integer; temp: TCard;
begin
Randomize; for i := FCards.Count - 1 downto 0 do begin j := Random(FCards.Count); temp := FCards[j]; FCards.Delete(j); FCards.Add(temp); end;
end;
function TDeck.ToString: string; var
i: Integer;
begin
for i := 0 to FCards.Count - 1 do Writeln(TCard(FCards[i]).ToString);
end;
begin
with TDeck.Create do try Shuffle; ToString; Writeln; with Deal do try Writeln(ToString); finally Free; end; finally Free; end;
Readln;
end.
</lang>
D
<lang d>import std.stdio, std.random, std.algorithm, std.string, std.conv;
struct Card {
static immutable suits = ["Club", "Heart", "Diamond", "Spade"]; static immutable pips = "Ace 2 3 4 5 6 7 8 9 10 J Q K".split(); enum nPack = suits.length * pips.length;
static bool rankAceTop = true; /*const*/ int pip, suit;
string toString() const { return format("%3s of %-7s", pips[pip], suits[suit]). rightJustify(15); }
@property int order() const nothrow { auto pipOrder = (!rankAceTop) ? pip : ((pip != 0) ? pip - 1 : 12); return pipOrder * suits.length + suit; }
bool opEqual(in Card rhs) const pure nothrow { return pip == rhs.pip && suit == rhs.suit; }
int opCmp(in Card rhs) const nothrow { return order - rhs.order; }
}
final class Deck {
private Card[] cards;
this(in bool initShuffle = true, in int pack = 0) nothrow { cards.length = 0; foreach (p; 0 .. pack) foreach (c; 0 .. Card.nPack) cards ~= Card((c / Card.suits.length) % Card.pips.length, c % Card.suits.length);
if (initShuffle) cards.randomShuffle(); }
@property size_t length() const pure nothrow { return cards.length; }
Deck add(in Card c) pure nothrow { cards ~= c; return this; }
Deck deal(in int loc, Deck toDeck = null) pure nothrow { if (toDeck !is null) toDeck.add(cards[loc]); cards = cards[0 .. loc] ~ cards[loc + 1 .. $]; return this; }
Deck dealTop(Deck toDeck = null) pure nothrow { return deal(length - 1, toDeck); }
Card opIndex(in int loc) const pure nothrow { return cards[loc]; }
alias opIndex peek;
Deck showDeck() { writeln(this); return this; }
Deck shuffle() { cards.randomShuffle(); return this; }
Deck sortDeck() { sort!q{a > b}(cards); return this; }
override string toString() const { string result; foreach (c; std.range.chunks(cards, 4)) result ~= map!text(c).join() ~ "\n"; return result; }
}
void main() {
Deck[4] guests; foreach (ref g; guests) g = new Deck; // empty deck
auto host = new Deck(false, 1); writeln("Host"); host.shuffle().showDeck();
while (host.length > 0) foreach (ref g; guests) if (host.length > 0) host.dealTop(g);
foreach (i, g; guests) { writefln("Player #%d", i + 1); g.sortDeck().showDeck(); }
}</lang>
- Output:
Host 2 of Heart J of Diamond 7 of Diamond K of Club K of Heart Ace of Heart J of Club 6 of Heart 7 of Spade 2 of Diamond Q of Diamond 5 of Diamond 4 of Club Q of Spade 5 of Spade 9 of Diamond 2 of Spade 9 of Club K of Spade 9 of Heart 3 of Club 8 of Heart 6 of Diamond 7 of Club 10 of Spade 10 of Heart 4 of Heart 9 of Spade 3 of Diamond 4 of Spade 8 of Spade 5 of Club 8 of Diamond 3 of Heart 5 of Heart K of Diamond 7 of Heart Ace of Diamond 8 of Club 6 of Spade J of Spade 6 of Club Q of Heart 3 of Spade 10 of Club 2 of Club Ace of Spade 4 of Diamond 10 of Diamond Ace of Club Q of Club J of Heart Player #1 K of Diamond K of Club J of Heart 9 of Spade 9 of Diamond 9 of Heart 7 of Club 6 of Spade 6 of Heart 5 of Diamond 5 of Club 4 of Diamond 3 of Spade Player #2 Ace of Spade K of Spade Q of Diamond Q of Heart Q of Club J of Club 8 of Spade 8 of Club 7 of Diamond 6 of Diamond 5 of Spade 5 of Heart 4 of Heart Player #3 Ace of Diamond Ace of Heart Ace of Club Q of Spade J of Diamond 10 of Heart 9 of Club 8 of Heart 6 of Club 4 of Spade 3 of Heart 2 of Diamond 2 of Club Player #4 K of Heart J of Spade 10 of Spade 10 of Diamond 10 of Club 8 of Diamond 7 of Spade 7 of Heart 4 of Club 3 of Diamond 3 of Club 2 of Spade 2 of Heart
Alternative version
<lang d>import std.random, std.conv, std.stdio;
class Card {
enum suits = ["Clubs", "Hearts", "Spades", "Diamonds"]; enum pips = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"];
string pip, suit;
this(string pip, string suit) { this.pip = pip; this.suit = suit; }
override string toString() { return this.pip ~ " of " ~ this.suit; }
}
class Deck {
Card[] deck;
this() { foreach (suit; Card.suits) foreach (pip; Card.pips) this.deck ~= new Card(pip, suit); }
override string toString() { return text(this.deck); }
void shuffle() { randomShuffle(this.deck); }
Card deal() { this.shuffle(); Card c = this.deck[$ - 1]; this.deck.length--; return c; }
}
void main() {}</lang>
E
See Playing Cards/E
Forth
<lang forth>require random.fs \ RANDOM ( n -- 0..n-1 ) is called CHOOSE in other Forths
create pips s" A23456789TJQK" mem, create suits s" DHCS" mem, \ diamonds, hearts, clubs, spades
- .card ( c -- )
13 /mod swap pips + c@ emit suits + c@ emit ;
create deck 52 allot variable dealt
- new-deck
52 0 do i deck i + c! loop 0 dealt ! ;
- .deck
52 dealt @ ?do deck i + c@ .card space loop cr ;
- shuffle
51 0 do 52 i - random i + ( rand-index ) deck + deck i + c@ over c@ deck i + c! swap c! loop ;
- cards-left ( -- n ) 52 dealt @ - ;
- deal-card ( -- c )
cards-left 0= abort" Deck empty!" deck dealt @ + c@ 1 dealt +! ;
- .hand ( n -- )
0 do deal-card .card space loop cr ;
new-deck shuffle .deck 5 .hand cards-left . \ 47</lang>
Fantom
<lang fantom> enum class Suit { clubs, diamonds, hearts, spades } enum class Pips { ace, two, three, four, five,
six, seven, eight, nine, ten, jack, queen, king
}
class Card {
readonly Suit suit readonly Pips pips
new make (Suit suit, Pips pips) { this.suit = suit this.pips = pips }
override Str toStr () { "card: $pips of $suit" }
}
class Deck {
Card[] deck := [,]
new make () { Suit.vals.each |val| { Pips.vals.each |pip| { deck.add (Card(val, pip)) } } }
Void shuffle (Int swaps := 50) { swaps.times { deck.swap(Int.random(0..deck.size-1), Int.random(0..deck.size-1)) } }
Card[] deal (Int cards := 1) { if (cards > deck.size) throw ArgErr("$cards is larger than ${deck.size}") Card[] result := [,] cards.times { result.push (deck.removeAt (0)) } return result }
Void show () { deck.each |card| { echo (card.toStr) } }
}
class PlayingCards {
public static Void main () { deck := Deck() deck.shuffle Card[] hand := deck.deal (7) echo ("Dealt hand is:") hand.each |card| { echo (card.toStr) } echo ("Remaining deck is:") deck.show }
} </lang>
Fortran
<lang fortran>MODULE Cards
IMPLICIT NONE
TYPE Card CHARACTER(5) :: value CHARACTER(8) :: suit END TYPE Card
TYPE(Card) :: deck(52), hand(52) TYPE(Card) :: temp
CHARACTER(5) :: pip(13) = (/"Two ", "Three", "Four ", "Five ", "Six ", "Seven", "Eight", "Nine ", "Ten ", & "Jack ", "Queen", "King ", "Ace "/) CHARACTER(8) :: suits(4) = (/"Clubs ", "Diamonds", "Hearts ", "Spades "/) INTEGER :: i, j, n, rand, dealt = 0 REAL :: x
CONTAINS
SUBROUTINE Init_deck ! Create deck DO i = 1, 4 DO j = 1, 13 deck((i-1)*13+j) = Card(pip(j), suits(i)) END DO END DO END SUBROUTINE Init_deck SUBROUTINE Shuffle_deck ! Shuffle deck using Fisher-Yates algorithm DO i = 52-dealt, 1, -1 CALL RANDOM_NUMBER(x) rand = INT(x * i) + 1 temp = deck(rand) deck(rand) = deck(i) deck(i) = temp END DO END SUBROUTINE Shuffle_deck
SUBROUTINE Deal_hand(number) ! Deal from deck to hand INTEGER :: number DO i = 1, number hand(i) = deck(dealt+1) dealt = dealt + 1 END DO END SUBROUTINE
SUBROUTINE Print_hand ! Print cards in hand DO i = 1, dealt WRITE (*, "(3A)") TRIM(deck(i)%value), " of ", TRIM(deck(i)%suit) END DO WRITE(*,*) END SUBROUTINE Print_hand SUBROUTINE Print_deck ! Print cards in deck DO i = dealt+1, 52 WRITE (*, "(3A)") TRIM(deck(i)%value), " of ", TRIM(deck(i)%suit) END DO WRITE(*,*) END SUBROUTINE Print_deck
END MODULE Cards</lang> Example use: <lang fortran>PROGRAM Playing_Cards
USE Cards CALL Init_deck CALL Shuffle_deck CALL Deal_hand(5) CALL Print_hand CALL Print_deck
END PROGRAM</lang> This creates a new deck, shuffles it, deals five cards to hand, prints the cards in hand and then prints the cards remaining in the deck.
Go
<lang go>package main
import (
"fmt" "math/rand" "time"
)
func main() {
rand.Seed(time.Now().UnixNano()) d := newDeck() fmt.Println("fresh deck") fmt.Println(d)
d.shuffle() fmt.Println("\nshuffled") fmt.Println(d)
h := d.deal(5) fmt.Println("\n5 cards delt") fmt.Println(h)
fmt.Println("\npip, suit values of cards in hand:") fmt.Println("pip suit") for _, c := range h { fmt.Printf("%3d %3d\n", c.pip(), c.suit()) } fmt.Print("\n", len(d), " cards left in deck\n") fmt.Println(d)
}
// card type. (deck type defined later) // valid range is 0..51. this facilititates computations. type card int
// zero-based pip/suit functions. useful for computations. // (or maybe just reference for computations, since they are trivial) func (c card) pip0() int {
return int(c % 13)
}
func (c card) suit0() int {
return int(c / 13)
}
func (c card) pipSuit0() (int, int) {
return int(c % 13), int(c / 13)
}
// one-base pip/suit functions. meaningful for output. // ("pip" does really mean the identifying number of spots on the card) func (c card) pip() int {
return int(c%13) + 1
}
func (c card) suit() int {
return int(c/13) + 1
}
func (c card) pipSuit() (int, int) {
return int(c%13) + 1, int(c/13) + 1
}
// string representation const pipS = "A23456789TJQK" const suitS = "CDHS"
func (c card) String() string {
px, sx := c.pipSuit0() return pipS[px:px+1] + suitS[sx:sx+1]
}
// deck type type deck []card
// "constructor" returns pointer to new deck object func newDeck() deck {
d := make(deck, 52) for i := range d { d[i] = card(i) } return d
}
// string representation: 13 cards to a line, up to four lines. // lines separated with newline character. empty deck is empty string. func (d deck) String() string {
if len(d) == 0 { return "" } r := d[0].String() for i, c := range d[1:] { if i%13 == 12 { r += "\n" } else { r += " " } r += c.String() } return r
}
// shuffle in place (although using extra memory) func (d deck) shuffle() {
d2 := make(deck, len(d)) copy(d2, d) for i, s := range rand.Perm(len(d)) { d[i] = d2[s] }
}
// return requested number of cards as new deck object. // the deck being delt from (the method reciever) is resliced. func (d *deck) deal(n int) deck {
if n > len(*d) { return nil } r := make(deck, n) copy(r, *d) *d = (*d)[n:] return r
}</lang> Output:
fresh deck AC 2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC AD 2D 3D 4D 5D 6D 7D 8D 9D TD JD QD KD AH 2H 3H 4H 5H 6H 7H 8H 9H TH JH QH KH AS 2S 3S 4S 5S 6S 7S 8S 9S TS JS QS KS shuffled AH KD 6C KS KH TS 7C 2C 4H 9C 5H KC 3S JH TH 5S QS JD 2D 7S 8H 8C 4D 9H QH TD 5C 3H 3C 8D AC TC JS 6S 9D 7D 6H QD 9S 8S 7H 4S 2H 4C QC 3D AD AS JC 5D 2S 6D 5 cards delt AH KD 6C KS KH pip, suit values of cards in hand: pip suit 1 3 13 2 6 1 13 4 13 3 47 cards left in deck TS 7C 2C 4H 9C 5H KC 3S JH TH 5S QS JD 2D 7S 8H 8C 4D 9H QH TD 5C 3H 3C 8D AC TC JS 6S 9D 7D 6H QD 9S 8S 7H 4S 2H 4C QC 3D AD AS JC 5D 2S 6D
Haskell
Straightforward implementation with explicit names for pips and suits. A deck is just a list of cards. Dealing consists of splitting off cards from the beginning of the list by the usual pattern matching (not shown). Printing is automatic. Purely functional shuffling is a bit tricky, so here we just do the naive quadratic version. This also works for other than full decks. <lang haskell>import System.Random
data Pip = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten |
Jack | Queen | King | Ace deriving (Ord, Enum, Bounded, Eq, Show)
data Suit = Diamonds | Spades | Hearts | Clubs
deriving (Ord, Enum, Bounded, Eq, Show)
type Card = (Pip, Suit)
fullRange :: (Bounded a, Enum a) => [a] fullRange = [minBound..maxBound]
fullDeck :: [Card] fullDeck = [(pip, suit) | pip <- fullRange, suit <- fullRange]
insertAt :: Int -> a -> [a] -> [a] insertAt 0 x ys = x:ys insertAt n _ [] = error "insertAt: list too short" insertAt n x (y:ys) = y : insertAt (n-1) x ys
shuffle :: RandomGen g => g -> [a] -> [a] shuffle g xs = shuffle' g xs 0 [] where
shuffle' g [] _ ys = ys shuffle' g (x:xs) n ys = shuffle' g' xs (n+1) (insertAt k x ys) where (k,g') = randomR (0,n) g</lang>
Icon and Unicon
<lang Icon>procedure main(arglist)
cards := 2 # cards per hand players := 5 # players to deal to
write("New deck : ", showcards(D := newcarddeck())) # create and show a new deck write("Shuffled : ", showcards(D := shufflecards(D))) # shuffle it
H := list(players) every H[1 to players] := [] # hands for each player
every ( c := 1 to cards ) & ( p := 1 to players ) do put(H[p], dealcard(D)) # deal #players hands of #cards
every write("Player #",p := 1 to players,"'s hand : ",showcards(H[p])) write("Remaining: ",showcards(D)) # show the rest of the deck
end
record card(suit,pip) #: datatype for a card suit x pip
procedure newcarddeck() #: return a new standard deck local D
every put(D := [], card(suits(),pips())) return D
end
procedure suits() #: generate suits
suspend !["H","S","D","C"]
end
procedure pips() #: generate pips
suspend !["2","3","4","5","6","7","8","9","10","J","Q","K","A"]
end
procedure shufflecards(D) #: shuffle a list of cards
every !D :=: ?D # see INL#9 return D
end
procedure dealcard(D) #: deal a card (from the top)
return get(D)
end
procedure showcards(D) #: return a string of all cards in the given list (deck/hand/etc.) local s
every (s := "") ||:= card2string(!D) || " " return s
end
procedure card2string(x) #: return a string version of a card
return x.pip || x.suit
end</lang> Sample output:
New deck : 2H 3H 4H 5H 6H 7H 8H 9H 10H JH QH KH AH 2S 3S 4S 5S 6S 7S 8S 9S 10S JS QS KS AS 2D 3D 4D 5D 6D 7D 8D 9D 10D JD QD KD AD 2C 3C 4C 5C 6C 7C 8C 9C 10C JC QC KC AC Shuffled : 5H 8S AC 5D 3H 9D 4S 3S 2C AD JD QH 6D 7H 4C 8H 3C KH 6S 10D 4D 8D AH 7D QS 2S QD 6H 9C KS JC 2D 10H JH 5S 2H 3D 10C 4H KC JS 8C 7S 10S KD 9S 6C 9H 7C AS QC 5C Player #1's hand : 5H 9D Player #2's hand : 8S 4S Player #3's hand : AC 3S Player #4's hand : 5D 2C Player #5's hand : 3H AD Remaining: JD QH 6D 7H 4C 8H 3C KH 6S 10D 4D 8D AH 7D QS 2S QD 6H 9C KS JC 2D 10H JH 5S 2H 3D 10C 4H KC JS 8C 7S 10S KD 9S 6C 9H 7C AS QC 5C
J
Solution:
<lang j>NB. playingcards.ijs
NB. Defines a Rosetta Code playing cards class
NB. Multiple decks may be used, one for each instance of this class.
coclass 'rcpc' NB. Rosetta Code playing cards class
NB. Class objects Ranks=: _2 ]\ ' A 2 3 4 5 6 7 8 910 J Q K' Suits=: ucp '♦♣♥♠' DeckPrototype=: (] #: i.@:*/)Ranks ,&# Suits
NB. Class methods create=: monad define
1: TheDeck=: DeckPrototype
)
destroy=: codestroy
sayCards=: ({&Ranks@{. , {&Suits@{:)"1
shuffle=: monad define
1: TheDeck=: ({~ ?~@#) TheDeck
)
NB.*dealCards v Deals y cards [to x players] NB. x is: optional number of players, defaults to one NB. Used monadically, the player-axis is omitted from output. dealCards=: verb define
{. 1 dealCards y
'Too few cards in deck' assert (# TheDeck) >: ToBeDealt=. x*y CardsOffTop=. ToBeDealt {. TheDeck TheDeck =: ToBeDealt }. TheDeck (x,y)$ CardsOffTop
)
NB.*pcc v "Print" current contents of the deck. pcc=: monad define
sayCards TheDeck
)
newDeck_z_=: conew&'rcpc'</lang>
Example use: <lang j> load '~user/playingcards.ijs'
coinsert 'rcpc' NB. insert rcpc class in the path of current locale pc=: newDeck $TheDeck__pc
52 2
shuffle__pc
1
sayCards 2 dealCards__pc 5 NB. deal two hands of five cards 3♦ 4♦ K♠ A♦ K♦
5♠
10♣
Q♥ 2♣ 9♣ $TheDeck__pc NB. deck size has been reduced by the ten cards dealt
42 2
destroy__pc
1</lang>
Java
<lang java>public enum Pip { Two, Three, Four, Five, Six, Seven,
Eight, Nine, Ten, Jack, Queen, King, Ace }</lang>
<lang java>public enum Suit { Diamonds, Spades, Hearts, Clubs }</lang>
The card: <lang java>public class Card {
private final Suit suit; private final Pip value;
public Card(Suit s, Pip v) { suit = s; value = v; }
public String toString() { return value + " of " + suit; }
}</lang> The deck: <lang java>import java.util.Collections; import java.util.LinkedList;
public class Deck {
private final LinkedList<Card> deck= new LinkedList<Card>();
public Deck() { for (Suit s : Suit.values()) for (Pip v : Pip.values()) deck.add(new Card(s, v)); }
public Card deal() { return deck.poll(); }
public void shuffle() { Collections.shuffle(deck); // I'm such a cheater }
public String toString(){ return deck.toString(); }
}</lang>
JavaScript
<lang javascript>function Card(pip, suit) {
this.pip = pip; this.suit = suit;
this.toString = function () { return this.pip + ' ' + this.suit; };
}
function Deck() {
var pips = '2 3 4 5 6 7 8 9 10 Jack Queen King Ace'.split(' '); var suits = 'Clubs Hearts Spades Diamonds'.split(' '); this.deck = []; for (var i = 0; i < suits.length; i++) for (var j = 0; j < pips.length; j++) this.deck.push(new Card(pips[j], suits[i]));
this.toString = function () { return '[' + this.deck.join(', ') + ']'; }; this.shuffle = function () { for (var i = 0; i < this.deck.length; i++) this.deck[i] = this.deck.splice( parseInt(this.deck.length * Math.random()), 1, this.deck[i])[0]; };
this.deal = function () { return this.deck.shift(); };
}</lang>
K
The deck is stored in the global variable "deck".
Create the deck. <lang K> v:"A23456789TJQK" / values
s:"SHCD" / suites
/ create a new deck newdeck:{deck::,/s,'\:v} newdeck();</lang>
Show the deck. <lang K> show:{`0:$,/-3$$deck}
show()
SA S2 S3 S4 S5 S6 S7 S8 S9 ST SJ SQ SK HA H2 H3 H4 H5 H6 H7 H8 H9 HT HJ HQ HK CA C2 C3 C4 C5 C6 C7 C8 C9 CT CJ CQ CK DA D2 D3 D4 D5 D6 D7 D8 D9 DT DJ DQ DK </lang>
Shuffle the deck. <lang K> shuffle:{deck::(-#deck)?deck}
shuffle();show()
S8 CA D5 D2 SJ D6 DJ H7 S4 S9 SQ SK S5 D8 C4 HT DA H3 S6 S2 DT HA C2 C5 D9 ST C7 DK S3 HQ D7 DQ C8 D3 SA CJ CQ CT H4 H2 CK H9 H5 C3 C6 H6 D4 HJ C9 S7 HK H8 </lang>
Deal: Get the N top cards and remove them from the deck. Deal 5 cards. <lang K> deal1:{|((#deck)-x)_|deck}
deal:{c:deal1[x];deck::(deck _dvl c);c}
deal[5]
("S8"
"CA" "D5" "D2" "SJ")
#deck / 5 cards are removed
47</lang>
Deal 3 more hands. <lang K> {deal@5}'!3 (("D6"
"DJ" "H7" "S4" "S9") ("SQ" "SK" "S5" "D8" "C4") ("HT" "DA" "H3" "S6" "S2"))</lang>
We now have 32 cards left. <lang K> #deck 32
show()
DT HA C2 C5 D9 ST C7 DK S3 HQ D7 DQ C8 D3 SA CJ CQ CT H4 H2 CK H9 H5 C3 C6 H6 D4 HJ C9 S7 HK H8</lang>
Liberty BASIC
<lang lb> Dim deckCards(52)
Dim holdCards(1, 1)
Print "The Sorted Deck"
Call sortDeck Call dealDeck
Print: Print Print "The Shuffled Deck"
Call shuffleDeck Call dealDeck
Print: Print
nPlayers = 4 nCards = 5 ct = 0 Redim holdCards(nPlayers, nCards)
Print "Dealing ";nCards;" cards to ";nPlayers;" players"
For i = 1 to nPlayers Print "Player #";i,, Next i Print For i = 1 to nCards For j = 1 to nPlayers ct = ct + 1 holdCards(j, i) = deckCards(ct) card = deckCards(ct) value = value(card) suit$ = suit$(card) pip$ = pip$(value) Print card;": ";pip$;" of ";suit$, Next j Print Next i
Print: Print
Print "The cards in memory / array" For i = 1 to nPlayers Print "Player #";i;" is holding" For j = 1 to nCards card = holdCards(i, j) value = value(card) suit$ = suit$(card) pip$ = pip$(value) Print card;": ";pip$;" of ";suit$ Next j Print Next i
End
Sub dealDeck
For i = 1 to 52 card = deckCards(i) value = value(card) suit$ = suit$(card) pip$ = pip$(value) Print i, card, value, pip$;" of ";suit$ Next i
End Sub
Sub sortDeck
For i = 1 to 52 deckCards(i) = i Next i
End Sub
Sub shuffleDeck
For i = 52 to 1 Step -1 x = Int(Rnd(1) * i) + 1 temp = deckCards(x) deckCards(x) = deckCards(i) deckCards(i) = temp Next i
End Sub
Function suit$(deckValue)
cardSuit$ = "Spades Hearts Clubs Diamonds" suit = Int(deckValue / 13) If deckValue Mod 13 = 0 Then suit = suit - 1 End If suit$ = Word$(cardSuit$, suit + 1)
End Function
Function value(deckValue)
value = deckValue Mod 13 If value = 0 Then value = 13 End If
End Function
Function pip$(faceValue)
pipLabel$ = "Ace Deuce Three Four Five Six Seven Eight Nine Ten Jack Queen King" pip$ = Word$(pipLabel$, faceValue)
End Function</lang>
Logo
<lang logo>make "suits {Diamonds Hearts Clubs Spades} make "pips {Ace Two Three Four Five Six Seven Eight Nine Ten Jack Queen King}
to card :n
output (sentence item 1 + modulo :n 13 :pips "of item 1 + int quotient :n 13 :suits)
end
to new.deck
make "deck listtoarray iseq 0 51 make "top 1
end
to swap :i :j :a
localmake "t item :i :a setitem :i :a item :j :a setitem :j :a :t
end to shuffle.deck
for [i [count :deck] 2] [swap 1 + random :i :i :deck]
end
to show.deck
for [i :top [count :deck]] [show card item :i :deck]
end
to deal.card
show card item :top :deck make "top :top + 1
end
new.deck shuffle.deck repeat 5 [deal.card]</lang>
Lua
<lang Lua> suits = {"Clubs", "Diamonds", "Hearts", "Spades"} faces = {2,3,4,5,6,7,8,9,10,"Jack","Queen","King","Ace"} --a stack is a set of cards. a stack of length 1 acts as a card; the stack constructor only creates decks.
stack = setmetatable({ --shuffles a stack __unm = function(z)
local ret = {} for i = #z, 1, -1 do ret[#ret + 1] = table.remove(z,math.random(i)) end return setmetatable(ret, stack)
end, --puts two stacks together __add = function(z, z2)
for i = 1, #z2 do z[#z+1] = table.remove(z2) end return z
end, --removes n cards from a stack and returns a stack of those cards __sub = function(z, n)
local ret = {} for i = 1, n do ret[i] = table.remove(z) end return setmetatable(ret, stack)
end, --breaks a stack into n equally sized stacks and returns them all deal = function(z, n)
local ret = {} for i = 1, #z/n do ret[i] = table.remove(z) end if n > 1 then return setmetatable(ret, stack), stack.deal(z,n-1) else return setmetatable(ret, stack) end
end, --returns a and b as strings, concatenated together. Simple enough, right? __concat = function(a, b)
if getmetatable(a) == stack then return stack.stackstring(a) .. b else return a .. stack.stackstring(b) end
end, stackstring = function(st, ind)
ind = ind or 1
if not st[ind] then return "" end return st[ind] and (faces[math.ceil(st[ind]/4)] .. " of " .. suits[st[ind]%4+1] .. "\n" .. stack.stackstring(st, ind+1)) or "" end}, { --creates a deck __call = function(z)
local ret = {} for i = 1, 52 do ret[i] = i end return -setmetatable(ret,z)
end})
print(stack() .. "\n") a, b, c, d = stack.deal(stack(), 4) print(a .. "\n\n\n") print(b + c .. "\n\n\n") print(d - 4 .. "") print(-b .. "") </lang>
M4
<lang M4>define(`randSeed',141592653)dnl define(`setRand',
`define(`randSeed',ifelse(eval($1<10000),1,`eval(20000-$1)',`$1'))')dnl
define(`rand_t',`eval(randSeed^(randSeed>>13))')dnl define(`random',
`define(`randSeed',eval((rand_t^(rand_t<<18))&0x7fffffff))randSeed')dnl
define(`for',
`ifelse($#,0,``$0, `ifelse(eval($2<=$3),1, `pushdef(`$1',$2)$4`'popdef(`$1')$0(`$1',incr($2),$3,`$4')')')')dnl
define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')')dnl define(`_arg1', `$1')dnl define(`_foreach', `ifelse(`$2', `()', `',
`define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')')dnl
define(`new',`define(`$1[size]',0)')dnl define(`append',
`define(`$1[size]',incr(defn(`$1[size]')))`'define($1[defn($1[size])],$2)')
define(`deck',
`new($1)foreach(`x',(Ace,2,3,4,5,6,7,8,9,10,Jack,Queen,King), `foreach(`y',(Clubs,Diamonds,Hearts,Spades), `append(`$1',`x of y')')')')dnl
define(`show',
`for(`x',1,defn($1[size]),`defn($1[x])ifelse(x,defn($1[size]),`',`, ')')')dnl
define(`swap',`define($1[$2],defn($1[$4]))define($1[$4],$3)')dnl define(`shuffle',
`for(`x',1,defn($1[size]), `swap($1,x,defn($1[x]),eval(1+random%defn($1[size])))')')dnl
define(`deal',
`ifelse($#,0,``$0, `ifelse(defn($1[size]),0, `NULL', defn($1[defn($1[size])])define($1[size],decr(defn($1[size]))))')')dnl
dnl deck(`b') show(`b') shuffling shuffle(`b') show(`b') deal deal(`b') deal deal(`b') show(`b')</lang>
Mathematica
<lang Mathematica>MakeDeck[] := Tuples[{{"Ace ", 2, 3 , 4 , 5, 6 , 7 , 8 , 9 , 10, "Jack" , "Queen", "King"}, {♦ , ♣, ♥ , ♠}}] DeckShuffle[deck_] := RandomSample[deck, Length@deck] DealFromDeck[] := (Print@First@deck; deck = deck2 ;; All;)</lang> Example usage:
deck = DeckShuffle@MakeDeck[]; Print[deck] ->{{10,♥},{10,♦},{5,♣},{7,♠},{4,♦},{8,♦},{4,♠},{Queen,♠},{5,♠},{4,♥},{9,♦},{King,♥},{2,♦},{Ace ,♦}, {3,♣},{6,♦},{Jack,♣},{10,♠},{2,♠},{3,♠},{9,♠},{King,♠},{Queen,♥},{8,♣},{King,♦},{6,♣},{4,♣},{Jack,♦}, {5,♦},{Ace ,♣},{2,♣},{8,♥},{Jack,♠},{5,♥},{7,♣},{8,♠},{King,♣},{Queen,♦},{9,♥},{Ace ,♥},{3,♦},{7,♥}, {Queen,♣},{10,♣},{3,♥},{2,♥},{Jack,♥},{7,♦},{6,♠},{6,♥},{Ace ,♠},{9,♣}} DealFromDeck[] DealFromDeck[] DealFromDeck[] ->{10,♥} ->{10,♦} ->{5,♣} Print[deck] ->{{7,♠},{4,♦},{8,♦},{4,♠},{Queen,♠},{5,♠},{4,♥},{9,♦},{King,♥},{2,♦},{Ace ,♦},{3,♣},{6,♦},{Jack,♣}, {10,♠},{2,♠},{3,♠},{9,♠},{King,♠},{Queen,♥},{8,♣},{King,♦},{6,♣},{4,♣},{Jack,♦},{5,♦},{Ace ,♣},{2,♣}, {8,♥},{Jack,♠},{5,♥},{7,♣},{8,♠},{King,♣},{Queen,♦},{9,♥},{Ace ,♥},{3,♦},{7,♥},{Queen,♣},{10,♣}, {3,♥},{2,♥},{Jack,♥},{7,♦},{6,♠},{6,♥},{Ace ,♠},{9,♣}}
MUMPS
OCaml
Straightforward implementation with algebraic types for the pips and suits, and lists of their values. A deck is an array of cards. <lang ocaml>type pip = Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten |
Jack | Queen | King | Ace
let pips = [Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten;
Jack; Queen; King; Ace]
type suit = Diamonds | Spades | Hearts | Clubs let suits = [Diamonds; Spades; Hearts; Clubs]
type card = pip * suit
let full_deck = Array.of_list (List.concat (List.map (fun pip -> List.map (fun suit -> (pip, suit)) suits) pips))
(* Fisher-Yates shuffle *) let shuffle deck =
for i = Array.length deck - 1 downto 1 do let j = Random.int (i+1) in (* swap deck.(i) and deck.(j) *) let temp = deck.(i) in deck.(i) <- deck.(j); deck.(j) <- temp done</lang>
PARI/GP
<lang parigp>name(n)=Str(["A",2,3,4,5,6,7,8,9,10,"J","Q","K"][(n+3)>>2],["h","d","s","c"][n%4+1]); newdeck()={
v=vector(52,i,i);
}; deal()={
my(n=name(v[1])); v=vecextract(v,2^#v-2); n
}; printdeck(){
apply(name,v)
}; shuffle()={
forstep(n=#v,2,-1, my(i=random(n)+1,t=v[i]); v[i]=v[n]; v[n]=t ); v
};</lang>
Pascal
See Delphi
Perl
<lang perl>package Playing_Card_Deck;
use strict;
@Playing_Card_Deck::suits = qw
[Diamonds Clubs Hearts Spades];
@Playing_Card_Deck::pips = qw
[Two Three Four Five Six Seven Eight Nine Ten Jack King Queen Ace];
- I choose to fully qualify these names rather than declare them
- with "our" to keep them from escaping into the scope of other
- packages in the same file. Another possible solution is to use
- "our" or "my", but to enclose this entire package in a bare block.
sub new
- Creates a new deck-object. The cards are initially neatly ordered.
{my $invocant = shift; my $class = ref($invocant) || $invocant; my @cards = (); foreach my $suit (@Playing_Card_Deck::suits) {foreach my $pip (@Playing_Card_Deck::pips) {push(@cards, {suit => $suit, pip => $pip});}} return bless([@cards], $class);}
sub deal
- Removes the top card of the given deck and returns it as a hash
- with the keys "suit" and "pip".
{return %{ shift( @{shift(@_)} ) };}
sub shuffle
- Randomly permutes the cards in the deck. It uses the algorithm
- described at:
- http://en.wikipedia.org/wiki/Fisher-Yates_shuffle#The_modern_algorithm
{our @deck; local *deck = shift; # @deck is now an alias of the invocant's referent. for (my $n = $#deck ; $n ; --$n) {my $k = int rand($n + 1); @deck[$k, $n] = @deck[$n, $k] if $k != $n;}}
sub print_cards
- Prints out a description of every card in the deck, in order.
{print "$_->{pip} of $_->{suit}\n" foreach @{shift(@_)};}</lang>
Some examples of use: <lang perl>my $deck = new Playing_Card_Deck; $deck->shuffle; my %card = $deck->deal; print uc("$card{pip} OF $card{suit}\n"); $deck->print_cards;</lang> This creates a new deck, shuffles it, removes the top card, prints out that card's name in all caps, and then prints the rest of the deck.
Perl 6
<lang perl6>enum Pip <A 2 3 4 5 6 7 8 9 10 J Q K>; enum Suit <♦ ♣ ♥ ♠>;
class Card {
has Pip $!pip; has Suit $!suit;
method Str { $!pip ~ $!suit }
}
class Deck {
has Card @!cards;
submethod BUILD { @!cards = pick *, map { Card.new(:$^pip, :$^suit) }, (Pip.keys X Suit.keys); }
method shuffle { @!cards .= pick: * }
method deal { shift @!cards }
method Str { ~@!cards }
}</lang>
Some examples of use:
<lang perl6>my Deck $d = Deck.new; say "Deck: $d"; my $top = $d.deal; say "Top card: $top"; $d.shuffle; say "Deck, re-shuffled: ", $d;</lang>
Output:
Deck: 3♦ J♦ 4♥ 7♠ 7♣ 7♥ 9♣ K♥ 6♠ 2♦ 3♠ Q♥ 8♥ 2♥ J♥ 5♥ 8♦ 8♣ 6♦ 7♦ 5♦ 2♣ 4♦ 8♠ 9♥ 4♣ 3♥ K♠ 2♠ 5♣ Q♣ Q♦ K♦ 4♠ 9♦ Q♠ 5♠ 6♥ J♣ J♠ K♣ 9♠ 3♣ 6♣
Top card: 3♦
Deck, re-shuffled: K♦ 4♣ J♠ 2♥ J♥ K♣ 6♣ 5♠ 3♥ 6♦ 5♦ 4♠ J♣ 4♦ 6♥ K♥ 7♥ 7♦ 2♦ 4♥ 6♠ 7♣ 9♦ 3♣ 3♠ 2♣ 2♠ 8♦ 5♣ 9♠ 5♥ J♦ 9♥ Q♦ Q♣ Q♥ Q♠ 8♥ 8♠ K♠ 9♣ 8♣ 7♠
PicoLisp
<lang PicoLisp>(de *Suits
Club Diamond Heart Spade )
(de *Pips
Ace 2 3 4 5 6 7 8 9 10 Jack Queen King )
(de mkDeck ()
(mapcan '((Pip) (mapcar cons *Suits (circ Pip))) *Pips ) )
(de shuffle (Lst)
(by '(NIL (rand)) sort Lst) )</lang>
Prolog
<lang Prolog>/** <module> Cards
A card is represented by the term "card(Pip, Suit)". A deck is represented internally as a list of cards.
Usage: new_deck(D0), deck_shuffle(D0, D1), deck_deal(D1, C, D2).
- /
- - module(cards, [ new_deck/1, % -Deck
deck_shuffle/2, % +Deck, -NewDeck deck_deal/3, % +Deck, -Card, -NewDeck print_deck/1 % +Deck ]).
%% new_deck(-Deck) new_deck(Deck) :-
Suits = [clubs, hearts, spades, diamonds], Pips = [2, 3, 4, 5, 6, 7, 8, 9, 10, jack, queen, king, ace], setof(card(Pip, Suit), (member(Suit, Suits), member(Pip, Pips)), Deck).
%% deck_shuffle(+Deck, -NewDeck) deck_shuffle(Deck, NewDeck) :-
length(Deck, NumCards), findall(X, (between(1, NumCards, _I), X is random(1000)), Ord), pairs_keys_values(Pairs, Ord, Deck), keysort(Pairs, OrdPairs), pairs_values(OrdPairs, NewDeck).
%% deck_deal(+Deck, -Card, -NewDeck) deck_deal([Card|Cards], Card, Cards).
%% print_deck(+Deck) print_deck(Deck) :-
maplist(print_card, Deck).
% print_card(+Card) print_card(card(Pip, Suit)) :-
format('~a of ~a~n', [Pip, Suit]).
</lang>
PureBasic
This approach keeps track of the cards in an abbrieviated form but allows them to be expanded to a more wordy form when they are dealt or shown. <lang PureBasic>#MaxCards = 52 ;Max Cards in a deck Structure card
pip.s suit.s
EndStructure
Structure _membersDeckClass
*vtable.i size.i ;zero based count of cards present cards.card[#MaxCards] ;deck content
EndStructure
Interface deckObject
Init() shuffle() deal.s(isAbbr = #True) show(isAbbr = #True)
EndInterface
Procedure.s _formatCardInfo(*card.card, isAbbr = #True)
;isAbbr determines if the card information is abbrieviated to 2 characters Static pips.s = "2 3 4 5 6 7 8 9 10 Jack Queen King Ace" Static suits.s = "Diamonds Clubs Hearts Spades" Protected c.s If isAbbr c = *card\pip + *card\suit Else c = StringField(pips,FindString("23456789TJQKA", *card\pip, 1), " ") + " of " c + StringField(suits,FindString("DCHS", *card\suit, 1)," ") EndIf ProcedureReturn c
EndProcedure
Procedure setInitialValues(*this._membersDeckClass)
Protected i, c.s Restore cardDat For i = 0 To #MaxCards - 1 Read.s c *this\cards[i]\pip = Left(c, 1) *this\cards[i]\suit = Right(c, 1) Next
EndProcedure
Procedure.s dealCard(*this._membersDeckClass, isAbbr)
;isAbbr is #True if the card dealt is abbrieviated to 2 characters Protected c.card If *this\size < 0 ;deck is empty ProcedureReturn "" Else c = *this\cards[*this\size] *this\size - 1 ProcedureReturn _formatCardInfo(@c, isAbbr) EndIf
EndProcedure
Procedure showDeck(*this._membersDeckClass, isAbbr)
;isAbbr determines if cards are shown with 2 character abbrieviations Protected i For i = 0 To *this\size Print(_formatCardInfo(@*this\cards[i], isAbbr)) If i <> *this\size: Print(", "): EndIf Next PrintN("")
EndProcedure
Procedure shuffle(*this._membersDeckClass)
;works with decks of any size Protected w, i Dim shuffled.card(*this\size) For i = *this\size To 0 Step -1 w = Random(i) shuffled(i) = *this\cards[w] If w <> i *this\cards[w] = *this\cards[i] EndIf Next For i = 0 To *this\size *this\cards[i] = shuffled(i) Next
EndProcedure
Procedure newDeck()
Protected *newDeck._membersDeckClass = AllocateMemory(SizeOf(_membersDeckClass)) If *newDeck *newDeck\vtable = ?vTable_deckClass *newDeck\size = #MaxCards - 1 setInitialValues(*newDeck) EndIf ProcedureReturn *newDeck
EndProcedure
DataSection
vTable_deckClass: Data.i @setInitialValues() Data.i @shuffle() Data.i @dealCard() Data.i @showDeck() cardDat: Data.s "2D", "3D", "4D", "5D", "6D", "7D", "8D", "9D", "TD", "JD", "QD", "KD", "AD" Data.s "2C", "3C", "4C", "5C", "6C", "7C", "8C", "9C", "TC", "JC", "QC", "KC", "AC" Data.s "2H", "3H", "4H", "5H", "6H", "7H", "8H", "9H", "TH", "JH", "QH", "KH", "AH" Data.s "2S", "3S", "4S", "5S", "6S", "7S", "8S", "9S", "TS", "JS", "QS", "KS", "AS"
EndDataSection
If OpenConsole()
Define deck.deckObject = newDeck() Define deck2.deckObject = newDeck()
If deck = 0 Or deck2 = 0 PrintN("Unable to create decks") End EndIf
deck\shuffle() PrintN("Dealt: " + deck\deal(#False)) PrintN("Dealt: " + deck\deal(#False)) PrintN("Dealt: " + deck\deal(#False)) PrintN("Dealt: " + deck\deal(#False)) deck\show() deck2\show()
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit") Input() CloseConsole()
EndIf</lang> Sample output:
Dealt: Queen of Hearts Dealt: 6 of Hearts Dealt: 6 of Diamonds Dealt: 2 of Spades 5D, QS, 9C, 7D, 3S, TC, 6S, 8H, 3D, KH, 2D, 2H, 5S, 4D, 4H, KS, 6C, 9S, KD, JH, 3C, TD, 4C, AH, JD, 8S, 3H, AS, QC, 4S, 8D, AD, 5H, 9H, 7C, 8C, 9D, TH, 5C, JS, 7S, TS, QD, JC, 2C, AC, 7H, KC 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, TD, JD, QD, KD, AD, 2C, 3C, 4C, 5C, 6C, 7C, 8C, 9C, TC, JC, QC, KC, AC, 2H, 3H, 4H, 5H, 6H, 7H, 8H, 9H, TH, JH, QH, KH, AH, 2S, 3S, 4S, 5S, 6S, 7S, 8S, 9S, TS, JS, QS, KS, AS
Python
<lang python>import random
class Card(object):
suits = ("Clubs","Hearts","Spades","Diamonds") pips = ("2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace")
def __init__(self, pip,suit): self.pip=pip self.suit=suit
def __str__(self): return "%s %s"%(self.pip,self.suit)
class Deck(object):
def __init__(self): self.deck = [Card(pip,suit) for suit in Card.suits for pip in Card.pips]
def __str__(self): return "[%s]"%", ".join( (str(card) for card in self.deck))
def shuffle(self): random.shuffle(self.deck)
def deal(self): self.shuffle() # Can't tell what is next from self.deck return self.deck.pop(0)</lang>
R
<lang R>pips <- c("2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace") suit <- c("Clubs", "Diamonds", "Hearts", "Spades")
- Create a deck
deck <- data.frame(pips=rep(pips, 4), suit=rep(suit, each=13))
shuffle <- function(deck) {
n <- nrow(deck) ord <- sample(seq_len(n), size=n) deck[ord,]
}
deal <- function(deck, fromtop=TRUE) {
index <- ifelse(fromtop, 1, nrow(deck)) print(paste("Dealt the", deck[index, "pips"], "of", deck[index, "suit"])) deck[-index,]
}
- Usage
deck <- shuffle(deck) deck deck <- deal(deck)
- While no-one is looking, sneakily deal a card from the bottom of the pack
deck <- deal(deck, FALSE)</lang>
REXX
<lang rexx>/* REXX ***************************************************************
- 1) Build ordered Card deck
- 2) Create shuffled stack
- 3) Deal 5 cards to 4 players each
- 4) show what cards have been dealt and what's left on the stack
- 05.07.2012 Walter Pachl
- /
colors='S H C D' ranks ='A 2 3 4 5 6 7 8 9 T J Q K' i=0 cards= ss= Do c=1 To 4
Do r=1 To 13 i=i+1 card.i=word(colors,c)word(ranks,r) cards=cards card.i End End
n=52 /* number of cards on deck */ Do si=1 To 51 /* pick 51 cards */
x=random(0,n-1)+1 /* take card x (in 1...n) */ s.si=card.x /* card on shuffled stack */ ss=ss s.si /* string of shuffled stack */ card.x=card.n /* replace card taken */ n=n-1 /* decrement nr of cards */ End
s.52=card.1 /* pick the last card left */ ss=ss s.52 /* add it to the string */ Say 'Ordered deck:' Say ' 'subword(cards,1,26) Say ' 'subword(cards,27,52) Say 'Shuffled stack:' Say ' 'subword(ss,1,26) Say ' 'subword(ss,27,52) si=52 deck.= Do ci=1 To 5 /* 5 cards each */
Do pli=1 To 4 /* 4 players */ deck.pli.ci=s.si /* take top of shuffled deck */ si=si-1 /* decrement number */ deck.pli=deck.pli deck.pli.ci /* pli's cards as string */ End End
Do pli=1 To 4 /* show the 4 dealt ... */
Say pli':' deck.pli End
Say 'Left on shuffled stack:' Say ' 'subword(ss,1,26) /* and what's left on stack */ Say ' 'subword(ss,27,6)</lang> Output:
Ordered deck: SA S2 S3 S4 S5 S6 S7 S8 S9 ST SJ SQ SK HA H2 H3 H4 H5 H6 H7 H8 H9 HT HJ HQ HK CA C2 C3 C4 C5 C6 C7 C8 C9 CT CJ CQ CK DA D2 D3 D4 D5 D6 D7 D8 D9 DT DJ DQ DK Shuffled stack: DJ D7 C6 DA HJ CJ D8 SA D2 DK C5 HA H9 SK ST DQ C3 SQ D5 CQ D3 S7 C9 HT CA CK S5 H3 S4 H5 S2 C2 HQ H2 S6 H6 H7 H8 S3 D4 D6 D9 HK CT C8 DT S8 SJ C7 C4 H4 S9 1: S9 SJ CT D4 H6 2: H4 S8 HK S3 S6 3: C4 DT D9 H8 H2 4: C7 C8 D6 H7 HQ Left on shuffled stack: DJ D7 C6 DA HJ CJ D8 SA D2 DK C5 HA H9 SK ST DQ C3 SQ D5 CQ D3 S7 C9 HT CA CK S5 H3 S4 H5 S2 C2
Ruby
<lang ruby>class Card
# class constants Suits = ["Clubs","Hearts","Spades","Diamonds"] Pips = ["2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace"] # class variables (private) @@suit_value = Hash[ Suits.each_with_index.to_a ] @@pip_value = Hash[ Pips.each_with_index.to_a ] attr_reader :pip, :suit def initialize(pip,suit) @pip = pip @suit = suit end def to_s "#{@pip} #{@suit}" end # allow sorting an array of Cards: first by suit, then by value def <=>(card) (@@suit_value[@suit] <=> @@suit_value[card.suit]).nonzero? or \ @@pip_value[@pip] <=> @@pip_value[card.pip] end
end
class Deck
def initialize @deck = [] for suit in Card::Suits for pip in Card::Pips @deck << Card.new(pip,suit) end end end def to_s "[#{@deck.join(", ")}]" end def shuffle! @deck.shuffle! self end def deal(*args) @deck.shift(*args) end
end
deck = Deck.new.shuffle! puts card = deck.deal hand = deck.deal(5) puts hand.join(", ") puts hand.sort.join(", ")</lang>
10 Clubs 8 Diamonds, Queen Clubs, 10 Hearts, 6 Diamonds, 4 Clubs 4 Clubs, Queen Clubs, 6 Diamonds, 8 Diamonds, 10 Hearts
Scheme
The procedure shuffle
requires an appropriate procedure random
to be
defined. Some Scheme implementations provide this as an extension.
<lang scheme>(define ranks
(quote (ace 2 3 4 5 6 7 8 9 10 jack queen king)))
(define suits
(quote (clubs diamonds hearts spades)))
(define new-deck
(apply append (map (lambda (suit) (map (lambda (rank) (cons rank suit)) ranks)) suits)))
(define (shuffle deck)
(define (remove-card deck index) (if (zero? index) (cdr deck) (cons (car deck) (remove-card (cdr deck) (- index 1))))) (if (null? deck) (list) (let ((index (random (length deck)))) (cons (list-ref deck index) (shuffle (remove-card deck index))))))
(define-syntax deal!
(syntax-rules () ((deal! deck hand) (begin (set! hand (cons (car deck) hand)) (set! deck (cdr deck))))))</lang>
Example: <lang scheme>(define deck
(shuffle new-deck))
(define hand
(list))
(deal! deck hand) (deal! deck hand) (deal! deck hand) (deal! deck hand) (deal! deck hand)
(display hand) (newline)</lang> Sample output:
((jack . hearts) (5 . clubs) (9 . hearts) (7 . clubs) (6 . spades))
Smalltalk
<lang smalltalk>Object subclass: #Card
instanceVariableNames: 'thePip theSuit' classVariableNames: 'pips suits' poolDictionaries: category: nil !
!Card class methods! initialize
suits ifNil: [ suits := 'clubs,hearts,spades,diamonds' subStrings: $, ]. pips ifNil: [ pips := '2,3,4,5,6,7,8,9,10,jack,queen,king,ace' subStrings: $, ]
! new
| o | o := super new. ^o
! new: card
| o | o := self new. o initWithPip: (card at: 1) andSuit: (card at: 2). ^o
!!
!Card class methods ! pips
Card initialize. ^pips
! suits
Card initialize. ^suits
!!
!Card methods! initWithPip: aPip andSuit: aSuit
( (pips includes: aPip asLowercase) & (suits includes: aSuit asLowercase) ) ifTrue: [ thePip := aPip copy. theSuit := aSuit copy ] ifFalse: [ 'Unknown pip or suit' displayOn: stderr . Character nl displayOn: stderr ]. ^self
! asString
^('(%1,%2)' % { thePip . theSuit })
! display
self asString display
! displayNl
self display. Character nl display
!!
Object subclass: #Deck
instanceVariableNames: 'deck' classVariableNames: poolDictionaries: category: nil !
!Deck class methods ! new
|d| d := super new. d init. ^d
!!
!Deck methods ! init
deck := OrderedCollection new. Card suits do: [ :suit | Card pips do: [ :pip | deck add: (Card new: { pip . suit }) ] ]
! deck
^deck
! shuffle
1 to: self deck size do: [ :i | |r2 o| r2 := Random between: 1 and: self deck size. o := self deck at: i. self deck at: i put: (self deck at: r2). self deck at: r2 put: o ]. ^self
! display
self deck do: [ :card | card displayNl ]
! deal
^self deck removeFirst
!!
"create a deck, shuffle it, remove the first card and display it" Deck new shuffle deal displayNl.</lang>
Note: there's something odd with the class method for getting pips and suits; it's because I've not understood how to initialize class variables to certain values without the need to explicitly call a method to do so.
Tcl
<lang tcl>package require Tcl 8.5
namespace eval playing_cards {
variable deck #variable suits {C D H S} variable suits {\u2663 \u2662 \u2661 \u2660} variable pips {2 3 4 5 6 7 8 9 10 J Q K A} proc new_deck {} { variable deck set deck [list] for {set i 0} {$i < 52} {incr i} { lappend deck $i } } proc shuffle {} { variable deck # shuffle in place for {set i 51} {$i > 0} {incr i -1} { set n [expr {int($i * rand())}] set card [lindex $deck $n] lset deck $n [lindex $deck $i] lset deck $i $card } } proc deal Template:Num 1 { variable deck incr num -1 set cards [lrange $deck 0 $num] set deck [lreplace $deck 0 $num] return $cards } proc card2string {card} { variable suits variable pips set suit [expr {$card / 13}] set pip [expr {$card % 13}] return [format "%2s %s" [lindex $pips $pip] [lindex $suits $suit]] } proc print {cards args} { array set opts [concat -sort false $args] if {$opts(-sort)} { set cards [lsort -integer $cards] } foreach card $cards { puts [card2string $card] } } proc print_deck {} { variable deck print $deck }
}
playing_cards::new_deck playing_cards::shuffle set hand [playing_cards::deal 5] puts "my hand:" playing_cards::print $hand -sort true puts "\nthe deck:" playing_cards::print_deck</lang>
VBScript
Implementation
<lang vb> class playingcard dim suit dim pips end class
class carddeck private suitnames private pipnames private cardno private deck(52) private nTop
sub class_initialize dim suit dim pips suitnames = split("H,D,C,S",",") pipnames = split("A,2,3,4,5,6,7,8,9,10,J,Q,K",",") cardno = 0
for suit = 1 to 4 for pips = 1 to 13 set deck(cardno) = new playingcard deck(cardno).suit = suitnames(suit-1) deck(cardno).pips = pipnames(pips-1) cardno = cardno + 1 next next nTop = 0 end sub
public sub showdeck dim a redim a(51-nTop) for i = nTop to 51 a(i) = deck(i).pips & deck(i).suit next wscript.echo join( a, ", ") end sub
public sub shuffle dim r randomize timer for i = nTop to 51 r = int( rnd * ( 52 - nTop ) ) if r <> i then objswap deck(i),deck(r) end if next end sub
public function deal() set deal = deck( nTop ) nTop = nTop + 1 end function
public property get cardsRemaining cardsRemaining = 52 - nTop end property
private sub objswap( a, b ) dim tmp set tmp = a set a = b set b = tmp end sub end class </lang>
Invocation
<lang vb> dim pack set pack = new carddeck wscript.echo "--before shuffle" pack.showdeck pack.shuffle wscript.echo "--after shuffle" pack.showdeck
dim card for i = 1 to 52 set card = pack.deal next wscript.echo "--dealt a card, it's the", card.pips, "of", card.suit wscript.echo "--", pack.cardsRemaining, "cards remaining" if pack.cardsRemaining <> 0 then pack.showdeck end if
</lang>
Output
--before shuffle AH, 2H, 3H, 4H, 5H, 6H, 7H, 8H, 9H, 10H, JH, QH, KH, AD, 2D, 3D, 4D, 5D, 6D, 7D, 8D, 9D, 10D, JD, QD, KD, AC, 2C, 3C, 4C, 5C, 6C, 7C, 8C, 9C, 10C, JC, QC, KC, AS, 2S, 3S, 4S, 5S, 6S, 7S, 8S, 9S, 10S, JS, QS, KS --after shuffle QD, QH, 4S, KD, JC, 10H, JD, 6D, 2S, 4C, 4D, 8H, QC, 5S, JH, KS, 6H, 8S, 7D, 10D, AD, 9S, KH, 2D, 3S, AC, JS, 3D, 9D, 3H, 5C, 10S, KC, 6C, AH, AS, 6S, 5H, 3C, 4H, 9H, 8C, 7S, 9C, 10C, 2C, 7H, 5D, QS, 2H, 7C, 8D --dealt a card, it's the 8 of D -- 0 cards remaining
Vedit macro language
The deck is created in a free edit buffer, one line for each card. Each users hand is another edit buffer. There is no need for any routines to display the deck or a hand, since each of them is displayed in an edit window. <lang vedit>// Playing Cards, main program
Call("CREATE_DECK") Call("SHUFFLE_DECK")
- 21 = Buf_Switch(Buf_Free) // #21 = players hand, 1st player
- 1 = 5; Call("DEAL_CARDS") // deal 5 cards to player 1
- 22 = Buf_Switch(Buf_Free) // #22 = players hand, 2nd player
- 1 = 5; Call("DEAL_CARDS") // deal 5 cards to player 2
Buf_Switch(#10) BOF // display the deck Return
/////////////////////////////////////////////////////////////////////////// // // Create a deck into a new edit buffer. One text line for each card. //
- CREATE_DECK:
- 10 = Buf_Switch(Buf_Free) // Buffer @(#10) = the deck
RS(1, "Diamonds") RS(2, "Spades") RS(3, "Hearts") RS(4, "Clubs")
RS(11, " Jack") RS(12, "Queen") RS(13, " King") RS(14, " Ace")
for (#1=1; #1<5; #1++) {
for (#2=2; #2<15; #2++) { if (#2 < 11) { Num_Ins(#2, NOCR) // pip (2 to 10) as numeric } else { IT(@(#2)) // pip (11 to 14) as a word } IT(" of ") IT(@(#1)) IN // suit }
} Return
/////////////////////////////////////////////////////////////////////////// // // Shuffle the deck using Fisher-Yates algorithm //
- SHUFFLE_DECK:
Buf_Switch(#10) // the deck
- 90 = Time_Tick // seed for random number generator
- 91 = 51 // random numbers in range 0 to 50
for (#1=1; #1<52; #1++) {
Call("RANDOM") Goto_Line(Return_Value+1) Block_Copy(#1, #1, LINESET+DELETE) Reg_Copy(9, 1, DELETE) Goto_Line(#1) Reg_Ins(9)
} Return
//-------------------------------------------------------------- // Generate random numbers in range 0 <= Return_Value < #91 // #90 = Seed (0 to 0x7fffffff) // #91 = Scaling (0 to 0x10000)
- RANDOM:
- 92 = 0x7fffffff / 48271
- 93 = 0x7fffffff % 48271
- 90 = (48271 * (#90 % #92) - #93 * (#90 / #92)) & 0x7fffffff
Return ((#90 & 0xffff) * #91 / 0x10000)
///////////////////////////////////////////////////////////////////////////
//
// Deal #1 cards: move the cards from deck to current edit buffer
//
- DEAL_CARDS:
- 11 = Buf_Num // this buffer (players hand)
Buf_Switch(#10) // the deck BOF Reg_Copy(9, #1, DELETE) // pull the first #1 cards from the deck Buf_Switch(#11) // players hand Reg_ins(9) // insert the cards here Return</lang>
- Programming Tasks
- Games
- ACL2
- Ada
- ALGOL 68
- AutoHotkey
- BASIC
- BBC BASIC
- C
- C++
- C sharp
- Clojure
- Common Lisp
- Delphi
- D
- E
- Forth
- Fantom
- Fortran
- Go
- Haskell
- Icon
- Unicon
- J
- Java
- JavaScript
- K
- Liberty BASIC
- Logo
- Lua
- M4
- Mathematica
- MUMPS
- OCaml
- PARI/GP
- Pascal
- Perl
- Perl 6
- PicoLisp
- Prolog
- PureBasic
- Python
- R
- REXX
- Ruby
- Scheme
- Smalltalk
- Tcl
- VBScript
- Vedit macro language