[Newbies] The Bridge Playing example

Todd Blanchard tblanchard at mac.com
Mon Aug 25 07:16:03 UTC 2008

```I'm sitting here watching Bootcamp install Windows XP - guess I'll
kill some time. :-)

On Aug 24, 2008, at 4:58 PM, Andy Burnett wrote:

> Todd, thanks for writing that up. I found it really interesting to
> see how you tackled the problem.  I think it would be great if - as
> time permits - the experts of the list could take a problem - nice
> simple ones would be good, and show how you might solve it.  It is
> also very interesting to see how you refine/modify each others'
> solutions.

Well my knowledge of bridge is pretty superficial and it is possible I
have just hit the bottom.  You guys pose problems and I'm sure someone
will point you towards a solution.  I totally empathize with the whole
"Just can't get started" problem. Anyhow, some obvious initial
refinements:

1) Randal is absolutely right that the variables north,east,south,west
should probably be put into some kind of indexed storage because you
tend to access them in a kind of sequence (going around the circle
either playing or dealing) and you do the same thing to each.  So his
refinement

hands := IdentityDictionary newFrom:
(#(north east south west) collect: [:each | each -> Set new]).

is good.  It creates a dictionary where the keys are symbols and the
values are Sets.  So now, if you want north's cards, you say

(hands at: #north)

and to "go around the circle" you could say

#(north east south west) do: [:position | (hands at: position)
doSomethingOrOther ]

From a style perspective, I'm not thrilled about pulling things out
of dictionaries constantly and I'd be likely to implement accessors
for convenience

north
^ hands at: #north

because I think it is prettier to say

self north doSomethingOrOther

than

(hands at: #north) doSomethingOrOther

but you could argue that, given the cyclic nature of a card game,
you'd probably never use them.

2) How to model a hand

I started with OrderedCollection because cards are dealt in an order
and I half-thought the order might matter.  However, it turns out that
it doesn't really matter in Bridge which is probably why Randal chose
Set.  Set has no concept of ordering and has the added nice property
of disallowing a card from being in a hand twice, which is somewhat
more realistic in Bridge but not so much in a game like Pinochle where
you can have two of the same card.  You could solve that by using
IdentitySet I suppose.

Incidentally, that is why Card responds to bridgeDeck rather than just
made out of the same kinds of cards, but composed differently (I dated
a cards fiend in college - I've forgotten most of the rules but
remember a few basics).

Actually, in Bridge, players invariably sort their hands by suit, then
rank as soon as they are dealt so maybe a SortedCollection with a
custom sort block makes more sense.  At least if you are displaying
the cards to human users.  Something like:

bySuitsThenRank := : [:x :y | ((x suit) = (y suit)) ifTrue: [x rank <
y rank] ifFalse: [x suit < y suit]]. " block value is true if x and y
are in right order, false if not"

now you get

hands := IdentityDictionary newFrom:
(#(north east south west) collect: [:each | each ->
(SortedCollection sortBlock:  bySuitsThenRank) ]).

This gives me a typical hand looking like:
a SortedCollection(Ace of Clubs Jack of Clubs Ace of Hearts 3 of
Hearts 4 of Hearts 5 of Hearts Ace of Diamonds 6 of Diamonds 10 of

which is how I typically sort my bridge hands.

If you want to do your own card game, I recommend trying to write
blackjack.  That's a program I used to assign my C students.  Write a
program that lets a person play the computer (who is dealer). The
rules are dead easy (dealer hits on 16, stays on 17 I think) but there
are nuances in evaluating the current hand when aces are involved.
Also, in BJ, I'd go back to OrderedCollection for representing a hand
because order matters - the first card is the 'down' card and is not
revealed to the other players until the end of the round.

Just tossing ideas.

```