Click here to Skip to main content
15,881,281 members
Articles / Programming Languages / C#

Pentominos - A C# Implementation of the Famous Puzzle Game

Rate me:
Please Sign up or sign in to vote.
4.89/5 (8 votes)
29 May 20023 min read 178.4K   3.8K   44   27
This is a simple implementation of Pentominos, a puzzle game. The source code is written in C# and uses a lot of concepts about drawing and matrix handling. Hope you enjoy it !

Sample Image - pentominossharp1.jpg

The Game

This is a C# implementation of the famous Pentominos Puzzle game. The game objective is to combine the 12 pieces into the rectangle. In the easiest mode (6x10 rectangle) there are 2339 possible solutions. You must be thinking... 2339 possible solutions... easy! If you have that thought (and never had played this game before)... I CHALLENGE YOU TO FINISH THE PUZZLE IN LESS THAN 5 MINUTES! Have fun!

The Program

The game is a simple Windows Forms application. In the main form structure, we have declared an array of cPiece class instances that represent the instances lying around the window and two int variables that represent the dimensions of the main rectangle.

C#
public int iCols;
public int iRows;

cPiece[]    piece = new cPiece[12];

At the beginning of the game, we have a call to the InitForm() function that is responsible for the creation of the 12 pieces and resetting the time counter. The time controlled by a DateTime variable that stores the start time of the game.

C#
for(int i=0;i<12;i++)
{
    piece[i] = new cPiece();
    piece[i].CreatePiece(i+1);
    piece[i].SetPos(20 + ( (i%6) *80), i>=6 ? 280 : 200);
}    

dtStart = DateTime.Now;

The cPiece Class

The cPiece class has all the functionality needed to work with the pieces around the screen. The piece structure is stored in a int 5x5 matrix. When we call the CreatePiece method of the class, we populate the matrix with 0 and 1 to describe where the piece is filled and where it is not filled.

C#
public void CreatePiece(int iPieceType)
{
    switch(iPieceType)
    {
        case 1:
            iMatrix[0,0] = 0;
            iMatrix[1,0] = 1;
            iMatrix[2,0] = 0;
            iMatrix[3,0] = 0;
            iMatrix[4,0] = 0;
        ...

        case 12:
            iMatrix[0,0] = 1;
            iMatrix[1,0] = 0;
            iMatrix[2,0] = 0;
            iMatrix[3,0] = 0;
            iMatrix[4,0] = 0;
            iMatrix[0,1] = 1;
            iMatrix[1,1] = 0;
            iMatrix[2,1] = 0;
            iMatrix[3,1] = 0;
            iMatrix[4,1] = 0;

            iMatrix[0,2] = 1;
            iMatrix[1,2] = 0;
            iMatrix[2,2] = 0;
            iMatrix[3,2] = 0;
            iMatrix[4,2] = 0;

            iMatrix[0,3] = 1;
            iMatrix[1,3] = 0;
            iMatrix[2,3] = 0;
            iMatrix[3,3] = 0;
            iMatrix[4,3] = 0;

            iMatrix[0,4] = 1;
            iMatrix[1,4] = 0;
            iMatrix[2,4] = 0;
            iMatrix[3,4] = 0;
            iMatrix[4,4] = 0;
            piecebrush = new SolidBrush(Color.LightGreen);
            break;                
    }
}

If you notice in the last piece of code, we have a piecebrush variable that holds a SolidBrush instance. This variable is used in the piece painting process. When we create the pieces, we assign a different color to each one. The drawing process of the piece is done with the Draw() method, that receives an instance of the Graphics object and paints the piece in its current position.

C#
public void Draw( Graphics oGraph)
{
    Pen blackpen = new Pen(Color.Black, 2);
    Point[] tmpPoints = (Point[]) thePoints.Clone();

    for(int i=0;i < iNumPoints;i++)
    {
        tmpPoints[i].X += iPosX;
        tmpPoints[i].Y += iPosY;
    }

    //gradbrush.InterpolationColors = oGradColor;
    
    oGraph.DrawPolygon(blackpen, tmpPoints);
    oGraph.FillPolygon(piecebrush, tmpPoints, FillMode.Winding);
}

The Draw() method uses a Point array that represents the points the form the piece polygon. This points are stored in the thePoints variable that is an array created dynamically in the CreatePoints method. The CreatePoints method gets a starting point on the matrix and starts a tracing process around the piece, to find the polygon vertices. The other methods available in the cPiece class are SetPos, that sets the position of the piece in the screen, RotatePiece() that rotates and shifts the matrix that describes the piece structure, and FlipPiece that flips the piece matrix. There is an extra method called Hitted that is used to check if the mouse current position is inside a piece.

The Main Form Painting

At the OnPaint event, we draw the puzzle box and all the pieces in their current positions, calling the Draw function of each piece.

C#
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    Graphics        grPaint = e.Graphics;
    SolidBrush        brushWhite = new SolidBrush(Color.White);
    Pen                blackpen = new Pen(Color.Black,2);
        
    // Clear the screen
    grPaint.FillRectangle(brushWhite, e.ClipRectangle);
    // Draw the grid
    grPaint.DrawString("Left-Click on a piece do drag or drop it",
                       new Font("Arial",12), 
                       new SolidBrush(Color.Black),20,10);
    grPaint.DrawString("Right-Click to rotate and flip " + 
                       "it (some pieces doesn´t flip)",
                       new Font("Arial",12), 
                       new SolidBrush(Color.Black),20,30);

    for(int i=0;i < iCols;i++)
    {
        for(int j=0;j < iRows;j++)
        {
            grPaint.DrawRectangle(blackpen, 100 + (i*20), 60 + (j*20),20,20);
        }
    }
            
    for(int i=0;i < 12;i++)
    {
        piece[i].Draw(grPaint);
    }
}

The MouseDown and MouseMove event implementations of the form is where the game logic is. We have a variable called draggedpiece that holds the piece that the user is dragging. When the user clicks in a piece, we assign the instance of the piece to the dragged piece variable. In the MouseMove event, we use the draggedpiece variable to set the piece's new position and redraw it.

I know this article is not TOPIC SPECIFIC, but it shows a lot of things about the drawing process of C# and Windows Forms. Hope you enjoy it !

Updates

  • 05/26/2002: I've corrected some resource leak problems so that users running the game on Win 9x don't have any problems. The main difference is that the cursor variables are at form scope and are loaded just once. Special thanks to PJ Arens for the bug report and testing, and James T. Johnson for his great explanation about the problem.

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
Web Developer
Brazil Brazil
Mauricio Ritter lives in Brazil, in the city of Porto Alegre. He is working with software development for about 8 years, and most of his work was done at a bank, within a home and office banking system.
Mauricio also holds MCSD, MCSE, MCDBA, MCAD and MCT Microsoft certifications and work as a trainer/consultant in some MS CTEC in his city.
Mauricio also works in his own programming site, aimed to Brazilian Developers: http://www.dotnetmaniacs.com.br

In his spare time he studys korean language...

Comments and Discussions

 
GeneralChecking resource leaks in a form Pin
elizas19-Feb-10 2:38
elizas19-Feb-10 2:38 
QuestionCan I use your src code? Pin
brianlan5-Jan-09 20:05
brianlan5-Jan-09 20:05 
Questioncan i ask you something? [modified] Pin
sunerbun24-May-08 22:48
sunerbun24-May-08 22:48 
Generaladdress of speaker and mouse socket Pin
wasimhasan29-Jan-03 0:38
wasimhasan29-Jan-03 0:38 

i want the address of speaker port and mouse port and the architecture of both
Confused | :confused:

GeneralRe: address of speaker and mouse socket Pin
Mauricio Ritter29-Jan-03 1:37
Mauricio Ritter29-Jan-03 1:37 
GeneralRe: address of speaker and mouse socket Pin
peterchen4-Dec-04 22:06
peterchen4-Dec-04 22:06 
GeneralResource leak Pin
PJ Arends4-May-02 12:19
professionalPJ Arends4-May-02 12:19 
GeneralRe: Resource leak Pin
Mauricio Ritter5-May-02 5:35
Mauricio Ritter5-May-02 5:35 
GeneralKaboom Splatter Crash Pin
Swinefeaster14-Apr-02 20:44
Swinefeaster14-Apr-02 20:44 
GeneralRe: Kaboom Splatter Crash Pin
Mauricio Ritter15-Apr-02 1:31
Mauricio Ritter15-Apr-02 1:31 
GeneralRe: Kaboom Splatter Crash Pin
Swinefeaster15-Apr-02 12:08
Swinefeaster15-Apr-02 12:08 
GeneralRe: Kaboom Splatter Crash Pin
Christian Graus15-Apr-02 12:22
protectorChristian Graus15-Apr-02 12:22 
GeneralRe: Kaboom Splatter Crash Pin
Swinefeaster15-Apr-02 12:27
Swinefeaster15-Apr-02 12:27 
GeneralRe: Kaboom Splatter Crash Pin
Christian Graus15-Apr-02 12:30
protectorChristian Graus15-Apr-02 12:30 
GeneralRe: Kaboom Splatter Crash Pin
Swinefeaster15-Apr-02 12:37
Swinefeaster15-Apr-02 12:37 
GeneralRe: Kaboom Splatter Crash Pin
Christian Graus15-Apr-02 12:44
protectorChristian Graus15-Apr-02 12:44 
GeneralRe: Kaboom Splatter Crash Pin
Swinefeaster15-Apr-02 12:47
Swinefeaster15-Apr-02 12:47 
GeneralRe: Kaboom Splatter Crash Pin
Dario Solera15-Sep-05 22:50
Dario Solera15-Sep-05 22:50 
GeneralHi Mauricio, just testing my sig... Pin
Nish Nishant22-Mar-02 16:31
sitebuilderNish Nishant22-Mar-02 16:31 
GeneralRe: Hi Mauricio, just testing my sig... Pin
Mauricio Ritter23-Mar-02 1:12
Mauricio Ritter23-Mar-02 1:12 
GeneralRe: Hi Mauricio, just testing my sig... Pin
Nish Nishant23-Mar-02 2:47
sitebuilderNish Nishant23-Mar-02 2:47 
GeneralUpdate Pin
Mauricio Ritter22-Mar-02 14:48
Mauricio Ritter22-Mar-02 14:48 
GeneralWow Pin
James T. Johnson16-Mar-02 19:57
James T. Johnson16-Mar-02 19:57 
GeneralRe: Wow Pin
Mauricio Ritter17-Mar-02 1:08
Mauricio Ritter17-Mar-02 1:08 
GeneralRe: Wow Pin
Nish Nishant17-Mar-02 13:07
sitebuilderNish Nishant17-Mar-02 13:07 

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.