Displaying playing cards for bridge

I love to play bridge. When I was a little kid, my parents played with their parents. I would put my palm on the table, and my dad would riffle shuffle on my hand. The thrills of childhood!


Nowadays I read bridge columns and try to play at the local bridge club whenever I can (which usually means when one of my brothers comes to visit).


I wrote the program below a long time ago: it deals and displays 4 hands of 13 cards each in a loop. Each hand is sorted and evaluated for the number of “high card points”. (Ace=4, King=3, Queen=2, and Jack=1.).  These are displayed and the statistics inserted into a cursor.



The primary purpose of this 150 line program was to calculate distributions. In bridge, the combined cards of North/South play against East/West. If NS have 9 spades between them, then the opponents have 4.


The actual distribution calculation is just a couple SQL select statements. Then a BROWSE with a calculated field based on 2 related cursors shows the results. The power of embedding data into the programming language!


How often is the distribution of those 4 spades split evenly amongst East/West  with 2 each ?  3-1?  4-0 ? The chance of an even split of 2-2  (40%) is actually lower in odds than 3-1 (50%)!. (see this link for more info)



Windows ships with cards.dll, which contains the pictures of playing cards, as well as the playing card backs. It’s used in solitaire, hearts, etc.


To find out what the exports of this DLL are, use link from Visual Studio to see the dll’s exports.


link /dump /exports c:\windows\system32\cards.dll


    ordinal hint RVA      name


          1    0 000013E0 WEP

          2    1 0000118A cdtAnimate

          3    2 00001813 cdtDraw

          4    3 000014F3 cdtDrawExt

          5    4 000013E6 cdtInit

          6    5 0000138B cdtTerm


Drawing cards is as simple as getting a Device Context (GetDC) and calling the cdtDraw  entry point of cards.dll.


The following Visual FoxPro program should run in most older versions.





#define NORTHx    150

#define NORTHy    0

#define EASTx     300

#define EASTy     140

#define SOUTHx    150

#define SOUTHy    280

#define WESTx     0

#define WESTy     140


DECLARE integer cdtInit IN cards.dll integer @, integer @

DECLARE integer cdtTerm IN cards.dll

DECLARE integer cdtDraw IN cards.dll integer, integer, integer, integer, integer, integer

DECLARE integer cdtDrawExt IN cards.dll integer, integer, integer, integer, integer, integer, integer, integer

DECLARE integer GetDC IN WIN32API integer

DECLARE integer ReleaseDC IN WIN32API integer, integer

DECLARE integer Sleep IN WIN32API integer

DECLARE integer ValidateRect IN WIN32API integer, string



FOR nloops = 1 to 1000

      IF CHRSAW()




      IF MOD(nloops,100) = 0





SELECT spades,count(*) FROM deals GROUP BY 1 INTO CURSOR foo

INDEX ON spades TAG spades


SELECT spades,spopp,count(*) FROM deals GROUP BY 1,2 INTO CURSOR foo2


BROWSE LAST NOWAIT FIELDS spades,spopp,cnt,pct=100*cnt / foo.cnt


DEFINE CLASS myform as Form





      xpix = 0

      ypix = 0

      DIMENSION crd[52]

      DIMENSION xlt[52]

      ADD OBJECT lblN as label WITH left=NORTHX, top = NORTHy+100

      ADD OBJECT lblE as label WITH left=EASTX, top = EASTy+100

      ADD OBJECT lblS as label WITH left=SOUTHX, top = SOUTHy+100

      ADD OBJECT lblW as label WITH left=WESTX, top = WESTy+100

      PROCEDURE init

            LOCAL i


            *crd 1-13 = 2-A clubs, 14-26 = 2-A Diam

            FOR i = 1 to 52

                  this.crd[i] = i


            *xlt 1-4 = A CDHS, 5-8 = 2 CDHS

            FOR i = 1 to 4

                  this.xlt[13 *i    ] = i - 1   && the aces


            FOR j = 2 to 13   && 2 thru K

                  FOR i = 0 to 3

                        this.xlt[j-2  + 13 *i+1] =  4*(j-1) + i



            CREATE CURSOR deals (north i, east i, south i, west i,spades i,spopp i)



            cdtInit(@xpix, @ypix)

            thisform.xpix = xpix

            thisform.ypix = ypix

      PROCEDURE shuffle

            LOCAL i, tmp

            FOR i = 1 to 52

                  nrnd = INT(RAND() * 52 )+1

                  tmp = this.crd[i]

                  this.crd[i] = this.crd[nrnd]

                  this.crd[nrnd] = tmp


      PROCEDURE sortem(nHand, xpos, ypos)

            LOCAL i,j, nSt, nEnd, tmp, npts, ndenom


            nSt = nHand * 13+1

            nEnd = nSt + 12

            FOR i = nSt to nEnd

                  FOR j = nSt to i-1

                        IF this.crd[i] > this.crd[j]

                              tmp = this.crd[i]

                              this.crd[i] = this.crd[j]

                              this.crd[j] = tmp




            hdc = GetDC(this.hwnd)

            FOR i = nSt to nEnd

                  ndenom = MOD(this.crd[i]-1, 13)

                  IF ndenom > 8

                        npts = npts + ndenom - 8


                  cdtDraw(hdc, xpos+(i-nSt)*12,ypos,this.xlt[this.crd[i]],0,0)


            ReleaseDC(this.hwnd, hdc)

            srect = this.ntox(0) + this.ntox(0) +     this.ntox(thisform.width) +  this.ntox(thisform.height)

            ValidateRect(this.HWnd, srect)

            RETURN npts

      PROCEDURE ntox(nPix)

            RETURN chr(MOD(npix,256)) + CHR(int(npix/256)) +CHR(0)+CHR(0)

      PROCEDURE dealem

            LOCAL nptsn,nptse, nptss, nptsw


            nptsn = this.sortem(0,NORTHx,NORTHy)

            nptse = this.sortem(2,EASTx, EASTy)

            nptss = this.sortem(1,SOUTHx,SOUTHy)

            nptsw = this.sortem(3,WESTx,WESTy)

            thisform.lbln.caption = TRANSFORM(nptsn)

            thisform.lble.caption = TRANSFORM(nptse)

            thisform.lbls.caption = TRANSFORM(nptss)

            thisform.lblw.caption = TRANSFORM(nptsw)

            nsp = 0

            FOR i = 1 to 26   && count spades in north & south hands

                  IF this.crd[i] > 39

                        nsp = nsp + 1



            *calc split by cnting how many in east

            nspe = 0

            FOR i = 27 to 39

                  IF this.crd[i] > 39

                        nspe = nspe + 1



*           thisform.lblw.caption = TRANSFORM(nsp)+","+TRANSFORM(nspe)

            IF nspe < (13 - nsp)/2  && if # of East's spades < half of E-W spades, then use cnt of spades in W

                  nspe = (13 - nsp) - nspe


            INSERT INTO deals VALUES (nptsn,nptse,nptss,nptsw,nsp,nspe)

      PROCEDURE destroy


      PROCEDURE xlate(nCrd as Integer)    && ncrd 0-51

            *0-13 = 2-A clubs

            LOCAL nsuit, nNum

            nSuit = int(nCrd/13)    && 0-3 for clubs-spades

            nNum = MOD(nCrd,13)           && 0 - 12 for 2 - A

            IF nNum = 12

                  nCrd = nSuit


                  nCrd = 4*(nNum + 1) + nSuit


            RETURN nCrd



Comments (8)

  1. Alan Biddle says:


    Great solution! One note… the "hdc = GetDC(this.hwnd)" call isn’t going to work in older versions of VFP that don’t have the hwnd property on the form.

    Fox rocks!

  2. Plinio says:

    I did not know there was a cards.dll !

  3. Koen Piller says:


    Very impressive. But somehow I am missing the point. Copy and Pasted your listing into a program: myBridge. Typed in command window DO myBridge. And MyForm shows, I see a counter below each hand, I see all the cards change at random, and can hardly finish this programm. Seem interesting to start a Bridge teaching programm, but what is the main purpose of your listing?


  4. Merlin Vilhauer says:

    Any chance you have this code in visual c++ ?

    you could send it to me via  vilhamm@aol.com

  5. Sam Hobbs says:

    Thank you for this; I am a little curious.

    I am a C++ programmer but not a FoxPro programmer. I tried to use this program in Visual FoxPro version 6 but I got an error saying that the HWND property is not found; the line is:

    hdc = GetDC(this.hwnd)

    in the sortem PROCEDURE. Should the program work in version 6?

    This is not important; I was just curious. I don’t need an answer. I found this page while searching for something else.

  6. Bill G. says:

    I'm trying to teach a small group of seniors who learned bridge when in college 50+ years ago. they know Goren well and are good players but I've talked them into learnign the new 2 over 1 bridge . I know nothing about programming but have set up a blog and would like to be able to display hands I could use to teach the new system. Any ideas on how I might do that and actually select  various hands of my choosing? thanks for any advice you might offer.

    Bill G.

Skip to main content