Example #1
0
        public void addSinglePieceToClusterCorrectLiberties()
        {
            //arrange
            GoBoard testgame = new GoBoard(5);

            Coordinate loc = new Coordinate(3, 3);
            testgame.addPiece(loc, Space.Black);
            PieceCluster simpleCluster = new PieceCluster(loc, Space.Black, testgame);

            Coordinate loc2 = new Coordinate(4, 2);
            testgame.addPiece(loc2, Space.White);

            Coordinate loc3 = new Coordinate(4, 3);
            testgame.addPiece(loc3, Space.Black);
            simpleCluster.piecesAdd(loc3);
            simpleCluster.removeLiberty(loc3);
            simpleCluster.addLibertiesOf(loc3);

            int expected = 5;

            //act
            int actual = simpleCluster.Liberties.Count;

            //assert
            Assert.AreEqual(expected, actual);
        }
Example #2
0
        public void basicClusterHasFourLiberties()
        {
            //arrange
            GoBoard testgame = new GoBoard(5);
            Coordinate loc = new Coordinate(3, 3);
            testgame.addPiece(loc, Space.Black);
            int expected = 4;

            //act
            PieceCluster simpleCluster = new PieceCluster(loc, Space.Black, testgame);
            int actual = simpleCluster.Liberties.Count;

            //assert
            Assert.AreEqual(expected, actual);
        }
Example #3
0
        public void basicClusterContainsSelf()
        {
            //arrange
            GoBoard testgame = new GoBoard(5);
            Coordinate loc = new Coordinate(3, 3);
            testgame.addPiece(loc, Space.Black);
            bool expected = true;

            //act
            PieceCluster simpleCluster = new PieceCluster(loc, Space.Black, testgame);
            bool actual = simpleCluster.Pieces.Contains(loc);

            //assert
            Assert.AreEqual(expected, actual);
        }
Example #4
0
        public void enemyNeighborHasLessLiberties()
        {
            //arrange
            GoBoard testgame = new GoBoard(5);
            Coordinate loc = new Coordinate(3, 3);
            testgame.addPiece(loc, Space.Black);
            Coordinate loc2 = new Coordinate(4,3);
            testgame.addPiece(loc2, Space.White);
            int expected = 3;

            //act
            PieceCluster simpleCluster = new PieceCluster(loc2, Space.White, testgame);
            int actual = simpleCluster.Liberties.Count;

            //assert
            Assert.AreEqual(expected, actual);
        }
Example #5
0
        public void libertyUpdatingWithLittleCluster()
        {
            //arrange
            GoBoard testgame = new GoBoard(5);

            Coordinate loc = new Coordinate(3, 3);
            testgame.addPiece(loc, Space.Black);
            PieceCluster black1 = new PieceCluster(loc, Space.Black, testgame);

            Coordinate loc2 = new Coordinate(4, 2);
            testgame.addPiece(loc2, Space.White);
            PieceCluster white1 = new PieceCluster(loc2, Space.White, testgame);

            Coordinate loc3 = new Coordinate(4, 3);
            testgame.addPiece(loc3, Space.Black);

            black1.piecesAdd(loc3);
            black1.removeLiberty(loc3);
            black1.addLibertiesOf(loc3);

            white1.removeLiberty(loc3);

            int expected = 3;

            //act
            int actual = white1.Liberties.Count;

            //assert
            Assert.AreEqual(expected, actual);
        }
Example #6
0
        public void libertyUpdatingForSimpleClustersWorks()
        {
            //arrange
            GoBoard testgame = new GoBoard(5);

            Coordinate loc = new Coordinate(3, 3);
            testgame.addPiece(loc, Space.Black);
            PieceCluster simpleCluster = new PieceCluster(loc, Space.Black, testgame);

            Coordinate loc2 = new Coordinate(4, 3);
            testgame.addPiece(loc2, Space.White);
            simpleCluster.removeLiberty(loc2);

            int expected = 3;

            //act

            int actual = simpleCluster.Liberties.Count;

            //assert
            Assert.AreEqual(expected, actual);
        }
Example #7
0
        private void CreateJigsawPuzzle()
        {
            #region Some validation

            if (_sourcePicture == null)
            {
                throw new Exception("Please provide source picture.");
            }

            if (GameSettings.NUM_ROWS <= 1 || GameSettings.NUM_COLUMNS <= 1)
            {
                throw new Exception("GameSettings.NUM_COLUMNS and GameSettings.NUM_ROWS must be at least 2.");
            }

            if (GameSettings.NUM_COLUMNS != GameSettings.NUM_ROWS)
            {
                throw new Exception("GameSettings.NUM_COLUMNS and GameSettings.NUM_ROWS must be the same.");
            }

            #endregion

            #region Make sure the piece size is not too small

            int pieceWidth  = _sourcePicture.Width / GameSettings.NUM_COLUMNS;
            int pieceHeight = _sourcePicture.Height / GameSettings.NUM_ROWS;

            if (pieceWidth < GameSettings.MIN_PIECE_WIDTH || pieceHeight < GameSettings.MIN_PIECE_HEIGHT)
            {
                throw new Exception("The picture is too small. Please select a bigger picture.");
            }

            int lastColPieceWidth  = pieceWidth + (_sourcePicture.Width % GameSettings.NUM_COLUMNS);
            int lastRowPieceHeight = pieceHeight + (_sourcePicture.Height % GameSettings.NUM_ROWS);

            #endregion

            #region Construct jigsaw pieces

            int lastRow = (GameSettings.NUM_ROWS - 1);
            int lastCol = (GameSettings.NUM_COLUMNS - 1);

            _currentCluster = null;
            _clusters       = new List <PieceCluster>();

            Matrix matrix = new Matrix();

            Pen outlinePen = new Pen(Color.Black, 1)
            {
                Width     = GameSettings.PIECE_OUTLINE_WIDTH,
                Alignment = PenAlignment.Inset
            };

            int pieceID = 0;

            for (int row = 0; row < GameSettings.NUM_ROWS; row++)
            {
                // Make the top and bottom curves face in the same way or opposite direction.
                bool topCurveFlipVertical    = (row % 2 == 0);
                bool bottomCurveFlipVertical = (row % 2 != 0);

                for (int col = 0; col < GameSettings.NUM_COLUMNS; col++)
                {
                    // Make the left and right curves face in the same way or opposite direction.
                    bool leftCurveFlipHorizontal  = (col % 2 != 0);
                    bool rightCurveFlipHorizontal = (col % 2 == 0);

                    // Toggle the facing of left and right curves with each row.
                    if (row % 2 == 0)
                    {
                        leftCurveFlipHorizontal  = (col % 2 == 0);
                        rightCurveFlipHorizontal = (col % 2 != 0);
                    }

                    // Toggle the facing of top and bottom curves with each row.
                    topCurveFlipVertical    = !topCurveFlipVertical;
                    bottomCurveFlipVertical = !bottomCurveFlipVertical;

                    GraphicsPath figure = new GraphicsPath();

                    int offsetX = (col * pieceWidth);
                    int offsetY = (row * pieceHeight);
                    int horizontalCurveLength = (col == lastCol ? lastColPieceWidth : pieceWidth);
                    int verticalCurveLength   = (row == lastRow ? lastRowPieceHeight : pieceHeight);

                    #region Top

                    if (row == 0)
                    {
                        int startX = offsetX;
                        int startY = offsetY;
                        int endX   = offsetX + horizontalCurveLength;
                        int endY   = offsetY;

                        figure.AddLine(startX, startY, endX, endY);
                    }
                    else
                    {
                        BezierCurve topCurve = BezierCurve.CreateHorizontal(horizontalCurveLength);

                        if (topCurveFlipVertical)
                        {
                            topCurve.FlipVertical();
                        }

                        topCurve.Translate(offsetX, offsetY);
                        figure.AddBeziers(topCurve.Points);
                    }

                    #endregion

                    #region Right

                    if (col == lastCol)
                    {
                        int startX = offsetX + lastColPieceWidth;
                        int startY = offsetY;
                        int endX   = offsetX + lastColPieceWidth;
                        int endY   = offsetY + verticalCurveLength;

                        figure.AddLine(startX, startY, endX, endY);
                    }
                    else
                    {
                        BezierCurve verticalCurve = BezierCurve.CreateVertical(verticalCurveLength);

                        if (rightCurveFlipHorizontal)
                        {
                            verticalCurve.FlipHorizontal();
                        }

                        verticalCurve.Translate(offsetX + pieceWidth, offsetY);
                        figure.AddBeziers(verticalCurve.Points);
                    }

                    #endregion

                    #region Bottom

                    if (row == lastRow)
                    {
                        int startX = offsetX;
                        int startY = offsetY + lastRowPieceHeight;
                        int endX   = offsetX + horizontalCurveLength;
                        int endY   = offsetY + lastRowPieceHeight;

                        figure.AddLine(endX, endY, startX, startY);
                    }
                    else
                    {
                        BezierCurve bottomCurve = BezierCurve.CreateHorizontal(horizontalCurveLength);
                        bottomCurve.FlipHorizontal();

                        if (bottomCurveFlipVertical)
                        {
                            bottomCurve.FlipVertical();
                        }

                        bottomCurve.Translate(offsetX + horizontalCurveLength, offsetY + pieceHeight);
                        figure.AddBeziers(bottomCurve.Points);
                    }

                    #endregion

                    #region Left

                    if (col == 0)
                    {
                        int startX = offsetX;
                        int startY = offsetY;
                        int endX   = offsetX;
                        int endY   = offsetY + verticalCurveLength;

                        figure.AddLine(endX, endY, startX, startY);
                    }
                    else
                    {
                        BezierCurve verticalCurve = BezierCurve.CreateVertical(verticalCurveLength);
                        verticalCurve.FlipVertical();

                        if (leftCurveFlipHorizontal)
                        {
                            verticalCurve.FlipHorizontal();
                        }

                        verticalCurve.Translate(offsetX, offsetY + verticalCurveLength);
                        figure.AddBeziers(verticalCurve.Points);
                    }

                    #endregion

                    #region Jigsaw information

                    #region Determine adjacent piece IDs for the current piece

                    List <Coordinate> adjacentCoords = new List <Coordinate>
                    {
                        new Coordinate(col, row - 1),
                        new Coordinate(col + 1, row),
                        new Coordinate(col, row + 1),
                        new Coordinate(col - 1, row)
                    };

                    List <int> adjacentPieceIDs = DetermineAdjacentPieceIDs(adjacentCoords, GameSettings.NUM_COLUMNS);

                    #endregion

                    #region Construct piece picture

                    Rectangle figureLocation = Rectangle.Truncate(figure.GetBounds());

                    // Translate the figure to the origin to draw the picture for individual piece
                    matrix.Reset();
                    matrix.Translate(0 - figureLocation.X, 0 - figureLocation.Y);
                    GraphicsPath translatedFigure = (GraphicsPath)figure.Clone();
                    translatedFigure.Transform(matrix);

                    Rectangle translatedFigureLocation = Rectangle.Truncate(translatedFigure.GetBounds());

                    Bitmap piecePicture = new Bitmap(figureLocation.Width, figureLocation.Height);

                    using (Graphics gfx = Graphics.FromImage(piecePicture))
                    {
                        gfx.FillRectangle(Brushes.White, 0, 0, piecePicture.Width, piecePicture.Height);
                        gfx.ResetClip();
                        gfx.SetClip(translatedFigure);
                        gfx.DrawImage(_sourcePicture, new Rectangle(0, 0, piecePicture.Width, piecePicture.Height),
                                      figureLocation, GraphicsUnit.Pixel);

                        if (GameSettings.DRAW_PIECE_OUTLINE)
                        {
                            gfx.SmoothingMode = SmoothingMode.AntiAlias;
                            gfx.DrawPath(outlinePen, translatedFigure);
                        }
                    }

                    // Wanted to do the "bevel edge" effect but too complicated for me.
                    Bitmap modifiedPiecePicture = (Bitmap)piecePicture.Clone();
                    ImageUtilities.EdgeDetectHorizontal(modifiedPiecePicture);
                    ImageUtilities.EdgeDetectVertical(modifiedPiecePicture);
                    piecePicture = ImageUtilities.AlphaBlendMatrix(modifiedPiecePicture, piecePicture, 200);

                    #endregion

                    #region Piece and cluster information

                    Piece piece = new Piece
                    {
                        ID                    = pieceID,
                        ClusterID             = pieceID,
                        Width                 = figureLocation.Width,
                        Height                = figureLocation.Height,
                        BoardLocation         = translatedFigureLocation,
                        SourcePictureLocation = figureLocation,
                        MovableFigure         = (GraphicsPath)translatedFigure.Clone(),
                        StaticFigure          = (GraphicsPath)figure.Clone(),
                        Picture               = (Bitmap)piecePicture.Clone(),
                        AdjacentPieceIDs      = adjacentPieceIDs
                    };

                    PieceCluster cluster = new PieceCluster
                    {
                        ID                    = pieceID,
                        Width                 = figureLocation.Width,
                        Height                = figureLocation.Height,
                        BoardLocation         = translatedFigureLocation,
                        SourcePictureLocation = figureLocation,
                        MovableFigure         = (GraphicsPath)translatedFigure.Clone(),
                        StaticFigure          = (GraphicsPath)figure.Clone(),
                        Picture               = (Bitmap)piecePicture.Clone(),
                        Pieces                = new List <Piece> {
                            piece
                        }
                    };

                    #endregion

                    _clusters.Add(cluster);

                    #endregion

                    pieceID++;
                }
            }

            #endregion

            #region Scramble jigsaw pieces

            Random random = new Random();

            int boardWidth  = this.ClientSize.Width - grbButtons.Width;
            int boardHeight = this.ClientSize.Height - menuStrip1.Height;

            foreach (PieceCluster cluster in _clusters)
            {
                int locationX = random.Next(1, boardWidth);
                int locationY = random.Next((menuStrip1.Height + 1), boardHeight);

                #region Make sure the piece is within client rectangle bounds

                if ((locationX + cluster.Width) > boardWidth)
                {
                    locationX = locationX - ((locationX + cluster.Width) - boardWidth);
                }

                if ((locationY + cluster.Height) > boardHeight)
                {
                    locationY = locationY - ((locationY + cluster.Height) - boardHeight);
                }

                #endregion

                for (int index = 0; index < cluster.Pieces.Count; index++)
                {
                    Piece piece = cluster.Pieces[index];
                    piece.BoardLocation = new Rectangle(locationX, locationY, piece.Width, piece.Height);

                    matrix.Reset();
                    matrix.Translate(locationX, locationY);
                    piece.MovableFigure.Transform(matrix);
                }

                // Move the figure for cluster piece
                cluster.BoardLocation = new Rectangle(locationX, locationY, cluster.Width, cluster.Height);

                matrix.Reset();
                matrix.Translate(locationX, locationY);
                cluster.MovableFigure.Transform(matrix);
            }

            #endregion
        }
Example #8
0
        private void frmJigsawPuzzle_MouseUp(object sender, MouseEventArgs e)
        {
            if (_canMovePiece)
            {
                _previousMouseX = e.X;
                _previousMouseY = e.Y;

                #region Draw the "dropped" moving cluster at its final position into back buffer

                using (Graphics gfx = Graphics.FromImage(_backBuffer))
                {
                    gfx.ResetClip();
                    gfx.SetClip(_currentCluster.MovableFigure);
                    gfx.DrawImageUnscaled(_currentCluster.Picture, _currentCluster.BoardLocation);
                }

                #endregion

                #region Sync the board, the back buffer, and the display

                using (Graphics gfx = Graphics.FromImage(_board))
                {
                    gfx.DrawImageUnscaled(_backBuffer, 0, 0);
                }

                using (Graphics gfx = this.CreateGraphics())
                {
                    gfx.DrawImageUnscaled(_backBuffer, 0, 0);
                }

                #endregion

                #region Snapping and combining adjacent pieces

                Matrix matrix = new Matrix();

                // Adjacent clusters to be combined with the current cluster
                List <int> adjacentClusterIDs = new List <int>();

                // For each piece in the current cluster, check if there is any adjacent piece to snap
                for (int i = 0; i < _currentCluster.Pieces.Count; i++)
                {
                    Piece currentPiece = _currentCluster.Pieces[i];

                    foreach (int pieceID in currentPiece.AdjacentPieceIDs)
                    {
                        Piece adjacentPiece = GetPieceByID(pieceID);

                        if (adjacentPiece != null && (adjacentPiece.ClusterID != currentPiece.ClusterID))
                        {
                            #region Make sure the adjacent piece is located at the correct "side" of the current piece

                            Rectangle adjacentPieceMovableFigureBoardLocation = Rectangle.Truncate(adjacentPiece.MovableFigure.GetBounds());
                            Rectangle currentPieceMovableFigureBoardLocation  = Rectangle.Truncate(currentPiece.MovableFigure.GetBounds());

                            // Math.Sign(.) returns a number indicating the sign of value.
                            // -1 value is less than zero. 0 value is equal to zero. 1 value is greater than zero.
                            // Tolerance value is set to 2 pixels.
                            if (Math.Abs(currentPiece.SourcePictureLocation.X - adjacentPiece.SourcePictureLocation.X) <= 2)
                            {
                                int figureYDifferenceSign        = Math.Sign(currentPieceMovableFigureBoardLocation.Y - adjacentPieceMovableFigureBoardLocation.Y);
                                int sourcePictureYDifferenceSign = Math.Sign(currentPiece.SourcePictureLocation.Y - adjacentPiece.SourcePictureLocation.Y);

                                // Adjacent piece is on the wrong side of the current piece. Do not snap to the current piece.
                                // For example, adjacent piece should be located below the current piece instead of being
                                // located above it.
                                if (figureYDifferenceSign != sourcePictureYDifferenceSign)
                                {
                                    continue;
                                }
                            }
                            else if (Math.Abs(currentPiece.SourcePictureLocation.Y - adjacentPiece.SourcePictureLocation.Y) <= 2)
                            {
                                int figureXDifferenceSign      = Math.Sign(currentPieceMovableFigureBoardLocation.X - adjacentPieceMovableFigureBoardLocation.X);
                                int sourceImageXDifferenceSign = Math.Sign(currentPiece.SourcePictureLocation.X - adjacentPiece.SourcePictureLocation.X);

                                // Adjacent piece is on the wrong side of the current piece. Do not snap to the current piece.
                                // For example, adjacent piece should be located at the right side of the current piece instead
                                // of being located at the left side.
                                if (figureXDifferenceSign != sourceImageXDifferenceSign)
                                {
                                    continue;
                                }
                            }

                            #endregion

                            #region Determine if the adjacent piece should be snapped to the current cluster

                            // =================================================
                            // If the dimensions of the rectangle bounds of the merged path
                            // almost equals the "unioned" rectangles of the two pieces' source image
                            // dimensions, they can be snapped together.
                            // =================================================
                            GraphicsPath combinedMovableFigure = new GraphicsPath();
                            combinedMovableFigure.AddPath(adjacentPiece.MovableFigure, false);
                            combinedMovableFigure.AddPath(currentPiece.MovableFigure, false);

                            Rectangle combinedMovableFigureBoardLocation = Rectangle.Truncate(combinedMovableFigure.GetBounds());

                            // The combined rectangle based on the source picture dimensions of the two pieces
                            Rectangle combinedSourcePictureLocation = Rectangle.Union(adjacentPiece.SourcePictureLocation, currentPiece.SourcePictureLocation);

                            if (Math.Abs(combinedMovableFigureBoardLocation.Width - combinedSourcePictureLocation.Width) <= GameSettings.SNAP_TOLERANCE &&
                                Math.Abs(combinedMovableFigureBoardLocation.Height - combinedSourcePictureLocation.Height) <= GameSettings.SNAP_TOLERANCE)
                            {
                                PieceCluster adjacentPieceCluster = GetPieceClusterByID(adjacentPiece.ClusterID);

                                adjacentClusterIDs.Add(adjacentPieceCluster.ID);

                                // Update the ClusterID for the pieces in adjacent cluster
                                foreach (Piece piece in adjacentPieceCluster.Pieces)
                                {
                                    piece.ClusterID = currentPiece.ClusterID;
                                }
                            }

                            #endregion
                        }
                    }
                }

                if (adjacentClusterIDs.Count > 0)
                {
                    #region Remove the adjacent cluster from the list after combining with the current cluster

                    foreach (int clusterID in adjacentClusterIDs)
                    {
                        PieceCluster adjacentCluster = GetPieceClusterByID(clusterID);

                        foreach (Piece piece in adjacentCluster.Pieces)
                        {
                            _currentCluster.Pieces.Add(piece);
                        }

                        RemovePieceGroupByID(clusterID);
                    }

                    #endregion

                    GraphicsPath combinedStaticFigure          = new GraphicsPath();
                    Rectangle    combinedBoardLocation         = _currentCluster.BoardLocation;
                    Rectangle    combinedSourcePictureLocation = _currentCluster.SourcePictureLocation;

                    foreach (Piece piece in _currentCluster.Pieces)
                    {
                        combinedStaticFigure.AddPath(piece.StaticFigure, false);
                        combinedBoardLocation         = Rectangle.Union(combinedBoardLocation, piece.BoardLocation);
                        combinedSourcePictureLocation = Rectangle.Union(combinedSourcePictureLocation, piece.SourcePictureLocation);
                    }

                    _currentCluster.BoardLocation = new Rectangle(combinedBoardLocation.X, combinedBoardLocation.Y,
                                                                  combinedSourcePictureLocation.Width,
                                                                  combinedSourcePictureLocation.Height);

                    _currentCluster.SourcePictureLocation = combinedSourcePictureLocation;
                    _currentCluster.Width         = combinedSourcePictureLocation.Width;
                    _currentCluster.Height        = combinedSourcePictureLocation.Height;
                    _currentCluster.StaticFigure  = (GraphicsPath)combinedStaticFigure.Clone();
                    _currentCluster.MovableFigure = (GraphicsPath)combinedStaticFigure.Clone();

                    Rectangle combinedStaticFigureLocation = Rectangle.Truncate(combinedStaticFigure.GetBounds());

                    // Translate the movable figure to the origin first and...
                    matrix.Reset();
                    matrix.Translate(0 - combinedStaticFigureLocation.X, 0 - combinedStaticFigureLocation.Y);
                    _currentCluster.MovableFigure.Transform(matrix);

                    //  ...then translate to the new board location
                    matrix.Reset();
                    matrix.Translate(combinedBoardLocation.X, combinedBoardLocation.Y);
                    _currentCluster.MovableFigure.Transform(matrix);

                    #region Construct cluster picture

                    // Translate the figure to the origin to draw the picture
                    matrix.Reset();
                    matrix.Translate(0 - combinedStaticFigureLocation.X, 0 - combinedStaticFigureLocation.Y);
                    GraphicsPath translatedCombinedStaticFigure = (GraphicsPath)combinedStaticFigure.Clone();
                    translatedCombinedStaticFigure.Transform(matrix);

                    Bitmap clusterPicture = new Bitmap(combinedSourcePictureLocation.Width, combinedSourcePictureLocation.Height);

                    using (Graphics gfx = Graphics.FromImage(clusterPicture))
                    {
                        gfx.FillRectangle(Brushes.White, 0, 0, clusterPicture.Width, clusterPicture.Height);

                        gfx.ResetClip();
                        gfx.SetClip(translatedCombinedStaticFigure);
                        gfx.DrawImage(_sourcePicture, new Rectangle(0, 0, clusterPicture.Width, clusterPicture.Height),
                                      combinedStaticFigureLocation, GraphicsUnit.Pixel);

                        if (GameSettings.DRAW_PIECE_OUTLINE)
                        {
                            Pen outlinePen = new Pen(Color.Black)
                            {
                                Width     = GameSettings.PIECE_OUTLINE_WIDTH,
                                Alignment = PenAlignment.Inset
                            };

                            gfx.SmoothingMode = SmoothingMode.AntiAlias;
                            gfx.DrawPath(outlinePen, translatedCombinedStaticFigure);
                        }
                    }

                    Bitmap modifiedClusterPicture = (Bitmap)clusterPicture.Clone();
                    ImageUtilities.EdgeDetectHorizontal(modifiedClusterPicture);
                    ImageUtilities.EdgeDetectVertical(modifiedClusterPicture);
                    clusterPicture = ImageUtilities.AlphaBlendMatrix(modifiedClusterPicture, clusterPicture, 200);

                    #endregion

                    _currentCluster.Picture = (Bitmap)clusterPicture.Clone();

                    // Update the piece's movable figure and board location
                    foreach (Piece piece in _currentCluster.Pieces)
                    {
                        int offsetX = piece.SourcePictureLocation.X - combinedSourcePictureLocation.X;
                        int offsetY = piece.SourcePictureLocation.Y - combinedSourcePictureLocation.Y;

                        int newLocationX = combinedBoardLocation.X + offsetX;
                        int newLocationY = combinedBoardLocation.Y + offsetY;

                        piece.BoardLocation = new Rectangle(newLocationX, newLocationY, piece.Width, piece.Height);

                        Rectangle movableFigureBoardLocation = Rectangle.Truncate(piece.MovableFigure.GetBounds());

                        // Translate the movable figure to the origin first and...
                        matrix.Reset();
                        matrix.Translate(0 - movableFigureBoardLocation.X, 0 - movableFigureBoardLocation.Y);
                        piece.MovableFigure.Transform(matrix);

                        //  ...then translate to the new board location
                        matrix.Reset();
                        matrix.Translate(newLocationX, newLocationY);
                        piece.MovableFigure.Transform(matrix);
                    }

                    #region Redraw

                    #region Back buffer

                    Rectangle areaToClear = new Rectangle(combinedBoardLocation.X, combinedBoardLocation.Y,
                                                          combinedBoardLocation.Width + GameSettings.DROP_SHADOW_DEPTH,
                                                          combinedBoardLocation.Height + GameSettings.DROP_SHADOW_DEPTH);

                    using (Graphics gfx = Graphics.FromImage(_backBuffer))
                    {
                        // Clear the area with the background picture first
                        gfx.DrawImage(_background, areaToClear, areaToClear, GraphicsUnit.Pixel);

                        #region Redraw the pieces

                        Region regionToRedraw = new Region(areaToClear);

                        foreach (PieceCluster cluster in _clusters)
                        {
                            Region clusterRegion = new Region(cluster.MovableFigure);
                            clusterRegion.Intersect(regionToRedraw);

                            if (!clusterRegion.IsEmpty(gfx))
                            {
                                gfx.SetClip(clusterRegion, CombineMode.Replace);
                                gfx.DrawImageUnscaled(cluster.Picture, cluster.BoardLocation);
                            }
                        }

                        #endregion
                    }

                    #endregion

                    #region Board

                    using (Graphics gfx = Graphics.FromImage(_board))
                    {
                        gfx.DrawImageUnscaled(_backBuffer, 0, 0);
                    }

                    #endregion

                    #region Form

                    using (Graphics gfx = this.CreateGraphics())
                    {
                        gfx.DrawImageUnscaled(_backBuffer, 0, 0);
                    }

                    #endregion

                    #endregion
                }

                #endregion

                _canMovePiece   = false;
                _currentCluster = null;

                #region Victory announcement

                if (_clusters.Count == 1)
                {
                    if (_victoryAnnounced == false)
                    {
                        _victoryAnnounced = true;
                        MessageBox.Show("¡Has resuelto el rompecabezas!", "¡Felicitaciones!", MessageBoxButtons.OK);
                        Cronometro.Enabled = false;
                    }
                }

                #endregion
            }
        }
Example #9
0
        private void frmJigsawPuzzle_MouseDown(object sender, MouseEventArgs e)
        {
            #region Determine which cluster is selected (mouse down)

            int selectedIndex = -1;

            for (int index = (_clusters.Count - 1); index >= 0; index--)
            {
                if (_clusters[index].MovableFigure.IsVisible(e.X, e.Y))
                {
                    selectedIndex = index;
                    break;
                }
            }

            #endregion

            #region Bring up the selected cluster

            if (selectedIndex >= 0)
            {
                _currentCluster = _clusters[selectedIndex];

                // Make the current cluster top-most and modify the list to reflect it
                _clusters.RemoveAt(selectedIndex);
                _clusters.Add(_currentCluster);

                #region Back buffer

                // ========================================================
                // Clear the current moving piece's area with the background image and redraw the
                // pieces whose region intersect with the area.
                // ========================================================
                using (Graphics gfx = Graphics.FromImage(_backBuffer))
                {
                    Rectangle currentClusterBoardLocation = _currentCluster.BoardLocation;

                    // Clear the area with the background picture first
                    gfx.DrawImage(_background, currentClusterBoardLocation, currentClusterBoardLocation, GraphicsUnit.Pixel);

                    #region Redraw the pieces

                    Region currentClusterBoardLocationRegion = new Region(_currentCluster.BoardLocation);

                    foreach (PieceCluster cluster in _clusters)
                    {
                        if (cluster != _currentCluster)
                        {
                            Region clusterRegion = new Region(cluster.MovableFigure);
                            clusterRegion.Intersect(currentClusterBoardLocationRegion);

                            if (!clusterRegion.IsEmpty(gfx))
                            {
                                gfx.SetClip(clusterRegion, CombineMode.Replace);
                                gfx.DrawImageUnscaled(cluster.Picture, cluster.BoardLocation);
                            }
                        }
                    }

                    #endregion
                }

                #endregion

                #region Board

                Matrix     matrix      = new Matrix();
                SolidBrush shadowBrush = new SolidBrush(GameSettings.DROP_SHADOW_COLOR);

                using (Graphics gfx = Graphics.FromImage(_board))
                {
                    #region Drop shadow
                    // Simple drop shadow only for now. Alpha-blended drop shadow is too slow and jerky.
                    matrix.Reset();
                    matrix.Translate(GameSettings.DROP_SHADOW_DEPTH, GameSettings.DROP_SHADOW_DEPTH);

                    GraphicsPath shadowFigure = (GraphicsPath)_currentCluster.MovableFigure.Clone();
                    shadowFigure.Transform(matrix);

                    gfx.ResetClip();
                    gfx.SetClip(shadowFigure);
                    gfx.FillPath(shadowBrush, shadowFigure);

                    #endregion

                    #region Cluster picture

                    gfx.ResetClip();
                    gfx.SetClip(_currentCluster.MovableFigure);
                    gfx.DrawImageUnscaled(_currentCluster.Picture, _currentCluster.BoardLocation);

                    #endregion
                }

                #endregion

                #region Form

                using (Graphics gfx = this.CreateGraphics())
                {
                    gfx.DrawImageUnscaled(_board, 0, 0);
                }

                #endregion

                _previousMouseX = e.X;
                _previousMouseY = e.Y;

                _canMovePiece = true;
            }

            #endregion
        }