Skip to main content
Email Password   helpLost your password?

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.
You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralCan I use your src code? Pin
brianlan
21:05 5 Jan '09  
Generalcan i ask you something? [modified] Pin
sunerbun
23:48 24 May '08  
Generaladdress of speaker and mouse socket Pin
wasimhasan
1:38 29 Jan '03  
GeneralRe: address of speaker and mouse socket Pin
Mauricio Ritter
2:37 29 Jan '03  
GeneralRe: address of speaker and mouse socket Pin
peterchen
23:06 4 Dec '04  
GeneralResource leak Pin
PJ Arends
13:19 4 May '02  
GeneralRe: Resource leak Pin
Mauricio Ritter
6:35 5 May '02  
GeneralKaboom Splatter Crash Pin
swinefeaster
21:44 14 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
Mauricio Ritter
2:31 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
swinefeaster
13:08 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
Christian Graus
13:22 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
swinefeaster
13:27 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
Christian Graus
13:30 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
swinefeaster
13:37 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
Christian Graus
13:44 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
swinefeaster
13:47 15 Apr '02  
GeneralRe: Kaboom Splatter Crash Pin
Dario Solera
23:50 15 Sep '05  
GeneralHi Mauricio, just testing my sig... Pin
Nish [BusterBoy]
17:31 22 Mar '02  
GeneralRe: Hi Mauricio, just testing my sig... Pin
Mauricio Ritter
2:12 23 Mar '02  
GeneralRe: Hi Mauricio, just testing my sig... Pin
Nish [BusterBoy]
3:47 23 Mar '02  
GeneralUpdate Pin
Mauricio Ritter
15:48 22 Mar '02  
GeneralWow Pin
James T. Johnson
20:57 16 Mar '02  
GeneralRe: Wow Pin
Mauricio Ritter
2:08 17 Mar '02  
GeneralRe: Wow Pin
Nish [BusterBoy]
14:07 17 Mar '02  
GeneralRe: Wow Pin
Mauricio Ritter
15:56 17 Mar '02  


Last Updated 29 May 2002 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009