[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now


Put Freecell Cards into Excel or Access

Posted on 2001-08-19
Medium Priority
Last Modified: 2008-02-01

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.

Question by:leojl
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3

Expert Comment

ID: 6405234
You could use cards.dll :


Expert Comment

ID: 6405281
Hi again,

Here's a link for cards32.dll


Author Comment

ID: 6405367
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.


What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.


Expert Comment

ID: 6407433

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.


Expert Comment

ID: 6408254
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

Author Comment

ID: 6412490
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.

Expert Comment

ID: 6413635
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

Author Comment

ID: 6416525
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.


Accepted Solution

garethd earned 800 total points
ID: 6420590
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

Author Comment

ID: 6444246
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

Expert Comment

ID: 6446184
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



Author Comment

ID: 6452205
I thank all for input..
I am going out of town again
so will accept this input and
evaluate it later..
sincerely .. leo

Featured Post

Veeam Task Manager for Hyper-V

Task Manager for Hyper-V provides critical information that allows you to monitor Hyper-V performance by displaying real-time views of CPU and memory at the individual VM-level, so you can quickly identify which VMs are using host resources.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article describes how to import an Outlook PST file to Office 365 using a third party product to avoid Microsoft's Azure command line tool, saving you time.
Outlook for dependable use in a very small business   This article is about using the Outlook application (part of Microsoft Office) in a very small business, or for homeowners where dependability and reliability are critical requirements. This …
The viewer will learn how to simulate a series of coin tosses with the rand() function and learn how to make these “tosses” depend on a predetermined probability. Flipping Coins in Excel: Enter =RAND() into cell A2: Recalculate the random variable…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

656 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question