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.
 
Technically, no.

There are some realtively obscure ways of sort of achieving it - but I'd expect that, since UserForms seem to be broken on your machine, that even the obscure methods of importing a UserForm from another VBA IDE wouldn't work.

Have you tried repairing the Access install?
 
I was hunting for my disk before I got your post. It's got to be here somewhere...

I found it, and repaired the installation. Installation complete, errors corrected?

Well, no. After complete repair I have exactly the same situation. I even included a screenshot so you know I'm not losing my mind.

Any other ideas?
 
 http://www.mediafire.com/imageview.php?quickkey=0jebn0hutda9prn&thumb=4
After the repair I took your advice and googled Registering DLL, and found the steps here.
I entered Regsvr32 "C:\Windows\System32\cards.dll" in the run box, and received the following message.

C:\Windows\System32\cards.dll was loaded but the DllRegisterServer entry point was not found. This file can not be registered.

Any other ideas?
 
No, not cards.dll. You don't need to register that. It isn't a COM dll. I was talking about registering FM20.DLL - but that seems to be working fine if the other Office apps can insert a UserForm.

And if the repair of Access didn't bring the option back, then I'm afraid I don't know what else to suggest.

Anyone else out there ever encountered MacroScope's problem?

MacroScope, you may want to post the lack of a UserForm option on the Insert menu as a new thread (since it is not directy related to the topic of this thread)

 
I did start a new thread, but I was wondering whether you have the code already written somewhere that would allow the use of cards.dll in a regular Access form. Unless someone comes through with a solution I won't be able to do what I'd prefer to do, make it "pretty". It may be much easier with UserForm but that seems less and less likely to be an option for me.
 
I have a workaround to the Insert problem - customize the Insert menu in the IDE. You can add the UserForm command to it ...

Right-click IDE menubar, select 'Customize' from the menu that appears.

Select teh 'Commands' tab of the Customize dialog, then click 'Insert' under 'Categories'

Under Command you should now see all the available 'Insert' options, one of which is 'User Form'. Drag and drop this onto the 'Insert' menu on the menu bar.

 
Yer a friggin' genius, strong. Thanks! That solved it. I now have the UserForm option.

Unfortunately, I'm not out of the woods yet. When I try to draw a frame onto the UserForm, I get a message, "Not implemented", and clicking "Help" opens a blank help window with no text in it at all.

Also, once I have this actually working how do I switch to form view, and how do I bring the form up?
 
Are there any suggestions on what might be causing the "Not implemented" error message when trying to create a frame on a UserForm?
 
Here's a screenshot of the error message. I did a net search to see if there was something available but found nothing. Seems my only hope is starting a new thread.

Strong, do you have the code allowing cards.dll to be called from within an standard Access form written already?
 
 http://www.mediafire.com/imageview.php?quickkey=qtc6tpn82mrim3k&thumb=4
>do you have the code allowing cards.dll to be called from within an standard Access form written already?

If I'd had that I'd would have provided it in the first place ...


Still, I had a spare moment, so I've put this together for you. You'll need an Access form with a single button on it. Then copy and paste this code into the form'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 Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Const GW_CHILD = 5

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 'iCard parameter should range from 53 to 68 if IDraw parameter is set to this
End Enum

Private hWndMainPart

Private Sub Command0_Click()
    PaintCards
End Sub

' Find the hWnd for the display part of our Access form
Private Sub Form_Load()
    Dim strClass As String
    Dim result As Long
    
    Do
        hWndMainPart = FindWindowEx(Me.hwnd, hWndMainPart, "OFormSub", "")
        strClass = Space(256)
        result = GetClassName(GetWindow(hWndMainPart, GW_CHILD), strClass, 256)
        strClass = Left(strClass, result)
    Loop Until strClass = "OFEDT" Or hWndMainPart = 0

End Sub

' Optional - makes an effort to keep cards painted
Private Sub Form_Resize()
    PaintCards
End Sub



' CardValue ranges from 1 to 13
Private Function GetCard(CardValue As Long, Suit As cdtSuit) As Long
    GetCard = Suit + (CardValue - 1) * 4
End Function

Private Sub PaintCards()
    Dim Card As Long
    Dim Suit As Long
    
    If hWndMainPart Then
        cdtInit cdtWidth, cdtHeight
        For Suit = ecsCLUBS To ecsSPADES
            For Card = 1 To 13
                cdtDraw GetDC(hWndMainPart), (Card - 1) * cdtWidth / 3 + Suit * 16, Suit * cdtHeight / 3, GetCard(Card, Suit), 0, RGB(127, 127, 127)
            Next
        Next
        cdtTerm
    End If
End Sub[/blue]
 
Kind of off topic but, the embedded advertizing at the top of this forum is for customised playing cards (at least it is for me) Spooky.

*******************************************************
Occam's Razor - All things being equal, the simplest solution is the right one.
 
Thanks so much, strong. The routine worked as soon as I switched to form view, even without the Command Button, and it is great to be able to bring up the cards within Access. As I said early on, I never before considered making this program "pretty", but I'm definitely willing to put in the extra work to make it so now that I have the tools to work with. I know I'm within striking distance of it now.

I have a question. I don't understand how the cards display at even horizontal intervals. I would have assumed that it would have required image frames or something in order to provide them a place to land and display yet they just pop up on the surface of the form. How does that happen?

Can the card display be modified to align the cards diagonally or vertically?

kwbMitel, it sure is odd since the ad remains with the page. The word spooky is a bit mystical for me, but it's definitely weird.

 
>even without the Command Button

Correct

>I don't understand how the cards display at even horizontal intervals

cdtDraw GetDC(hWndMainPart), (Card - 1) * cdtWidth / 3 + Suit * 16, Suit * cdtHeight / 3, GetCard(Card, Suit), 0, RGB(127, 127, 127)

where cdtDraw is declared as:

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)

hdc - device context we want to draw on (a screen DC can be thought of as a drawing surface)
X - x origin for drawing card in pixels
Y - y origin for drawing card in pixels
iCard - specify the card we want to draw (1 - 68)*
iDraw - front or back of the card
clr - sets the background color for the ecbCrossHatch card back

*iCard should be 1 to 52 when iDraw specifies the front of the card, and 53 to 68 when iDraw specifies the back. When drawing the front, iCard is calculated by the simple formula [tt]value = suit + card * 4[/tt]; this calculation is carried out in my GetCard function (why bother with a function for this rather than doing it inline? becaue my original VB code that I adapted this from worked with both the 16-bit and 32-bit versions of cards.dll, and the 16-bit card library has a different calculation for the card value)

There is also a cdtDrawEx which allows us to stretch and shrink the size of the displayed image
 
You have been amazingly patient and helpful through this and I really feel indebted to you. Thanks. If you contact me privately I'd be happy to pay you back in a small way by sharing what I have already learned and will learn shortly about the game so you can take a few bucks home from the casino next time! Failing that, if you live anywhere near Southern California I'd love to buy you a beer at the very least!

There's one more thing that would really help me to see how this all goes together. I told you I'm not a code guy, but I can certainly manipulate code that's already written and make the changes needed to modify it for my purposes once I understand the parameters, as your last post helped me to do.

If it would not be too much of an imposition, I'd really like to see an example of how to interface that code with the outside world so that the next card stored in a table can be generated and displayed on the screen, perhaps with a button click stepping through one after the other. You've seen the shuffle routine I'm using, and the shuffled decks are stored in tblShoe.

The code you have offered generates a full deck of cards and provides the basics for display of cards.dll, but I really do need to see at least one example of how specific cards are actually drawn from the table for display on the screen, and also how to clear a card already displayed. Without those last missing links I'm still unable to follow this through to a working useful routine.
 
Strong, I waited several days before posting again. I assume that my request did not go over too well with you since you didn't respond. I'd just like to try again.

You're the only person that seems to know and understand how to use cards.dll within Access, not a common implementation to say the least. You hung in there and were greatly helpful in getting me to the point where the deck of cards can be displayed on an Access form. I'm almost home, but not far enough along that I can take it and run with it. That's why I'm writing again.

I am hoping that I can convince you to offer the last bit of assistance that will make it possible for me to actually use this in the program I'm creating.

I don't understand yet how to interface the code you offered with the table that carries the shuffled shoe. I'd really like to see something that would allow me to display the cards in the shoe one by one so that I can see how that is accomplished. Getting the deck to display on screen was a major step forward, but I'm just not at a point where it's useful to me yet, and I'm trying to get there.

The other thing that I need to know that will finally put me on the path I need is how to position the starting point where cards are displayed on screen. There are a minimum of seven starting points, six players and the dealer, and actually considerably more when you consider up to four splits per player, each with its own starting point for cards display.

I know how to write the routines to make the game play. I've already done that in fact, although I'm going to scrap it and start again because my original configuration only made allowance for one player. I originally used text boxes to display the card value (2, J, A, etc) but did not use graphics of any kind. As I have said, this is an analytical program and "pretty" was never really a consideration.

However, being as tantalizingly close to being able to utilize cards.dll as I am right now is both gratifying and frustrating at the same time, because I still don't have the final tools I need to use it.

I'm hoping you'll reconsider and will decide to help me across the finish line as you have through all the other steps up until now.

Regardless, I do appreciate the help you've offered up until now.
 

Just illustrative. Not a full solution. Not bomb proof. Contains more-or-less all the elements you'll need for shuffling and card display*. If, after all this, you can't tie this together into a proper solution of your own then I'm afraid that this whole task may be beyond your skill level ...

*Be warned - an Access 2003 form is heavily subclassed, and thus will often do horrendous things to the Device Context, which in turn means that our raw display of the cards may not always show what it ought to. Which is one of the reaons I originally elected to demonstrate this on a User Form, which does not suffer the same problems.
 
That's truly awesome, Strong. Thanks. I think there's enough there for me to manipulate and do what I want to do with it. I can see now how the elements work together, and now that I have it in a format that I can really see and examine I'm confident that I can make whatever changes are needed to turn it into a fully functional game.

Your help is most greatly appreciated, and I'm looking forward to working on this and creating a truly graphic game where none existed before.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top