Click here to Skip to main content
Click here to Skip to main content
Go to top

Pentominos - A C# implementation of the famous puzzle game

, 29 May 2002
Rate this:
Please Sign up or sign in to vote.
This is a simple implementation of Pentominos, a puzzle game. The source code is written in C# an 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 THEN 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.

public int iCols;
public int iRows;

cPiece[]    piece = new cPiece[12];

At the begging 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.

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 need 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 its not filled.

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.

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 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.

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 doesn´t have any problems. The main difference is that the cursor variables are at form scope an 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

Share

About the Author

Mauricio Ritter
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 Pingroupelizas19-Feb-10 2:38 
QuestionCan I use your src code? Pinmemberbrianlan5-Jan-09 20:05 
Questioncan i ask you something? [modified] Pinmembersunerbun24-May-08 22:48 
Generaladdress of speaker and mouse socket Pinmemberwasimhasan29-Jan-03 0:38 
GeneralRe: address of speaker and mouse socket PinmemberMauricio Ritter29-Jan-03 1:37 
GeneralRe: address of speaker and mouse socket Pinmemberpeterchen4-Dec-04 22:06 
GeneralResource leak PinmemberPJ Arends4-May-02 12:19 
GeneralRe: Resource leak PinmemberMauricio Ritter5-May-02 5:35 
GeneralKaboom Splatter Crash Pinmemberswinefeaster14-Apr-02 20:44 
GeneralRe: Kaboom Splatter Crash PinmemberMauricio Ritter15-Apr-02 1:31 
GeneralRe: Kaboom Splatter Crash Pinmemberswinefeaster15-Apr-02 12:08 
GeneralRe: Kaboom Splatter Crash PinmemberChristian Graus15-Apr-02 12:22 
GeneralRe: Kaboom Splatter Crash Pinmemberswinefeaster15-Apr-02 12:27 
GeneralRe: Kaboom Splatter Crash PinmemberChristian Graus15-Apr-02 12:30 
GeneralRe: Kaboom Splatter Crash Pinmemberswinefeaster15-Apr-02 12:37 
GeneralRe: Kaboom Splatter Crash PinmemberChristian Graus15-Apr-02 12:44 
GeneralRe: Kaboom Splatter Crash Pinmemberswinefeaster15-Apr-02 12:47 
GeneralRe: Kaboom Splatter Crash PinmemberDario Solera15-Sep-05 22:50 
GeneralHi Mauricio, just testing my sig... PinmemberNish [BusterBoy]22-Mar-02 16:31 
GeneralRe: Hi Mauricio, just testing my sig... PinmemberMauricio Ritter23-Mar-02 1:12 
GeneralRe: Hi Mauricio, just testing my sig... PinmemberNish [BusterBoy]23-Mar-02 2:47 
GeneralUpdate PinmemberMauricio Ritter22-Mar-02 14:48 
GeneralWow PinmemberJames T. Johnson16-Mar-02 19:57 
GeneralRe: Wow PinmemberMauricio Ritter17-Mar-02 1:08 
GeneralRe: Wow PinmemberNish [BusterBoy]17-Mar-02 13:07 
GeneralRe: Wow PinmemberMauricio Ritter17-Mar-02 14:56 
GeneralRe: Wow PinmemberRichard Birkby19-Mar-02 23:29 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 30 May 2002
Article Copyright 2002 by Mauricio Ritter
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid