Click here to Skip to main content
15,880,543 members
Articles / Multimedia / GDI+

HiLow Card Game

Rate me:
Please Sign up or sign in to vote.
2.67/5 (8 votes)
14 May 20073 min read 94.3K   2.7K   22   6
An article on creating a simple card game with C#, using updated card.dll wrapper class

HiLow Card Game

Introduction

This is a simple version of the card game HiLow that includes a high score table.

Background

In 2003, when I started to program with C#, I was interested in writing a card game. After some time, I found enough information to write a wrapper class to use the cards.dll that ships with Windows. This prompted me to write an article about the DLL that can be found here. Since then, I have been gradually improving it to a point where I feel it is now in a good enough state to be resubmitted. If you want to see the history of how I got to where the class is now, you can see this on my website.

HiLow Game

The game is simply based on guessing whether the next random card is higher or lower than the currently shown card. Each game costs 10 points, and if you guess four correct cards, you win 20 points. After playing for a while, guessing four correct cards is not as easy as it seems.

When you have either guessed four correct cards or you have lost the game, then the "Play Again" button appears.

The Wrapper Class

The first change to the cards.dll wrapper class is that it now implements IDisposable. This is to make sure that the graphics device context is cleaned up properly, as the class now has its own graphics surface to draw upon.

C#
/// <summary>
/// .NET Graphics surface used for drawing.
/// </summary>
private Graphics graphicsSurface;

/// <summary>
/// Win32 HDC surface use for Win32 drawing.
/// </summary>
private IntPtr graphicsDC;

In order to now use the class, we call Begin before any cards are drawn, and End when we have finished drawing our cards.

C#
protected override void OnPaint(PaintEventArgs e)
{
  // Allocate graphics device context
  cardDrawing.Begin( e.Graphics );

  // Do Card drawing
  . . .

  // Release graphics device context
  cardDrawing.End();

  // Draw anything else

  base.OnPaint(e);
}

Also, we need to ensure that the cards' Dispose method is called from the form.

C#
if( cardDrawing != null )
{
  cardDrawing.Dispose();
}

New Features

One of the nice new features of the class is the ability to draw a card rotated at any angle. So in order to draw the King of Hearts rotated at 90 degrees anti-clockwise from the top-left corner of the card, we would use the following line of code:

C#
cardDrawing.DrawRotatedCard( new Point(120,120), 90, 
       Card.ToCardIndex( CardSuit.Hearts, CardRank.King ) );

where cardDrawing is an instance of the Card class.

A Simple Deck Class

This application uses a simple class to represent a deck of cards. Rather than having an array of cards, we only need an array of integers, because the Card class only draws cards and nothing else.

C#
public class Deck
{
  private int[] CardArray = new int[52];

  /// <summary>
  /// Initializes deck with the 52 integers.
  /// </summary>
  public Deck()
  {
    // Deck uses RankCollated cards 0 - 51
    for( int i = 0; i < 52; i++ )
    {
      CardArray[i] = i;
    }
  }
}

This makes it easy to implement a shuffle routine, which is very random in nature.

C#
/// <summary>
/// Randomly rearrange integers
/// </summary>
public void Shuffle()
{
  int[] newArray = new int[52];
  bool[] used = new bool[52];

  for( int j = 0; j < 52; j++ )
  {
    used[j] = false;
  }

  Random rnd = new Random();
  int iCount = 0;
  int iNum;

  while( iCount < 52 )
  {
    iNum = rnd.Next( 0, 52 ); // between 0 and 51

    if( used[iNum] == false )
    {
      newArray[iCount] = iNum;
      used[iNum] = true;
      iCount++;
    }
  }

  // Load original array with shuffled array
  CardArray = newArray;
}

Finally, the current integer stored in our array is accessed to know which card to draw.

C#
/// <summary>
/// Obtains a card number from the deck.
/// </summary>
public int GetCard( int arrayNum )
{
  if (arrayNum >= 0 && arrayNum <= 51)
    return CardArray[arrayNum];
  else
    throw (new System.ArgumentOutOfRangeException("arrayNum", arrayNum,
      "Value must be between 0 and 51."));
}

Reusing Code

Whilst making this game, I decided that I wanted a high score table. Rather than re-inventing the wheel so to speak, I have incorporated the HighScore class from my Yahtzee game submitted previously.

High Score Table

Enjoy the game!

History

  • 10th May, 2007 - Updated source code for .NET 2.0
  • 14th May, 2007 - Updated article posted to Code Project

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 3 Pin
vipana4-Sep-10 18:50
vipana4-Sep-10 18:50 
Generaldraw rotated back Pin
Chip02265030-May-08 12:29
Chip02265030-May-08 12:29 
GeneralCards as a PictureBox for dragging Pin
shastaou81231-Oct-07 9:58
shastaou81231-Oct-07 9:58 
GeneralCode Error Pin
Mike Kitchen15-May-07 1:00
Mike Kitchen15-May-07 1:00 
GeneralPInvoke error Pin
C. Marshall25-Apr-06 8:16
C. Marshall25-Apr-06 8:16 
GeneralRe: PInvoke error Pin
cheeks863-Apr-07 17:16
cheeks863-Apr-07 17:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.