示例#1
0
        public bool CreateTwoSymmetricOpenCells(Coordinates coord)
        {
            if ((coord.X < 1) || (coord.Y < 1))
            {
                return(false);
            }
            if ((coord.X >= constants.dimensions) || (coord.Y >= constants.dimensions))
            {
                return(false);
            }
            ICell cell = cellMatrix[coord.X, coord.Y];

            if (cell == null)
            {
                debugLog.Write("creating an open cell at (" + coord.X + "," + coord.Y + ")\n");
                OpenCell newCell = new OpenCell(coord, this);
                cellMatrix[coord.X, coord.Y] = newCell;
                openCells.Push(newCell);
            }
            Coordinates symmCoord = new Coordinates
                                        (constants.dimensions - coord.X, constants.dimensions - coord.Y);
            ICell symmetricCell = cellMatrix[symmCoord.X, symmCoord.Y];

            if (symmetricCell == null)
            {
                debugLog.Write("creating a symmetric open cell at (" + symmCoord.X + "," + symmCoord.Y + ")\n");
                OpenCell newCell = new OpenCell(symmCoord, this);
                cellMatrix[symmCoord.X, symmCoord.Y] = newCell;
                openCells.Push(newCell);
            }
            return(true);
        }
示例#2
0
        private bool FinalizeCell(OpenCell cellToFinalize)
        {
            debugLog.Write("     FinalizeCell " + cellToFinalize.ToString() + "...\n");
            if (!cellToFinalize.OnlyOneSolution())
            {
                debugLog.Write("Finalize is a no-op, since there is still more than one possible solution.\n");
                return(false);
            }
            data.MoveToSolvedList(cellToFinalize);
            data.availableDigits.Remove(cellToFinalize.GetValue());

            cellToFinalize.SetCellAsSolved();

            foreach (OpenCell cell in data.GetCopyOfUnsolvedCells())
            {
                if (cell == cellToFinalize)
                {
                    continue;
                }
                SolutionInfo solutionInfo = cell.UpdateValueList(true);
                //if (solutionInfo.MovedCloserToSolution() && cell.OnlyOneSolution())
                //    FinalizeCell(cell);
            }
            return(true);
        }
示例#3
0
 public void MoveToSolvedList(OpenCell cell)
 {
     if (!unsolvedList.Remove(cell))
     {
         return;
     }
     solvedList.Add(cell);
 }
示例#4
0
        public void FinalizeBothParents(OpenCell cellToFinalize)
        {
            bool cellWasFinalized = true;

            foreach (CellGroup parentGroup in cellToFinalize.GetParentGroups())
            {
                cellWasFinalized &= parentGroup.FinalizeCell(cellToFinalize);
            }
            if (cellWasFinalized)
            {
                debugLog.Write("Finalized " + cellToFinalize.ToString() + ".\n");
            }
        }
示例#5
0
        private void CreateARowGroup(Coordinates coordinates)
        {
            Queue <OpenCell> cellQueue  = new Queue <OpenCell>();
            SumCell          rowSumCell = (SumCell)cellMatrix[coordinates.X - 1, coordinates.Y];

            while ((coordinates.X < constants.dimensions) && CellIsOpen(coordinates))
            {
                OpenCell cellToAdd = (OpenCell)cellMatrix[coordinates.X, coordinates.Y];
                cellQueue.Enqueue(cellToAdd);
                coordinates = new Coordinates(coordinates.X + 1, coordinates.Y);
            }
            CellGroup newGroup = new RowCellGroup(rowSumCell, new List <OpenCell>(cellQueue), debugLog);

            CellGroup.rowList.Add(newGroup);
            cellGroupsWithoutSums.Push(newGroup);
        }
示例#6
0
        private SolutionInfo CheckCellValuesForViability(OpenCell cell)
        {
//            debugLog.Write("CheckCellValuesForViability(" + cell.ToString() + ")");
            SolutionInfo solutionInfo      = new SolutionInfo();
            int          sumOfUnsolvedCels = SumOfAllUnsolvedCells();

            if (sumOfUnsolvedCels == 0)
            {
                solutionInfo.solvable = false;
                return(solutionInfo);
            }
            List <int>      possibleDigits         = new List <int>(cell.GetPossibleValues());
            int             initialNumberOfDigits  = cell.GetPossibleValues().Count;
            List <OpenCell> copyOfUnsolvedCellList = data.GetCopyOfUnsolvedCells();

            copyOfUnsolvedCellList.Remove(cell);
            Stack <OpenCell> cellStack = new Stack <OpenCell>(copyOfUnsolvedCellList);

            foreach (int digit in possibleDigits)
            {
                if (digit <= sumOfUnsolvedCels)
                {
                    List <int> availableDigitsFromGroup = new List <int>(data.availableDigits);
                    availableDigitsFromGroup.Remove(digit);
                    if (!SumWorksForGroup(sumOfUnsolvedCels - digit, availableDigitsFromGroup, cellStack))
                    {
                        cell.DigitIsNotAPossibleValue(digit);
                    }
                }
                else
                {
                    cell.DigitIsNotAPossibleValue(digit);
                }
            }
            int finalNumberOfDigits = cell.GetPossibleValues().Count;

            solutionInfo.increaseInNumber = finalNumberOfDigits - initialNumberOfDigits;
            debugLog.Write("        Validate cell " + cell.ToString() +
                           "(start:" + initialNumberOfDigits + " end:" + finalNumberOfDigits + ")\n");
            if (finalNumberOfDigits == 0)
            {
                solutionInfo.solvable = false;
            }
            return(solutionInfo);
        }
示例#7
0
        private bool SolveForLastCell()
        {
            debugLog.Write("Only one cell to try.  Solving that cell...\n");
            OpenCell cellToSolve = data.GetCopyOfUnsolvedCells().ElementAt(0);
            int      randomValue = cellToSolve.GetARandomValue();

            if (randomValue == 0)
            {
                return(false);
            }
            int sum = SumOfAllSolvedCells() + randomValue;

            if (data.unusableSums.Contains(sum))
            {
                cellToSolve.DigitIsNotAPossibleValue(randomValue);
                return(SolveForLastCell());
            }
            cellToSolve.SetToAValue(randomValue);
            FinalizeBothParents(cellToSolve);
            return(UpdateSum(sum));  // Need to deal with a failure here...
        }
示例#8
0
        private bool SumWorksForGroup(int sum, List <int> possibleDigits, Stack <OpenCell> cells)
        {
            // steps:
            // 1) pick a possible digit from the first item in the list.
            // 2) make sure that the digit chosen can't be used again.
            // 3) recurse using the sum that was passed in minus the chosen digit.

            //debugLog.Write("    Trying[sum:" + sum + ",cellCount:" + cells.Count() + "\n");

            if (cells.Count == 0)
            {
                return((sum == 0) ? true : false);
            }
            OpenCell cellToTry = cells.Pop();

            foreach (int possibleValue in cellToTry.GetPossibleValues())
            {
                if ((possibleValue <= sum) && (possibleDigits.Contains(possibleValue)))
                {
                    possibleDigits.Remove(possibleValue);
                    bool sumWorks = SumWorksForGroup(sum - possibleValue, possibleDigits, cells);
                    if (sumWorks)
                    {
//                        debugLog.Write("  Return true...\n");
                        cells.Push(cellToTry);
                        possibleDigits.Add(possibleValue);
                        return(true);
                    }
                    else
                    {
                        possibleDigits.Add(possibleValue);
                    }
                }
            }
            cells.Push(cellToTry);
            return(false);
        }
示例#9
0
 public void AddOpenCell(OpenCell cell)
 {
     Controls.Add(cell);
 }
示例#10
0
        /******************************************************
        *                  SetTheSum
        ******************************************************
        * Chooses a random solution from the possibilities.  This method assumes
        * the entire puzzle is in a state where all invalid values have been
        * tossed out.
        *
        * This method gets the cell group to a point where it is internally consistent.
        * It is up to the caller of this method to ensure that the rest of the puzzle
        * still works with the changes made here.
        *
        * Pick any valid digit for the cellToTry.  See if the cellToTry can be forced to
        * that digit by:
        * 1) setting the sum of this group (assuming it hasn't already been set)
        * 2) setting the sum of the orthoganal group (again, if it hasn't been set.)
        * 3) Seeing if minimizing this group's sum and maximizing the other's works.
        * 4) Maximize this group and minimize the other, and see if that works.
        * 5) if nothing works, return false and try a different cellToTry.
        ******************************************************/
        public UpdateResult SetTheSum()
        {
            debugLog.Write("Method SetTheSum called...\n");
            BackUpData();
//            UpdateResult result = new UpdateResult();

            if (data.NumberOfUnsolvedCells() == 0)
            {
                if (!SumIsKnown())
                {
                    debugLog.Write("Returning for empty unsolvedCellList.  Had to set the sum.\n");
                    if (!UpdateSum(SumOfAllSolvedCells()))
                    {
                        throw new UnsolvableGroupException2
                                  ("The sum of all the cells apparently doesn't work for this group.");
                    }
                    return(UpdateResult.changed);
                }
                debugLog.Write("Returning for empty unsolvedCellList.\n");
                return(UpdateResult.unchanged);
            }

            if (SumIsKnown())
            {
                debugLog.Write("Returning for already determined sum.\n");
                PrintAllCells();
                return(UpdateResult.unchanged);
            }

            UpdateAvailableValueList();  // If this changes the group, is it bad to return unchanged later on?.
            PrintAllCells();

            if (OneUnsolvedCellLeft())
            {
                if (!SolveForLastCell())
                {
                    throw new UnsolvableGroupException2("Tried the one possible solution, and bombed out.");
                }
                return(UpdateResult.changed);
            }

            OpenCell cellToSolve = data.GetCopyOfUnsolvedCells().ElementAt(0);  // To Do:  Need to make this truly random.

            if (cellToSolve.TendencyOfCell() == Tendency.low)
            {
                int  sum        = 0;
                bool successful = MaximumSum(out sum);
                if (!successful)
                {
                    throw new UnsolvableGroupException2("MaximumSum couldn't find anything.");
                }
                if (!UpdateSum(sum))
                {
                    throw new IllegalSumException2("Setting to maximum failed.");
                }
            }
            else
            {
                int  sum        = 0;
                bool successful = MinimumSum(out sum);
                if (!successful)
                {
                    throw new UnsolvableGroupException2("MinimumSum couldn't find anything.");
                }
                if (!UpdateSum(sum))
                {
                    throw new IllegalSumException2("Setting to minimum failed.");
                }
            }

            return(UpdateResult.changed);
        }