Put Freecell Cards into Excel or Access


I am planning to write a program to play freecell.

It is possible to start a freecell game and then put the starting data into Excel or into an array manually....but what I would like to do is take the starting cards on the screen and put them into an Excel sheet or an Access table directly from the screen with VB code or whatever
Office type technique .

This is a real challange well worth 200 points.

Who is Participating?

Improve company productivity with a Business Account.Sign Up

garethdConnect With a Mentor Commented:
Hi Leo,

Didn't like leaving my previous comment up in the air but unfortunately my C/C++ knowledge does not extend to writing DLL's......so here is a workable (maybe not ultra elegent) solution.

The solution is in 2 parts:

Part 1: Use a C program based on the original authors (Jim Horne) C routine to generate the card numbers to a file. (see code below)

This program accepts 2 parameters 1) GameNumber as String and 2) FilePath\FileName as a string

The created file is a Comma Delimetered (CSV) format that Excel can read, The default file is created in the same folder that you put the program in. (default file name is "@FreeCell@GameNumber")

Part 2. A simple Vis.Basic sub to call the C routine and then read in the values from the newly created file the end result of this routine is an array of integers 7 rows by 8 columns representing the deal layout


The Cards are represented by the numbers 0 thru 51 and can be defined as follows:

            Club      Diam      Heart      Spade

Ace            0      1      2      3  
Two            4      5      6      7
Three            8      9      10      11
Four            12      13      14      15
Five            16      17      18      19
Six            20      21      22      23
Seven            24      25      26      27
Eight            28      29      30      31
Nine            32      33      34      35
Ten            36      37      38      39
Jack            40      41      42      43
Queen            44      45      46      47
King            48      49      50      51

This means that the card SUIT can be determined by the formula (CardValue Mod 4) with 0=Clubs, 1=Diamonds, 2=Hearts, 3=Clubs

The actual card can be determinined by the formula ((CardValue/4) +1) to return a number between 1 and 13 with 1 the Ace and 13 the King

I am not certain why Jim Horne didnt alternate the suits so that a MOD 2 would have indicated Red or Black !!!!


You mentioned that you have the Visual C which is what I used to create the program as a "WIN32 Console" "Empty project" ( to eliminate all that complicated C++ stuff that I don't understand). However I could e-mail the executable if you wish.

Hope this is what u are looking for

Good Luck



Part 1 C Program by Jim Thorne with a few modifications by GarethD

#include <stdio.h>                // garethd
#include <stdlib.h>
#include <string.h>                        // garethd

int main(int argc, char* argv[])

#define     MAXPOS         21
#define     MAXCOL          9    // includes top row as column 0
int    card[MAXCOL][MAXPOS];    // current layout of cards, CARDs are

    int  i, j;                // generic counters
    int  col, pos;
    int  wLeft = 52;          // cards left to be chosen in shuffle
    int deck[52];            // deck of 52 unique cards

// GarethD Definitions
int GameNumber ;
char   FileName[256];
char  GameNumberChar[9];
int FileOK;
FILE *ptrFileName;

strcpy(GameNumberChar,"1");            // Default to Game 1
// GarethD Code to      
// Resolve the Game Number and File names AND CREATE THE FILE      
      if (argc > 1) strcpy(GameNumberChar,argv[1]);

      GameNumber = atoi(GameNumberChar);

      if (argc > 2)
            strcpy(FileName, argv[2]);

      FileOK = 0;
      if ( (ptrFileName = fopen( FileName, "w" )) != NULL) FileOK = 1;

      printf("[FreeCell Game # %d]\n",GameNumber);
      if (FileOK == 1)
      fprintf(ptrFileName,"[FreeCell Game # %d]\n",GameNumber);
wLeft = 52;
    for (col = 0; col < MAXCOL; col++)          // clear the deck
        for (pos = 0; pos < MAXPOS; pos++)
            card[col][pos] = 0;
    /* shuffle cards */

    for (i = 0; i < 52; i++)      // put unique card in each deck loc.
        deck[i] = i;

    srand(GameNumber);            // gamenumber is seed for rand()


    for (i = 0; i < 52; i++)
        j = rand() % wLeft;
        card[(i%8)+1][i/8] = deck[j];

// GarethD Code to      
// Print the results to the Window and to the named File
            printf("%00d,",deck[j]);                              // GarethD
            if (FileOK == 1) fprintf(ptrFileName,"%00d,",deck[j]); // GarethD

            if (i % 8 == 7)                                    // GarethD
            {                                                // GarethD
                  printf("\n") ;                              // GarethD
                  if (FileOK == 1) fprintf(ptrFileName,"\n");      // GarethD
            deck[j] = deck[--wLeft];
// GarethD to Close File      
      printf("\n\n") ;                                          // GarethD
      if (FileOK == 1)  fclose( ptrFileName);                        // GarethD

      return 0;

Part 2 Visual Basic Code

Sub GetDeal(gamenumber As Integer, FileName As String)

Dim Cards(7, 8) As Integer
Dim GameHeader As String
Dim inchar As String

' Call C routine to generate the deal

returnCode = Shell("c:\FreeCellDeal.exe " & gamenumber & " " & FileName, 6)

' Read the Deal File into Cards Array

Open FileName For Input As #1
COL = 0
ROW = 0

Line Input #1, Header  ' Read 1st line into header.

Do While Not EOF(1)   ' Loop until end of file.

inchar = Input(1, #1)
   If (inchar = ",") Then
        If (COL Mod 8) = 0 Then
            ROW = ROW + 1
            COL = 1
            COL = COL + 1
        End If
    Cards(ROW, COL) = CInt(Number)
    Number = ""
  Number = Number & inchar
  End If

Close #1

End Sub
You could use cards.dll :

Hi again,

Here's a link for cards32.dll

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

leojlAuthor Commented:
thanks for the input.
I did not know about those dll's
and they could be of interest to me
to use in the future.

however the dll's do not answer my question.

I wish to start a new game of freecell which will
put on my screen 8 columns of cards. Then I wish to
use an identifier for each card and put that identifier
into an Excel cell for each column.

I have choosen to designate cards as 1 through 13
with ace=1, then 2=2 ... 10=10 etc and then
jack=11, queen=12 and king=13.
spades=1,clubs=2,hearts=3 diamonds=4

Then use a decimal point between card value and suit
so that ,for example, a jack of diamonds would be
identified as 11.4  and a 5 of clubs as 5.2 etc.

This is completely arbitrary and I am open to suggestion
if there is already a standard... in fact my brief look
at the sites provided suggest that there must be a similar
identifier technique for the dll's.

So the task at hand is to have a computerized technique
to look at the 8 columns of cards at the start of a
freecell game and put the identifier for each card into
a corresponding cell in an Excel sheet.



You'll have to make your own Freecell game and place the data in Excel. You'll have to make a table of all the cards in the deck and randomly select cards that will be referenced in your grid.

Hi Leojl,

Here is some VBA code which will generate a deal in Freecell format onto a Excel worksheet called "Sheet1". The Randomized deal sequence is based on the same formula used to generate the actual Freecell deals and it generates numbers between 0 and 51 representing the cards. This is also how the cards are represented in CARDS/CARDS32.DLL , I believe.

The actual Freecell randomized deals are seeded with the game number as in this example but here the deal is different because the randomizer in VB (Access as well i think) returns a decimal value between 0 and 1 whereas the C compiler RAND() function returns an integer.

If you have access to a c compiler to create your own call to the RAND() function or you know how to access a C function from VB you could replace the line that reads:
j = Int(Rnd() * (cardsleft - 1))

with call to C routine as follows:

j = Rand() mod cardsleft

and your deals should come out the same as Freecell.

However, from your post I don't think you really need to generate the same deals as Freecell to create your own version of the game!

If you want to keep your designation for cards you can change the code but I like the simplicity of the 0 thru 51 personally.

Additionally for further coding purposes you might want to store the deal in an array as well as or instead of putting on the spreadsheet.

Info on the original algorithm by Jim Horne can be found at http://members.aol.com/wgreview/mshuffle.txt

If you want to contact me directly please e-mail to

Here is the VBA Subroutine, hope this helps

Public Sub gen_deal(GameNumber As Integer)

        Dim deck(0 To 51) As Integer
        Dim i, j, col, row, cardsleft As Integer
'Load 0 thru 51 to array representing deck of cards

        For i = 0 To 51
           deck(i) = i
' Set the Active Excel sheet to receive the deal


' Keep Count of Cards that Haven't yet been dealt
        cardsleft = 52
' Seed the randomizer with Game Number

        Rnd (-1) ' Reset Randomizer
        Randomize (GameNumber) 'Seed it

' Deal the Cards

    For i = 0 To 51
            ' Get next Random Number. and ensure it is
            'between 1 and number of cards left
        j = Int(Rnd() * (cardsleft - 1))
        col = (i Mod 8) + 1
        row = Int((i / 8)) + 1
       Worksheets("Sheet1").Cells(row, col).Value = deck(j)
       cardsleft = cardsleft - 1
      deck(j) = deck(cardsleft) 'fill spot used by lastcard
End Sub
leojlAuthor Commented:
hi all,

thanks for the input...i have been too busy to
really study the comments. my question is really
if I start a freecell game...such as game #68
, which is currently unsolved by us,  how can I get
the starting cards for game #68 and put them into my VB6 program.

Excel is not a problem....the question is to somehow
sweep across the monitor and detect card identifiers.

Ident by 0 thru 51 is ok if you provide the rule to go
from an integer to a specific card.
Hi Leojl,

Why do this complicated process of interfacing to a program that was not designed for such?

The cards are generated by the simple (public domain)algorithm that I sent earlier. This code I posted is a VB version of that exact same code used by Freecell which can be found at


This article was provided by the original auther of Freecell.

This algorithm uses a "Game Number" as the seed to a randomize routine to randomly generate the numbers 0 thru 51 representing your cards.

The only proviso for the VB code version (as I noted) is that the Rnd function in VB is different than the Rand function in C which is what Freecell uses.

This means that though the result is a genuine freecell deal it will differ from the same "Game Number" in Freecell.

It is now clear that rather than writing a Freecell program you are going to write a Freecell solver program.

Therefore you really need the same deal as the corresponding "Game number" in Freecell.

What remains to be done is:
Replace the one (1) line of code in the VB version with a call to the C routine rand() instead of the VB routine rnd(). Then seeding the routine with the "game number" will result in the exact same deal as Freecell.

The question is: what is the best way to use a C function in a VB program ? Maybe the whole thing should be done in C ?

Good Luck
leojlAuthor Commented:
hi again,

I am going to be out of town for a few days, but I
am not ignoring this question.....

If I could create the same cards with the game number as the random number seed that would indeed give me what I need ..... I will study your inputs while I am at the

I am quite good in Visual Basic. I recently bought Visual
C++ 6.0 , but I am just starting to learn C++ so there
will be some study to do something as complicated as getting the cards for freecell.

leojlAuthor Commented:
hello all

thanks much for the input.

I have not had time to actually apply the ideas so far.
I will be interested in the difference between random
numbers from C/C++ vs VB.   VB random numbers from rnd
are indeed random 0<rnd<1 (or are 0 or 1  possible?)  .
But VB rnd does NOT restart the same string of random
numbers when you try to randomize with the same seed.
The only way that I know to get the same sequence of random numbers from VB is to do randomize (start seed)
at the very start of a program.

sincerely ... leo
See my earlier comment, where I posted a deal generation routine in VB. As noted, this will NOT produce the same random sequence as C compiler that Freecell uses, but it does produce a legitimate deal. The use of the rnd(-1) in this routine will always reset the randomizer. Without this the randomizer users the previously returned random number as the next seed regardless of what you use in the rnd() function or randomize function.

The rnd() in VB and the RAND() in C are totally different beasts and will never produce the same set of random number no matter what you seed with.

VB returns a decimal number betweeen 0.000000 and 0.999999
which means you multiply by your upper boundary (in this case 52)to get what you want
whereas C returns an integer between 1 and 32,267 (or something close to this) which means you use MOD with your upper boundary

Hope this helps


leojlAuthor Commented:
I thank all for input..
I am going out of town again
so will accept this input and
evaluate it later..
sincerely .. leo
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.