Playing cards

From Rosetta Code
Revision as of 07:06, 21 January 2011 by rosettacode>Dingowolf (→‎{{header|D}}: clear the messy , redo)
Task
Playing cards
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.

Ada

See Playing Cards/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:

<lang algol68>MODE CARD = STRUCT(STRING pip, suit); # instance attributes #

  1. class members & attributes #

STRUCT(

 PROC(REF CARD, STRING, STRING)VOID init, 
 FORMAT format,
 PROC(REF CARD)STRING repr,
 []STRING suits, pips

) class card = (

  1. PROC init = # (REF CARD self, STRING pip, suit)VOID:(
   pip OF self:=pip;
   suit OF self :=suit
 ),
  1. format = # $"("g" OF "g")"$,
  2. PROC repr = # (REF CARD self)STRING: (
   HEAP STRING out; putf(BOOK out,(format OF class card,self)); out
 ),
  1. suits = # ("Clubs","Hearts","Spades","Diamonds"),
  2. pips = # ("2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace")

);

MODE DECK = STRUCT(REF[]CARD deck); # instance attributes #

  1. class members & attributes #

STRUCT(

 PROC(REF DECK)VOID init, shuffle, 
 PROC(REF DECK)STRING repr, 
 PROC(REF DECK)CARD deal

) class deck = (

  1. 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
 ),

  1. 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,

  1. 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
 ),

  1. PROC deal = # (REF DECK self)CARD: (
   (shuffle OF class deck)(self);
   (deck OF self)[UPB deck OF self]
 )

);

  1. associate a STRING with a FILE for easy text manipulation #

OP BOOK = (REF STRING string)REF FILE:(

 HEAP FILE book;
 associate(book, string);
 book

);

  1. 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

Works with: QuickBASIC version QBX 7.1

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

C

See Playing Cards/C

C++

Works with: g++ version 4.1.2 20061115 (prerelease) (SUSE Linux)

Since all the functions are quite simple, they are all defined inline <lang cpp>#ifndef CARDS_H_INC

  1. define CARDS_H_INC
  1. include <deque>
  2. include <algorithm>
  3. include <ostream>
  4. 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;
 }

}

  1. 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>

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>

D

Works with: D version 2.051

<lang d>import std.stdio, std.random, std.algorithm, std.regexp ;

import std.string : rjust = rjustify, ljust = ljustify ;

enum Suit = ["Club", "Heart", "Diamond", "Spade"] ; enum Pip = ["Ace","2","3","4","5","6","7","8","9","10","J","Q","K"]; enum NSuit = Suit.length ; enum NPip = Pip.length ; enum NPack = Suit.length*Pip.length ;

struct Card {

   static bool RankAceTop = true ;
   int pip, suit ;
   string toString() {
       return (Pip[pip].rjust(3) ~ " of "~ Suit[suit].ljust(7)).rjust(15) ;
   }
   int order() @property {
       auto pipOrder = (!RankAceTop) ? pip : ((pip != 0) ? pip - 1 : 12) ;
       return pipOrder * Suit.length + suit ;
   }
   int opCmp(Card rhs) { return order - rhs.order ; }
   bool opEqual(Card rhs) { return pip == rhs.pip && suit == rhs.suit; }

}

class Deck {

   private Card[] cards ;
   this(bool initShuffle = true, int pack = 0) {
       cards.length = 0 ;
       foreach(p;0..pack)
           foreach(c;0..NPack)
               cards ~= Card((c / NSuit) % NPip, c % NSuit) ;
       if(initShuffle) randomShuffle(cards) ;
   }
   int length() @property { return cards.length ; }
   Deck add(Card c) { cards ~= c; return this ; }
   Deck deal(int loc, Deck toDeck = null) {
       if(toDeck !is null) toDeck.add(cards[loc]) ;
       cards = cards[0..loc]~cards[loc+1..$] ;
       return this ;
   }
   Deck dealTop(Deck toDeck = null) { return deal(length - 1, toDeck) ; }
   Card opIndex(int loc) { return cards[loc] ; }
   alias opIndex peek ;
   Deck showDeck() { writeln(this) ; return this ; }
   Deck shuffle() {
       randomShuffle(cards) ;
       return this ;
   }
   Deck sortDeck() {
       sort!"a>b"(cards) ;
       return this ;
   }
   string toString() {
       auto s = reduce!`a~","~b`(map!`format("%s", a)`(cards)) ;
       return s.sub("([^,]+,[^,]+,[^,]+,[^,]+),", "$1\n", "g") ;
   }

} void main() {

   Deck[4] guests ;
   foreach(ref g ; guests)
       g = new Deck; // empty deck
   Deck 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>

E

See Playing Cards/E

Forth

Works with: GNU 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>

Fortran

Works with: Fortran version 90 and later

<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.

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

Icon

<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

Unicon

This Icon solution works in Unicon.

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

Works with: Java version 1.5+

<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>

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>

Works with: UCB 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>

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>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>

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];
  1. I choose to fully qualify these names rather than declare them
  2. with "our" to keep them from escaping into the scope of other
  3. packages in the same file. Another possible solution is to use
  4. "our" or "my", but to enclose this entire package in a bare block.

sub new

  1. 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

  1. Removes the top card of the given deck and returns it as a hash
  2. with the keys "suit" and "pip".
{return %{ shift( @{shift(@_)} ) };}

sub shuffle

  1. Randomly permutes the cards in the deck. It uses the algorithm
  2. described at:
  3. 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

  1. 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

Works with: Rakudo version Star

<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

Translation of: Common Lisp

<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

Works with: SWI Prolog version 4.8.0

<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")

  1. 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,]   

}

  1. Usage

deck <- shuffle(deck) deck deck <- deal(deck)

  1. While no-one is looking, sneakily deal a card from the bottom of the pack

deck <- deal(deck, FALSE)</lang>

Ruby

Translation of: Python
Works with: Ruby version 1.8.7+

<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

Works with: Scheme version RRS

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: <lang>((jack . hearts) (5 . clubs) (9 . hearts) (7 . clubs) (6 . spades))</lang>

Smalltalk

Works with: GNU 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")

  1. 21 = Buf_Switch(Buf_Free) // #21 = players hand, 1st player
  2. 1 = 5; Call("DEAL_CARDS") // deal 5 cards to player 1
  3. 22 = Buf_Switch(Buf_Free) // #22 = players hand, 2nd player
  4. 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:
  1. 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

  1. 90 = Time_Tick // seed for random number generator
  2. 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:
  1. 92 = 0x7fffffff / 48271
  2. 93 = 0x7fffffff % 48271
  3. 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:
  1. 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>