private void CountPossibleFullPlacesForNumber(int row, int column, int unallowedDirection, int cellsNeeded)
        {
            solver.passedFullCells.Add(new Point(row, column));

            if ((emptyCells.Count + noneFullCells.Count()) >= cellsNeeded)
            {
                return;
            }

            // up
            if (unallowedDirection != 1 && (row - 1) >= 0)
            {
                if (solver.CellIsFull((row - 1), column) && !solver.FullCellIsAlreadyPassed((row - 1), column))
                {
                    if (solver.GetCellId((row - 1), column) == 0)
                    {
                        noneFullCells.Add(new Point((row - 1), column));
                    }
                    CountPossibleFullPlacesForNumber(((row - 1)), column, 3, cellsNeeded);
                }
                else if (solver.CellIsEmpty((row - 1), column) && !emptyCells.Contains(new Point((row - 1), column)))
                {
                    emptyCells.Add(new Point((row - 1), column));
                    CountPossibleFullPlacesForNumber(((row - 1)), column, 3, cellsNeeded);
                }
            }

            // right
            if (unallowedDirection != 2 && (column + 1) < solver.gridWidth)
            {
                if (solver.CellIsFull(row, (column + 1)) && !solver.FullCellIsAlreadyPassed(row, (column + 1)))
                {
                    if (solver.GetCellId(row, (column + 1)) == 0)
                    {
                        noneFullCells.Add(new Point(row, (column + 1)));
                    }
                    CountPossibleFullPlacesForNumber(row, (column + 1), 4, cellsNeeded);
                }
                else if (solver.CellIsEmpty(row, (column + 1)) && !emptyCells.Contains(new Point(row, (column + 1))))
                {
                    emptyCells.Add(new Point(row, (column + 1)));
                    CountPossibleFullPlacesForNumber(row, (column + 1), 4, cellsNeeded);
                }
            }

            // down
            if (unallowedDirection != 3 && (row + 1) < solver.gridHeight)
            {
                if (solver.CellIsFull((row + 1), column) && !solver.FullCellIsAlreadyPassed((row + 1), column))
                {
                    if (solver.GetCellId((row + 1), column) == 0)
                    {
                        noneFullCells.Add(new Point((row + 1), column));
                    }
                    CountPossibleFullPlacesForNumber((row + 1), column, 1, cellsNeeded);
                }
                else if (solver.CellIsEmpty((row + 1), column) && !emptyCells.Contains(new Point((row + 1), column)))
                {
                    emptyCells.Add(new Point((row + 1), column));
                    CountPossibleFullPlacesForNumber((row + 1), column, 1, cellsNeeded);
                }
            }

            // left
            if (unallowedDirection != 4 && (column - 1) >= 0)
            {
                if (solver.CellIsFull(row, (column - 1)) && !solver.FullCellIsAlreadyPassed(row, (column - 1)))
                {
                    if (solver.GetCellId(row, (column - 1)) == 0)
                    {
                        noneFullCells.Add(new Point(row, (column - 1)));
                    }
                    CountPossibleFullPlacesForNumber(row, (column - 1), 2, cellsNeeded);
                }
                else if (solver.CellIsEmpty(row, (column - 1)) && !emptyCells.Contains(new Point(row, (column - 1))))
                {
                    emptyCells.Add(new Point(row, (column - 1)));
                    CountPossibleFullPlacesForNumber(row, (column - 1), 2, cellsNeeded);
                }
            }
        }
 /// <summary>
 /// Ako imamo praznu ćeliju koja je okružena horizontalno i vertikalno
 /// sa crnim poljima, onda tu središnju ćeliju stavit isto da je crna.
 /// </summary>
 private void TechniqueSurroundedSquare(int i, int j)
 {
     if (solver.CellIsEmpty(i, j) && IsCellSurroundedWithBlack(i, j))
     {
         solver.UpdateCell(i, j, 'B', -1);
     }
 }