Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

6 Deck Card Shuffling in Access 3

Status
Not open for further replies.

MacroScope

Programmer
Jul 17, 2010
286
US
I'm doing something not generally associated with Access. I'm writing an analytical blackjack program. Anyone familiar with Access knows that it can be instructed to do the things involved, namely count the hand, stand or hit at a certain level, and anything else required to play the game. My problem is that I've been unable to come up with a practical and fast shuffling routine, but I have special requirements.

I want the shuffled decks stored in a table for several reasons. I want to be able to compare two moves, say standing vs. hitting a 16 v 10. The only way that's possible is to be able to see what the next card would have been and then making a comparison of the results. Another reason is to be able to save really good or really poor decks so that they can be collected and strategies can be developed which are optimized to bad or good runs of cards.

Can anyone offer a means of shuffling 6 decks and storing the results in a table? I have been able to do it, but the wait is interminable, and I know there are much better ways out there. I just can't think of any!

Thanks for your help.
 
To all of you who offered ideas and suggestions, I wanted to pass this along. Someone in another forum in which I posted this question submitted the following. It's fast, and fulfills all my needs. I thought I'd pass it along for others to review. It's at
Thanks to everyone!
 
That's more-or-less just a very minor front end against the SQL query you showed earlier

>SELECT INTO randCards FROM sixdeck ORDER BY Rnd(<some_number_field>)

where

tblShoe = randCards
tblCards = sixdeck
Seed = <some_number_field> (with some minor additional work)

The solution is slightly and perhaps unnecessarily overcomplicated by expanding the randomization component as:

Int((97344-1+1)*Rnd([Seed])+1)

This will generate an integer random number between 1 and 97344, in an effort to avoid collisions in the generated numbers. Frankly

a) (97344-1+1) could be simplified to 97344 (although the selection of this number seems somewhat arbitary - I'm guessing this was ripped from some other program where the value of this number was relevant)

b) We don't actually need to do the scaling to an integer at all, and the example would still work. Just change the type od the Seed field in tblShoe to Numeric Double, and then the query qmakShoe becomes:

SELECT tblCard.CardID, tblCard.Suit, tblCard.Kind, tblCard.Deck, Rnd([Seed]) AS ShuffleSeed INTO tblShoe
FROM tblCard
ORDER BY Rnd([Seed]);

which you should now be able to see is pretty much your earlier SQL query - which, as I said before, is a reasonable solution given the small size of your source table.
 
Thanks again.

I have another question. This program has always been intended to be analytical, and I never considered making it "pretty". I only cared that it worked, and my original shuffle routine made no provision for suit since a six is a six.

However the shuffle routine I have now includes suits, and if it's not too much trouble I wouldn't mind adding graphics. Does anyone know how to call a specific card from cards.dll within Access? Is it even possible to do?
 
Shouldn't be too hard, at least to pull in an image. I've no idea how to pull it from a .dll, so maybe someone else knows that part. All you should need to do is have an image holder on the form, and then when the code runs, have it point the image holder to the correct image file/location.
 
Thanks again.

I have another question. This program has always been intended to be analytical, and I never considered making it "pretty". I only cared that it worked, and my original shuffle routine made no provision for suit since a six is a six.

However the shuffle routine I have now includes suits, and if it's not too much trouble I wouldn't mind adding graphics. Does anyone know how to call a specific card from cards.dll within Access? Is it even possible to do?

BTW, strong, the routine's author told me that the reason he chose 97344 was on a lark. It's actually 312 squared.
 
> the reason he chose 97344 was on a lark. It's actually 312 squared

But, as I say, isn't really needed

>Does anyone know how to call a specific card from cards.dll

Yes, I do.

And I even have some code that I wrote for VB. I just need to do a quick modification to have it running on an Access UserForm, and then I'll post it ...
 
Ok - you'll need a UserForm with a Frame and a COmmandButton on it. Then simply copy and paste this code into the userform's code module
Code:
[blue]Option Compare Database
Option Explicit

Private Declare Function cdtInit Lib "CARDS.DLL" (dx As Long, dy As Long) As Long
Private Declare Function cdtDrawExt Lib "CARDS.DLL" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal dx As Long, ByVal dy As Long, ByVal ordCard As Long, ByVal iDraw As Long, ByVal clr As Long) As Long

Private Declare Function cdtDraw Lib "CARDS.DLL" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal iCard As Long, ByVal iDraw As Long, ByVal clr As Long) As Long
Private Declare Function cdtTerm Lib "CARDS.DLL" () As Long

Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long

Private cdtWidth As Long
Private cdtHeight As Long

Private Enum cdtSuit
    ecsCLUBS = 0
    ecsDIAMONDS = 1
    ecsHEARTS = 2
    ecsSPADES = 3
End Enum

Private Enum cdtBacks
    ecbCROSSHATCH = 53
    ecbWEAVE1 = 54
    ecbWEAVE2 = 55
    ecbROBOT = 56
    ecbFLOWERS = 57
    ecbVINE1 = 58
    ecbVINE2 = 59
    ecbFISH1 = 60
    ecbFISH2 = 61
    ecbSHELLS = 62
    ecbCASTLE = 63
    ecbISLAND = 64
    ecbCARDHAND = 65
    ecbUNUSED = 66
    ecbTHE_X = 67
    ecbTHE_O = 68
End Enum

Private Enum iDraw
    Front = 0
    Back = 1 [green]'iCard parameter should range from 53 to 68 if IDraw parameter is set to this[/green]
End Enum

Private Sub CommandButton1_Click()
    Dim Card As Long
    Dim Suit As Long
    cdtInit cdtWidth, cdtHeight
    For Suit = ecsCLUBS To ecsSPADES
        For Card = 1 To 13
            cdtDraw GetDC(UserForm2.Frame1.[_GethWnd]), (Card - 1) * cdtWidth / 3 + Suit * 16, Suit * cdtHeight / 3, GetCard(Card, Suit), 0, RGB(127, 127, 127)
        Next
    Next
    cdtTerm
End Sub

[green]' CardValue ranges from 1 to 13[/green]
Private Function GetCard(CardValue As Long, Suit As cdtSuit) As Long
    GetCard = Suit + (CardValue - 1) * 4
End Function[/blue]
Note that this does rather assume that you have cards.dll in the system folder (which will not be the case on anything later than XP, I believe)
 
Thanks, strong. I waited to respond until after I played with the code and I've run into an error message which says "Object doesn't support this property or method."

Clearly that's a reference to the frame itself. Is it supposed to be unbound? I tried both bound and unbound and got the same message for both. What is the OLE class for the card images? Are there some settings that I'm missing?

Any guidance would be appreciated.
 
Which version of Access are you running? Access 2007 doesn't have any controls (frames included) that support (the hidden) _GethWnd method that existed on earlier versions of Access. Mind you, neither does it have UserForms in quite the way other Office 2007 (and earlier) apps do ...

If you ARE using Access 2007, then you should be able to remove the Frame, and then modify this bit of code

GetDC(UserForm2.Frame1.[_GethWnd])

to

GetDC(Me.Parent.hWnd)

 
I'm running 03. What type of frame should be used, bound or unbound? I'm assuming it's unbound, but as I said I get the same error message for both.
 
UserForm - NOT an Access Form. They are different things in versions of Access prior to 2007.
 
Hi. I decided to change my handle since its a little more reflective of what I do. I am not good with code but I'm crazy with macros.

I didn't recognize the difference between UserForm and a regular Access form and I spent a long time yesterday searching through threads and other online postings looking for instructions on how to build one. I didn't find anything that answered the question directly.

I can see that the code is directed to a UserForm, but is there any particular reason why it could not be done in a standard Access form? The regular form can have its own background code and it doesn't seem all that much different. If there's nothing excluding the use of cards.dll in a normal form I'd rather stick with what I know.

 
>instructions on how to build one

Open Access' VBA IDE. Select Insert from the menu, and select UserForm. That's it.

>but is there any particular reason why it could not be done in a standard Access form?

To display the cards from CARDS.DLL directly you need something called a Device Context (DC). It is much easier to get the DC of (a control on) a UserForm than it is to get the DC of an Access form. So, for the purposes of the example and speed of conversion from my original VB I went for simplicity.

As I said before I'm happy to provide guidance, but I'm not writing this all for you.
 
I suspected it was that easy, yet I dont' have that option available in the Insert menu. I have Procedure, Module, Class Module, and File as the only options. Any reason why I shouldn't have that option available?
 
Well, that sounds suspiciously like Access 2007's Insert menu.

I certainly cannot explain why the Access 2003 VBA IDE does not have UserForm on the Insert menu. It should do. It's on mine. On multiple machines. I have never encountered it being missing in my entire time using Access 2003, so I don't have a solution for you I'm afraid (there was a known problem when the Forms 2 library was not properly registered - a very infreqiuent occurrence - that would generate an error when you selected Insert UserForm, but the menu option would still be there). Perhaps someone else in this forum has some knowledge of this bug, and can assist.
 
What's strange is that in the Help file I find a reference to Userform Window and Userform Objects, but nothing that says how to create it, yet I also found the UserForm toolbar, all greyed out. There's absolutely nothing about it in the Insert menu, however. I hope someone has some info that will help get past this glitch.
 
I have a quick question. I note that there is a code command CreateForm. Is it possible via code to create a UserForm, and bypass the missing option on the Insert menu?
 
No, that's for creating an Access Form, not a UserForm.

Here's a quick question: can you insert a UserForm in any other Office application? If not, then it would suggest that the Forms 2 library (necessary for UserForms, and normally a default part of the Office install) is missing or incorrectly registered.

It is normally found here:

C:\WINDOWS\System32\FM20.DLL

and I'd suggest Googling for how to register a DLL
 
The FM20.dll file was right where is should have been, and yes, when I opened Word it was right there in the Insert menu! Go figure!
 
Well, something is clearly broken in your Access install then ...
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top