private bool TryIncludeAddOperation(List <BoardOperation> resultOperations)
        {
            var resultOperation = new BoardOperation();

            resultOperation.Type = OperationTypes.Add;
            var boardStatus = this.currentStatus;

            for (int i = 0; i < boardStatus.Length; i++)
            {
                int yOffset = -1;
                for (int j = 0; j < boardStatus[0].Length; j++)
                {
                    if (boardStatus[i][j].Type == CandyTypes.Empty)
                    {
                        yOffset++;

                        resultOperation.AddCandyOperation(new CandyOperation
                        {
                            PreviousPosition = new Coordinate {
                                X = i, Y = -1
                            },
                            CurrentPosition = new Coordinate {
                                X = i, Y = j
                            },
                            CandyProperties = new Candy
                            {
                                Type  = CandyTypes.Regular,
                                Color = this.generator.GetRandomCandyColor()
                            }
                        });
                    }
                    else
                    {
                        var opCount = resultOperation.CandyOperations.Count;
                        while (yOffset > 0)
                        {
                            var coord = resultOperation.CandyOperations[opCount - yOffset].PreviousPosition;
                            coord.Y -= yOffset;
                            resultOperation.CandyOperations[opCount - yOffset].PreviousPosition = coord;

                            yOffset--;
                        }
                        break;
                    }
                }
            }

            if (resultOperation.CandyOperations.Count > 0)
            {
                resultOperations.Add(resultOperation);
                return(true);
            }

            return(false);
        }
        private bool TryIncludeMoveOperation(List <BoardOperation> resultOperations)
        {
            var resultOperation = new BoardOperation();

            resultOperation.Type = OperationTypes.Move;
            var boardStatus = this.currentStatus;

            for (int i = 0; i < boardStatus.Length; i++)
            {
                var empty = 0;
                for (int j = boardStatus[0].Length - 1; j >= 0; j--)
                {
                    if (boardStatus[i][j].Type == CandyTypes.Empty)
                    {
                        empty++;
                    }
                    else if (empty > 0)
                    {
                        resultOperation.AddCandyOperation(new CandyOperation
                        {
                            PreviousPosition = new Coordinate {
                                X = i, Y = j
                            },
                            CurrentPosition = new Coordinate {
                                X = i, Y = j + empty
                            }
                        });
                    }
                }
            }

            if (resultOperation.CandyOperations.Count > 0)
            {
                resultOperations.Add(resultOperation);
                return(true);
            }

            return(false);
        }
        private void CreateRemoveCandyOperation(List <Coordinate> removedCoordinates, Candy[][] boardStatus, Piece piece, int i, int j, BoardOperation resultOperation)
        {
            var coordinate = new Coordinate {
                X = i, Y = j
            };

            if (removedCoordinates.Contains(coordinate) || !this.IsValidCoordinate(coordinate))
            {
                return;
            }

            removedCoordinates.Add(new Coordinate {
                X = i, Y = j
            });
            resultOperation.AddCandyOperation(new CandyOperation
            {
                PreviousPosition = new Coordinate {
                    X = i, Y = j
                },
                CurrentPosition = new Coordinate {
                    X = -1, Y = -1
                }
            });

            var candy = boardStatus[i][j];

            if (candy.Type == CandyTypes.FourInLine)
            {
                // Remove line
                if (piece.M == 1)
                {
                    for (int fi = 0; fi < boardStatus.Length; fi++)
                    {
                        this.CreateRemoveCandyOperation(removedCoordinates, boardStatus, piece, fi, j, resultOperation);
                    }
                }
                else if (piece.N == 1)
                {
                    for (int fj = 0; fj < boardStatus[0].Length; fj++)
                    {
                        this.CreateRemoveCandyOperation(removedCoordinates, boardStatus, piece, i, fj, resultOperation);
                    }
                }
            }
            if (candy.Type == CandyTypes.FourInSquare)
            {
                // Remove box of 4x4
                for (int fi = -1; fi < 2; fi++)
                {
                    for (int fj = -1; fj < 2; fj++)
                    {
                        this.CreateRemoveCandyOperation(removedCoordinates, boardStatus, piece, i + fi, j + fj, resultOperation);
                    }
                }
            }
        }
        private bool TryIncludeRemoveOperation(List <BoardOperation> resultOperations)
        {
            var addOperations     = new List <BoardOperation>();
            var removedCoordinate = new List <Coordinate>();
            var boardStatus       = this.currentStatus;

            for (int p = 0; p < pieces.Length; p++)
            {
                var piece = pieces[p];
                for (int i = 0; i <= boardStatus.Length - piece.M; i++)
                {
                    for (int j = 0; j <= boardStatus[i].Length - piece.N; j++)
                    {
                        var matching   = true;
                        var candyColor = boardStatus[i][j].Color;
                        for (int pi = 0; pi < piece.M && matching; pi++)
                        {
                            for (int pj = 0; pj < piece.N && matching; pj++)
                            {
                                var currentCoordinate = new Coordinate()
                                {
                                    X = i + pi, Y = j + pj
                                };
                                if (boardStatus[i + pi][j + pj].Color != candyColor || removedCoordinate.Contains(currentCoordinate))
                                {
                                    matching = false;
                                }
                            }
                        }

                        if (matching)
                        {
                            var resultOperation = new BoardOperation();
                            resultOperation.Type = OperationTypes.Remove;
                            for (int pi = 0; pi < piece.M; pi++)
                            {
                                for (int pj = 0; pj < piece.N; pj++)
                                {
                                    this.CreateRemoveCandyOperation(removedCoordinate, boardStatus, piece, i + pi, j + pj, resultOperation);
                                }
                            }

                            resultOperations.Add(resultOperation);

                            if (piece.AddCandy != null)
                            {
                                var addOperation = new BoardOperation();
                                addOperation.Type = OperationTypes.Add;
                                addOperation.AddCandyOperation(new CandyOperation
                                {
                                    PreviousPosition = new Coordinate {
                                        X = i, Y = j
                                    },
                                    CurrentPosition = new Coordinate {
                                        X = i, Y = j
                                    },
                                    CandyProperties = new Candy
                                    {
                                        Type  = piece.AddCandy.Value,
                                        Color = candyColor
                                    }
                                });

                                addOperations.Add(addOperation);
                            }
                        }
                    }
                }
            }

            resultOperations.AddRange(addOperations);

            return(resultOperations.Any());
        }