예제 #1
0
        /// <summary>
        /// A Digit in one of his peers is set.
        /// </summary>
        /// <remarks>
        /// Check if digit is possible in this house.
        /// </remarks>
        /// <param name="digit"></param>
        /// <param name="sudokuResult"></param>
        /// <returns></returns>
        internal override bool SetDigit(int digit, SudokuLog sudokuResult)
        {
            var sudokuEvent = new SudokuEvent
            {
                Value           = digit,
                SolveTechnik    = "SetDigit",
                ChangedCellBase = this,
                Action          = CellAction.SetDigitInt
            };
            var ok           = true;
            var newBaseValue = Consts.BASESTART;
            var m            = new HashSet <int>();

            foreach (var cell in _cells)
            {
                if (cell.Digit > 0)
                {
                    if (m.Contains(cell.Digit))
                    {
                        ok = false;
                        break;
                    }
                    else
                    {
                        m.Add(cell.Digit);
                        newBaseValue -= (1 << (cell.Digit - 1));
                    }
                }
            }

            if (!ok)
            {
                var resultError = sudokuResult.CreateChildResult();
                resultError.EventInfoInResult = sudokuEvent;
                resultError.Successful        = false;
                resultError.ErrorMessage      = "Digit " + digit + " is in CellContainer not possible";
                return(true);
            }

            _candidateValueInternal = newBaseValue;

            var result = sudokuResult.CreateChildResult();

            result.EventInfoInResult = new SudokuEvent
            {
                ChangedCellBase = this,
                Action          = CellAction.SetDigitInt,
                SolveTechnik    = "None",
                Value           = digit,
            };

            foreach (var cell in _cells)
            {
                cell.RemoveCandidate(digit, result);
            }

            return(true);
        }
예제 #2
0
        public void CheckLastDigit_returns_false_when_not_last_candidate_after_create_Test()
        {
            var       target       = new Cell(0);
            SudokuLog sudokuResult = null;
            var       expected     = false;
            var       actual       = target.CheckLastDigit(sudokuResult);

            Assert.AreEqual(expected, actual);
        }
예제 #3
0
        public SudokuLog CreateChildResult()
        {
            SudokuLog child = new SudokuLog
            {
                ParentSudokuResult = this
            };

            this.ChildSudokuResult.Add(child);
            return(child);
        }
예제 #4
0
        public void SetDigit_return_true_when_digit_was_set_Test()
        {
            var  target           = new Cell(0);
            var  digitFromOutside = 1;
            var  sudokuResult     = new SudokuLog();
            var  expected         = true;
            bool actual;

            actual = target.SetDigit(digitFromOutside, sudokuResult);
            Assert.AreEqual(expected, actual);
        }
예제 #5
0
        public void RemoveCandidate_BaseValue_changes_when_candidate_removes_Test()
        {
            var  target       = new Cell(0);
            var  digit        = 1;
            var  sudokuResult = new SudokuLog();
            var  expected     = true;
            bool actual;

            actual = target.RemoveCandidate(digit, sudokuResult);
            Assert.AreEqual(expected, actual);
        }
예제 #6
0
        /// <summary>
        /// Solves Sudoku with SolveTechniques (no Backtracking).
        /// </summary>
        /// <param name="sudokuResult">Log</param>
        public bool Solve(SudokuLog sudokuResult)
        {
            var tmpSudokuResult = sudokuResult;

            if (tmpSudokuResult == null)
            {
                tmpSudokuResult = new SudokuLog();
            }

            do
            {
                _keepGoingWithChecks = false;
                for (var containerIdx = 0; containerIdx < Consts.DIMENSIONSQUARE; containerIdx++)
                {
                    for (var containerType = 0; containerType < 3; containerType++)
                    {
                        if (_container[containerIdx][containerType].IsComplete())
                        {
                            continue;
                        }

                        if (_solveTechniques != null && _solveTechniques.Length > 0)
                        {
                            foreach (var st in _solveTechniques)
                            {
                                if (st.IsActive)
                                {
                                    if (!_container[containerIdx][containerType].ReCheck && st.CellView == ECellView.OnlyHouse)
                                    {
                                        continue;
                                    }

                                    try
                                    {
                                        st.SolveHouse(this, _container[containerIdx][containerType], tmpSudokuResult);
                                    }
                                    catch
                                    {
                                        return(false);
                                    }
                                    if (!tmpSudokuResult.Successful)
                                    {
                                        return(false);
                                    }
                                }
                            }
                        }
                        _container[containerIdx][containerType].ReCheck = false;
                    }
                }
            } while (_keepGoingWithChecks);
            return(tmpSudokuResult.Successful);
        }
예제 #7
0
        public SudokuLog Backtracking()
        {
            var tmpSudokuResult = new SudokuLog();

            if (!BacktrackingContinue((Board)Clone()))
            {
                tmpSudokuResult.Successful   = false;
                tmpSudokuResult.ErrorMessage = "Sudoku hat keine Lösung";
            }

            return(tmpSudokuResult);
        }
예제 #8
0
        public void CheckLastDigit_returns_false_when_not_last_candidate_Test()
        {
            var       target       = new Cell(0);
            SudokuLog sudokuResult = null;
            var       expected     = false;

            target.CheckLastDigit(sudokuResult);
            for (var x = 0; x < Consts.DIMENSIONSQUARE - 3; x++)
            {
                for (var y = x + 1; y < Consts.DIMENSIONSQUARE - 2; y++)
                {
                    var newBaseValue = (1 << x) | (1 << y);
                    target.CandidateValue = newBaseValue;
                    var actual = target.CheckLastDigit(sudokuResult);
                    Assert.AreEqual(expected, actual);
                }
            }
        }
예제 #9
0
        public void RemoveCandidate_checks_lastcandidate_Test()
        {
            var id     = 0;
            var target = new Cell(id)
            {
                CandidateValue = 7
            };
            var  sudokuResult = new SudokuLog();
            var  expected     = true;
            bool actual;

            actual = target.RemoveCandidate(1, sudokuResult);
            Assert.AreEqual(expected, actual);
            actual = target.RemoveCandidate(2, sudokuResult);
            Assert.AreEqual(expected, actual);
            expected = false;
            actual   = target.RemoveCandidate(3, sudokuResult);
            Assert.AreEqual(expected, actual);
            Assert.AreEqual(3, target.Digit);
        }
예제 #10
0
        public void Solve_Sudoku_solved_with_3_solvetechniques_and_without_backtracking_Test()
        {
            var board        = new Board(_solveTechniques);
            var simpleSudoku = @"030050040
008010500
460000012
070502080
000603000
040109030
250000098
001020600
080060020";

            var lines = simpleSudoku.Split('\n');

            for (var y = 0; y < 9; y++)
            {
                var line = lines[y];

                for (var x = 0; x < 9; x++)
                {
                    var currChar = line[x];
                    if (currChar.Equals('0'))
                    {
                        continue;
                    }

                    var result = board.SetDigit(y, x, Convert.ToInt32(currChar) - 48);
                    Assert.IsTrue(result.Successful);
                }
            }
            var sudokuResult = new SudokuLog();

            Assert.IsFalse(board.IsComplete());
            Assert.IsTrue(sudokuResult.Successful);
            board.Solve(sudokuResult);
            Assert.IsTrue(board.IsComplete());
            Assert.IsTrue(sudokuResult.Successful);
        }
예제 #11
0
        /// <summary>
        /// Set a digit at cell.
        /// </summary>
        /// <param name="cellID">ID of cell</param>
        /// <param name="digitToSet">Set Digit to Cell</param>
        /// <param name="withSolve">true = Start solving with every solvetechnique (without backtrack) after digit was set.</param>
        public SudokuLog SetDigit(int cellID, int digitToSet, bool withSolve)
        {
            var sudokuResult = new SudokuLog
            {
                EventInfoInResult = new SudokuEvent
                {
                    ChangedCellBase = null,
                    Action          = CellAction.SetDigitInt,
                    SolveTechnik    = "SetDigit",
                }
            };

            if (cellID < 0 || cellID > _cells.Length)
            {
                sudokuResult.Successful   = false;
                sudokuResult.ErrorMessage = "Cell " + cellID + " is not in range";
                return(sudokuResult);
            }
            sudokuResult.EventInfoInResult.ChangedCellBase = _cells[cellID];

            _cells[cellID].SetDigit(digitToSet, sudokuResult);
            if (sudokuResult.Successful)
            {
                _cells[cellID].IsGiven = true;
                if (withSolve)
                {
                    Solve(sudokuResult);
                }

                _history.Add(new SudokuHistoryItem(this, _cells[cellID], sudokuResult));
            }
            else
            {
                SetHistory(_history.Count - 1);
                _cells[cellID].RemoveCandidate(digitToSet, sudokuResult);
            }
            return(sudokuResult);
        }
예제 #12
0
        public void TestHardestData_Test()
        {
            IBoard <Cell> board = new Board(new DE.Onnen.Sudoku.SolveTechniques.HiddenPairTripleQuad <Cell>(), new DE.Onnen.Sudoku.SolveTechniques.LockedCandidates <Cell>(), new DE.Onnen.Sudoku.SolveTechniques.NakedPairTrippleQuad <Cell>());

            var source = TestRessources.top95;
            var i      = 0;

            for (i = 0; i < 2; i++)
            {
                IList <string> boards = source.Split('\n');

                var emh   = new int[3];
                var total = 0;
                foreach (var line in boards)
                {
                    if (line.Length < 81)
                    {
                        continue;
                    }

                    total++;
                    var currentLine = "---";

                    try
                    {
                        currentLine = line.Substring(0, 81).Replace('.', '0');
                        board.SetCellsFromString(currentLine);
                    }
                    catch (Exception ex)
                    {
                        Assert.Fail($"Error in line{total} : {currentLine} " + ex.Message);
                        continue;
                    }

                    if (board.IsComplete())
                    {
                        emh[0] += 1;
                    }
                    else
                    {
                        var result = new SudokuLog();
                        board.Solve(result);
                        if (board.IsComplete())
                        {
                            emh[1] += 1;
                        }
                        else
                        {
                            result = board.Backtracking();
                            if (!board.IsComplete() || !result.Successful)
                            {
                                Assert.Fail("Board is not solved");
                            }
                            else
                            {
                                emh[2] += 1;
                            }
                        }
                    }
                }

                source = TestRessources.HardestDatabase110626;
                board  = new Board();
                Assert.AreEqual(total, emh.Sum(x => x));
                Assert.IsTrue(total > 10);
            }

            Assert.AreEqual(i, 2);
        }