Pentominos - A C# Implementation of the Famous Puzzle Game






4.89/5 (8 votes)
Mar 16, 2002
3 min read

179904

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