Thursday, January 11, 2007

"My first card game": Cassino

No, it's not my spellchecker that has suffered a nervous breakdown (although I wouldn't blame it if it did), I actually mean Cassino. You might not be familiar with this game, but it's quite a fun little math based card game, and since it's the first "real" card game I remember learning, I choose it some years ago to be the first card game I'd try to code. Coding for fun you know - not the "I-wanna-take-over-the- entire-gaming-industry" kind of code. So code I did.

For some years you've been able to see the result on cassino.thraen.dk (feel free to play). The game is pretty simple: 2 players get 4 cards each, plus 4 cards goes face up on the table. The players then take turn trying to gather points by matching table cards with cards on their hands, based on values. Read the detailed rules on Wikipedia.

I did the development in a couple of steps:

First I coded a general cassino library which contained classes for all the typical card game objects - like card, deck, hand, card-collection, etc. Then I also added some classes more specialized for this specific game like a cassino game class, card combination class, a computer player class and a point collection class (Note: this was back in the days of .NET framework 1.0, so I had to make custom collection classes to keep the code tidy. Imagine how it was to live in a world without Generics - incredible how we survived). I made the cards IComparable so it would be easy to sort a hand and check legal/illegal moves.


//Deal
for(int i=0;i<4;i++)
{
Player.AddCard(deck.DrawCard());
Computer.AddCard(deck.DrawCard());
}


The "computer intelligence" of the game is a simple algorithm that identifies all the options available to the computer and then makes a partially random decission which option to choose.
Afterwards I coded a webUI to it, pretty basic and pretty ugly. The only partially interesting thing there is the aspx page I made to show when cards on the table were combined. I needed something that would create the graphic of cards being located on top of each other, so I needed to dynamically merge the card graphics together. It resulted in this Page Load code for the CombiImage.aspx file:



private void Page_Load(object sender, System.EventArgs e)
{
Response.ContentType="image/gif";

//Request format= cards=xx.gif-yy.gif-zz.gif
string cardlist=(string)Request["cards"];
//cardlist="2c.gif-2d.gif-ac.gif";
string[] cardsrc=cardlist.Split(new char[]{'-'});

//Load cards
Bitmap[] cards=new Bitmap[cardsrc.Length];
for(int i=0;i<cards.Length;i++) cards[i]=(Bitmap) Bitmap.FromFile(Server.MapPath("Cards/"+cardsrc[i]));

int max=30;
Bitmap b=new Bitmap(cards[0].Width,cards[0].Height+((cards.Length-1)*max));

//Try a raw copy
int y=0;
for(int cur=0;cur<cards.Length;cur++)
for(int i=0;i<((cur!=(cards.Length-1))?max:cards[cur].Height);i++)
{
for(int x=0;x<cards[cur].Width;x++)
b.SetPixel(x,y,cards[cur].GetPixel(x,i));
y++;
}

Bitmap b2=new Bitmap((System.Drawing.Image)b,cards[0].Width,cards[0].Height);

b2.Save(Response.OutputStream,System.Drawing.Imaging.ImageFormat.Gif);
Response.End();
}

It's always fun to sit a several years later and look through some old code you've written...I always go through several phases.....pride, embarrasment, frustration and eventually I get so inspired by the ideas that I end up rewriting it all using everything I've learned since then and all the technology that has appeared in the mean time. Perhaps this little game will suffer the same fate - now when I look at it I get an itch in my fingers to clean up the code, add some better computer intelligence, AJAX'ify the UI and perhaps even add features like TopScore list, player-player games, etc. Drop a comment if you think it's a good idea :-)

And oh yeah - if you want to look at the old library I made (for a good laugh) you can download it here.

1 comment:

Adam said...

Hi Allan, i would like to extend the game...i have downloaded your library and use it....the object of the game cannot store in the viewstate, any ideas on doing it ?