public void Assign(BoardConstraints inBoardConstraints,Board inBoard)
        {
            mBoard = inBoard;
            for (int i = 0; i < 9; ++i)
            {
                RowsConstraints[i].Assign(inBoardConstraints.RowsConstraints[i]);
                ColumnsConstraints[i].Assign(inBoardConstraints.ColumnsConstraints[i]);
                ThreeByTreeBlockConstraints[i % 3, i / 3].Assign(
                    inBoardConstraints.ThreeByTreeBlockConstraints[i % 3, i / 3]
                );
                for (int j = 0; j < 9; ++j)
                    CellsConstraints[i, j].Assign(inBoardConstraints.CellsConstraints[i, j]);

                if (inBoardConstraints.TopToBottomDiagonalConstraint != null)
                {
                    TopToBottomDiagonalConstraint = new DiagonalConstraint(true);
                    TopToBottomDiagonalConstraint.Assign(inBoardConstraints.TopToBottomDiagonalConstraint);
                }
                else
                {
                    TopToBottomDiagonalConstraint = null;
                }

                if (inBoardConstraints.mBottomToTopDiagonalConstraint != null)
                {
                    mBottomToTopDiagonalConstraint = new DiagonalConstraint(false);
                    mBottomToTopDiagonalConstraint.Assign(inBoardConstraints.mBottomToTopDiagonalConstraint);
                }
                else
                {
                    mBottomToTopDiagonalConstraint = null;
                }
            }
        }
 protected override CellConstraint GetCellFromIndex(BoardConstraints inConstraints, int inCellIndex)
 {
     if (mTopToBottom)
         return inConstraints.CellsConstraints[inCellIndex, inCellIndex];
     else
         return inConstraints.CellsConstraints[inCellIndex, 8 - inCellIndex];
 }
 public bool AssignValue(int inNumberValue, BoardConstraints inConstraints)
 {
     if (AssignValue(inNumberValue))
     {
         for (int i = 0; i < 9; ++i)
             GetCellFromIndex(inConstraints, i).AssignValue(inNumberValue);
         return true;
     }
     else
         return false;
 }
        private int SearchSollutionWithBackTracking(
            Board inBoard, 
            BoardConstraints inConstraints,
            GuessesGeneration inGuessesGeneration
        )
        {
            bool foundGoodGuess = false;
            BoardConstraints pendingConstraints = new BoardConstraints();
            Board pendingBoard = new Board();
            List<GuessGroup> guesses;
            int status = 1;

            if(mAbort || (DepthLimit == mDepth))
                return status;
            ++mDepth;
            MaxReachedDepth = (MaxReachedDepth > mDepth ? MaxReachedDepth : mDepth);
            guesses = inGuessesGeneration.GetListOfGuesses(inConstraints);
            foreach (GuessGroup guessGroup in guesses)
            {
                if(mAbort)
                    break;
                foreach(Assignment guess in guessGroup.Guesses)
                {
                    if (mAbort)
                        break;
                    ++TotalTriedGuesses;
                    pendingBoard.Assign(inBoard);
                    pendingConstraints.Assign(inConstraints, pendingBoard);
                    pendingConstraints.AssignValueToCell(guess);
                    if (SearchSollution(pendingBoard, pendingConstraints, inGuessesGeneration) == 0)
                    {
                        foundGoodGuess = true;
                        break;
                    }
                    else
                        ++TotalFailedGuesses;
                }
                if(foundGoodGuess)
                {
                    inBoard.Assign(pendingBoard);
                    inConstraints.Assign(pendingConstraints,inBoard);
                    status = 0;
                    break;
                }
            }
            --mDepth;
            return status;
        }
        public int Solve(Board inBoard,bool inUseCellGuess, bool inEnforceDiagonalsConstraint)
        {
            BoardConstraints constraints = new BoardConstraints();
            GuessesGeneration guessesGeneration = new GuessesGeneration(inUseCellGuess);
            mAbort = false;
            TotalTriedGuesses = 0;
            TotalFailedGuesses = 0;
            MaxReachedDepth = 0;
            mDepth = 0;

            int status = (constraints.Init(inBoard, inEnforceDiagonalsConstraint) ? 0 : -1);
            if (0 == status)
                status = SearchSollution(inBoard, constraints, guessesGeneration);
            if(mAbort)
                return -2;
            else
                return status;
        }
        private int SearchSollution(
            Board inBoard,
            BoardConstraints inConstraints,
            GuessesGeneration inGuessesGeneration
        )
        {
            if(inConstraints.HasConflicts())
                return -1;

            inConstraints.ImproveFollowingContraints();
            if(inBoard.IsFull())
                return 0;
            else
            {
                if (inConstraints.HasConflicts())
                    return -1;
                else
                    return SearchSollutionWithBackTracking(inBoard, inConstraints, inGuessesGeneration);
            }
        }
        public bool ImproveSingleNumberAssignment(Board inBoard, BoardConstraints inConstraints)
        {
            if (isFull())
                return false;

            int possibleAssisgnmentsCount = 0;
            List<CellConstraint> cellAssignments = new List<CellConstraint>();
            List<int> numberAssignments = new List<int>();
            CellConstraint aPossibleAssignment = null, aCell;

            foreach (int numberValue in mAllowedValues.Keys)
            {
                possibleAssisgnmentsCount = 0;
                for (int i = 0; i < 9; ++i)
                {
                    aCell = GetCellFromIndex(inConstraints, i);
                    if (inBoard.IsAvailable(aCell.GetColumn(), aCell.GetRow()) &&
                        aCell.CanAssignValue(numberValue))
                        {
                            ++possibleAssisgnmentsCount;
                            aPossibleAssignment = aCell;
                        }
                }
                if (1 == possibleAssisgnmentsCount)
                {
                    cellAssignments.Add(aPossibleAssignment);
                    numberAssignments.Add(numberValue);
                }
            }

            for (int i = 0; i < cellAssignments.Count; ++i)
            {
                inConstraints.AssignValueToCell(
                    cellAssignments[i].GetColumn(),
                    cellAssignments[i].GetRow(),
                    numberAssignments[i]
                );
            }

            return (cellAssignments.Count > 0);
        }
        public bool HasNumbersWithNoPossibleAssignments(Board inBoard, BoardConstraints inConstraints)
        {
            if (isFull())
                return false;

            int possibleAssisgnmentsCount = 0;
            CellConstraint aCell;

            foreach (int numberValue in mAllowedValues.Keys)
            {
                possibleAssisgnmentsCount = 0;
                for (int i = 0; i < 9; ++i)
                {
                    aCell = GetCellFromIndex(inConstraints, i);
                    if (inBoard.IsAvailable(aCell.GetColumn(), aCell.GetRow()) &&
                        aCell.CanAssignValue(numberValue))
                            ++possibleAssisgnmentsCount;
                }
                if (0 == possibleAssisgnmentsCount)
                    break;
            }

            return (0 == possibleAssisgnmentsCount);
        }
 protected override CellConstraint GetCellFromIndex(BoardConstraints inConstraints, int inCellIndex)
 {
     return inConstraints.CellsConstraints[inCellIndex % 3 + mLeftColumn,inCellIndex / 3 + mTopRow];
 }
 protected abstract CellConstraint GetCellFromIndex(BoardConstraints inConstraints, int inCellIndex);
 protected override CellConstraint GetCellFromIndex(BoardConstraints inConstraints, int inCellIndex)
 {
     return inConstraints.CellsConstraints[inCellIndex,mRowIndex];
 }