public void TestComponentMethods() { int dimension = 9; SudokuGridComponent row = new SudokuGridComponent(dimension); Assert.IsNotNull(row); Assert.IsNotNull(row.Cells); Assert.AreEqual(dimension, row.Dimension); for (int i = 0; i < dimension; i++) { row.AddCell(new SudokuCell((char)('1' + i), dimension)); } Assert.IsTrue(row.Validate()); row.Cells[1].UpdateValue('-'); Assert.IsTrue(row.Validate()); row.Cells[2].UpdateValue((char)(dimension + '0')); Assert.IsFalse(row.Validate()); row[8].UpdateValue('2'); Assert.IsTrue(row.Validate()); SudokuCell newCell = new SudokuCell('-', dimension); row.AddCell(newCell); Assert.AreEqual(row.Cells.Count, dimension + 1); Assert.AreEqual(newCell, row.GetCell(9)); Assert.AreEqual('-', row.GetCell(9).Value); }
/// <summary> /// Solves a specific cell assuming a cell value and attempts to solve the complete board using recusrsion /// </summary> /// <param name="num">Initial assumed cell value</param> /// <param name="r">row number of the cell</param> /// <param name="c">column number of the cell</param> public void SolveCell(int num, int r, int c) { SudokuCell cell = this.SudoArray[r, c]; if (cell.CellValue > 0) { return; //base case } cell.CellValue = num; cell.PossibleValues = null; this.Rows[r].Add(num); this.Columns[c].Add(num); for (int x = 0; x < 9; x++) { // remove current value from all possible values in current row var horizontalSibling = this.SudoArray[r, x]; if (horizontalSibling.CellValue == 0 && horizontalSibling.PossibleValues != null) { horizontalSibling.PossibleValues.Remove(num); if (horizontalSibling.PossibleValues.Count == 1) { SolveCell(horizontalSibling.PossibleValues.First(), r, x); } } // remove current value from all possible values in current column var vertialSibling = this.SudoArray[x, c]; if (vertialSibling.CellValue == 0 && vertialSibling.PossibleValues != null) { vertialSibling.PossibleValues.Remove(num); if (vertialSibling.PossibleValues.Count == 1) { SolveCell(vertialSibling.PossibleValues.First(), x, c); } } // remove current value from all possible values in current box int a = r / 3; int b = c / 3; for (int l = 0; l < 3; l++) { for (int m = 0; m < 3; m++) { SudokuCell boxSibling = this.SudoArray[(a * 3) + l, (b * 3) + m]; if (boxSibling.CellValue == 0 && boxSibling.PossibleValues != null) { boxSibling.PossibleValues.Remove(num); if (boxSibling.PossibleValues.Count == 1) { SolveCell(boxSibling.PossibleValues.First(), (a * 3) + l, (b * 3) + m); } } } } } }
public int EliminateCandidatesInScopeOfCell(SudokuCell Cell) { int eliminatedTotal = EliminateCandidatesInScope(GetRegionScope(SudokuRegion.Row, Cell.Row)); eliminatedTotal += EliminateCandidatesInScope(GetRegionScope(SudokuRegion.Column, Cell.Column)); eliminatedTotal += EliminateCandidatesInScope(GetRegionScope(SudokuRegion.Block, Cell.Block)); return(eliminatedTotal); }
private void GenerateGameBoard() { Random random = new Random((int)DateTime.Now.Ticks); switch (_Difficulty) { case Difficulty.Easy: for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (random.Next(100) % 20 == 0) { Gameboard[i, j] = new SudokuCell(false); } else { Gameboard[i, j] = Board[i, j]; } } } break; case Difficulty.Normal: for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (random.Next(100) % 10 == 0) { Gameboard[i, j] = new SudokuCell(false); } else { Gameboard[i, j] = Board[i, j]; } } } break; case Difficulty.Hard: for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (random.Next(100) % 5 == 0) { Gameboard[i, j] = new SudokuCell(false); } else { Gameboard[i, j] = Board[i, j]; } } } break; } }
public static int GetBoxOrder(SudokuCell cell) { int boxEntry = 0; int col = cell.Column; int row = cell.Row; int dimensionRoot = (int)Math.Sqrt(cell.Markup.Count()); boxEntry = (col % dimensionRoot) + (row % dimensionRoot) * dimensionRoot; return boxEntry; }
private static void UpdateCandidatesInternal(Sudoku p_sudoku, SudokuCell p_sudokuCell) { IList <int> findPossibleCandidatesRow = FindPossibleCandidatesRow(p_sudoku, p_sudokuCell); IList <int> findPossibleCandidatesColumn = FindPossibleCandidatesColumn(p_sudoku, p_sudokuCell); IList <int> findPossibleCandidatesSquare = FindPossibleCandidatesSquare(p_sudoku, p_sudokuCell); IList <int> possibleValues = findPossibleCandidatesRow.Intersect(findPossibleCandidatesColumn) .Intersect(findPossibleCandidatesSquare).ToList(); p_sudokuCell.UpdateCandidates(possibleValues); }
public bool AddCell(SudokuCell newCell) { bool cellAdded = Validate(newCell); if (cellAdded) { Cells.Add(newCell); } return cellAdded; }
/// <summary> /// Solve what remains of the sudoku game. /// </summary> public void Solve() { // Start in the top left corner. activeCell = cells[0, 0]; // Move to first empty square (possibly first). Shift(Direction.JumpBackward); Shift(Direction.JumpForward); SolveCell(activeCell); //SolveRandom(); }
/// <summary> /// Focus on a specific button by providing the corresponding cell. /// </summary> private void Select(SudokuCell cell) { var button = gamePanel.Controls.Find(cell.ToString(), false).First(); if (button == null) { throw new ArgumentException("Cell did not have a matching control."); } button.Focus(); }
private bool AddIfIntersect(SudokuCell cell, IEnumerable <int> possibleValues, int possibleValue) { if (possibleValues.Count(x => x == possibleValue) != 1) { return(false); } this.AddValue(cell, possibleValue); return(true); }
private void AddValue(SudokuCell cell, int value) { if (this.SolverResults.Any(x => x == SolverResult.Guessed)) { cell.CalculatedAfterGuess = value; } else { cell.CalculatedValue = value; } }
public SudokuBoard() { Cells = new SudokuCell[9, 9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { Cells[i, j] = new SudokuCell(this, i, j); } } }
private bool GetConflicts(SudokuCell activeCell, int i) { foreach (SudokuCell cell in neighbors[activeCell]) { if (i == cell.Value) { return(true); } } return(false); }
/// <summary> /// Create empty cells to fill a Sudoku board of size by size. /// </summary> public static SudokuCell[,] Create(int size) { SudokuCell[,] cells = new SudokuCell[size, size]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { cells[i, j] = new SudokuCell(i, j); } } return(cells); }
private bool DoesAttemptExist(SudokuCell sudokuRowCell, int number, List <Attempt> listOfAttempts) { if (listOfAttempts == null || !listOfAttempts.Any()) { return(false); } if (listOfAttempts.Any(a => a.SudokuCell == sudokuRowCell && a.Number == number)) { return(true); } return(false); }
private void InitBoard(SudokuCell[,] board) { //i = row //j = col for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { board[i, j] = new SudokuCell(); } } }
/// <summary> /// Return a list of numbers without conflicts at a given cell. /// </summary> /// <returns>list of numbers 1-size which could be valid in a cell</returns> private List <int> GetPossibleNums(SudokuCell cell) { List <int> nums = Enumerable.Range(1, size).ToList(); for (int i = 1; i < size + 1; i++) { if (GetConflicts(cell, i)) { nums.Remove(i); } } return(nums); }
public void AddConflict(SudokuCell other) { conflicts.Add(other); other.conflicts.Add(this); // Notify cells whose conflict count has increased. if (conflicts.Count == 1) { OnValueChanged(); } if (other.conflicts.Count == 1) { other.OnValueChanged(); } }
private void GenerateSolution() { Random random = new Random(); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { SudokuCell cell = Board[i, j]; //random starter List <int> picks = cell.GetRemaining(); int num = picks.ElementAt(random.Next(0, picks.Count)); bool working = true; do { if (CheckCol(j, num, Board) && CheckRow(i, num, Board) && CheckBox(i, j, num, Board)) { Board[i, j].SetValue(num); working = false; } else { picks.Remove(num); if (picks.Count == 0) { j = j - 2; if (j <= -1) { i--; j = 7; } //back down to previous row, reset to last col cell.ResetCell(); break; } else { num = picks.ElementAt(random.Next(0, picks.Count)); } } } while (working); } } }
private static void ReducePossibleValues(SudokoBoard pBoard) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { SudokuCell cell = pBoard.SudoArray[i, j]; if (cell.CellValue == 0) { //cell.PossibleValues = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; List <int> boxValues = null; foreach (var pv in cell.PossibleValues.ToList()) { if (pBoard.Rows[i].Contains(pv)) { cell.PossibleValues.Remove(pv); } else if (pBoard.Columns[j].Contains(pv)) { cell.PossibleValues.Remove(pv); } else { if (boxValues == null) { boxValues = pBoard.GetBoxValues(i, j); // new List<int>(); } if (boxValues.Contains(pv)) { cell.PossibleValues.Remove(pv); } } } if (cell.PossibleValues.Count == 1) { cell.CellValue = cell.PossibleValues[0]; pBoard.Rows[i].Add(cell.CellValue); pBoard.Columns[j].Add(cell.CellValue); cell.PossibleValues = null; } } } } }
public override bool Equals(object obj) { if (obj == null) { return(false); } if (!(obj is SudokuCell)) { return(false); } SudokuCell other = obj as SudokuCell; return(this.X == other.X && this.Y == other.Y); }
public SudokuButton(SudokuCell cell) { Cell = cell; Font = new Font(SystemFonts.DefaultFont.FontFamily, 20); Size = new Size(40, 40); ForeColor = SystemColors.ControlDarkDark; Location = new Point(Cell.X * 40, Cell.Y * 40); FlatStyle = FlatStyle.Flat; FlatAppearance.BorderColor = Color.Black; TabStop = false; Cell.ValueChanged += cell_ValueChanged; Name = cell.ToString(); }
private static IList <int> FindPossibleCandidatesColumn(Sudoku p_sudoku, SudokuCell p_cell) { IList <int> possibleCandidates = new List <int>(); IList <SudokuCell> column = p_sudoku.GetColumn(p_cell.Column); List <int> alreadyUsedValues = column.Where(p_cell => p_cell.Value != 0).Select(p_cell => p_cell.Value).ToList(); for (int i = 0; i < p_sudoku.Size; i++) { if (!alreadyUsedValues.Contains(i + 1)) { possibleCandidates.Add(i + 1); } } return(possibleCandidates); }
public static IList <SudokuCell> GetBox(SudokuCell cell, SudokuGrid grid) { List <SudokuCell> cellList = new List <SudokuCell>(); int x = cell.X; int y = cell.Y; int width = grid.width; int height = grid.height; // Check boxes don't have duplicates. // Ex: go from 5 - (2) to 5 - (2) + 3 for (int i = x - (x % width); i < x - (x % width) + width; i++) { for (int j = y - (y % height); j < y - (y % height) + height; j++) { cellList.Add(grid.cells[i, j]); } } return(cellList); }
public void TestSudokuCellFunctions() { int symbolCount = 3; char emptyCell = '-'; SudokuCell cell = new SudokuCell(emptyCell, symbolCount); Assert.AreEqual(emptyCell, cell.Value); Assert.IsTrue(cell.Validated); foreach (bool possibility in cell.Markup) { Assert.IsTrue(possibility); } cell.UpdateValue('1'); Assert.AreEqual('1', cell.Value); Assert.IsFalse(cell.Validated); cell.UpdateValue(emptyCell); Assert.AreEqual(emptyCell, cell.Value); Assert.IsTrue(cell.Validated); }
public List <int> GetBoxValues(int i, int j) { List <int> boxValues = new List <int>(); int a = i / 3; int b = j / 3; for (int l = 0; l < 3; l++) { for (int m = 0; m < 3; m++) { SudokuCell cell2 = this.SudoArray[(a * 3) + l, (b * 3) + m]; if (cell2.CellValue != 0) { boxValues.Add(cell2.CellValue); } } } return(boxValues); }
private bool Validate(SudokuCell cellToValidate) { bool isValid = true; if (cellToValidate.Value == '-') { isValid = true; } else { foreach (SudokuCell cell in Cells) { if (!cellToValidate.Equals(cell)) { isValid &= cellToValidate.Value != cell.Value; } } } return isValid; }
private bool SolveCell(SudokuCell cell) { // Break from method if no more cells are left. if (AllCellsFilled) { return(true); } List <int> possNums = GetPossibleNums(cell); do { activeCell = cell; if (!TryRandomFromList(possNums)) { return(false); } }while (!cell.IsValid || !SolveCell(activeCell)); return(true); }
private bool SolveRandom() { if (AllCellsFilled) { return(true); } SudokuCell cell = GetRandomCell(); List <int> possNums = GetPossibleNums(cell); do { activeCell = cell; if (!TryRandomFromList(possNums)) { return(false); } }while (!cell.IsValid || !SolveCell(activeCell)); return(true); }
public bool CanNumberBeUsedInCell(int number, SudokuCell cell) { var row = GetRow(cell.RowNumber); if (row.HasNumberBeenUsed(number)) { return(false); } var column = GetColumn(cell.ColumnNumber); if (column.HasNumberBeenUsed(number)) { return(false); } var square = GetSquare(cell.RowNumber, cell.ColumnNumber); if (square.HasNumberBeenUsed(number)) { return(false); } return(true); }
/// <summary> /// Initializes a new instance of the SudokuSolver.SudokuGrid class. /// </summary> public SudokuGrid(int width, int height, int size, BlockFlag gameMode = new BlockFlag()) { this.width = width; this.height = height; this.size = size; this.cells = GridOperations.Create(size); var movement = new Movement(cells); this.mapping = new Dictionary <Direction, Func <SudokuCell, SudokuCell> > { { Direction.Up, cell => movement.Up(cell) }, { Direction.Down, cell => movement.Down(cell) }, { Direction.Left, cell => movement.Left(cell) }, { Direction.Right, cell => movement.Right(cell) }, { Direction.JumpForward, cell => movement.JumpForward(cell) }, { Direction.JumpBackward, cell => movement.JumpBackward(cell) } }; this.neighbors = Block.FindNeighbors(this, gameMode); this.activeCell = cells[0, 0]; }
/// <summary> /// Jump to the next available open or invalid cell. /// Can jump forward or backward, and past grid's borders. /// </summary> private SudokuCell Jump(SudokuCell cell, int edge, Func <SudokuCell, SudokuCell> verticalShift, Func <SudokuCell, SudokuCell> horizontalShift) { // Save the starting cell. SudokuCell startCell = cell; // Loop until a different empty or invalid cell is reached. do { // Edge of board. if (cell.X == edge) { cell = verticalShift(cell); } // Shift left or right. cell = horizontalShift(cell); // Cell is the same as start cell. if (cell.Equals(startCell)) { break; } } while (cell.Value != 0 && cell.IsValid); return(cell); }
public SudokuBoard(int numbersPerUnit) { NumbersPerUnit = numbersPerUnit; this.Rows = new List <SudokuRow>(); this.Columns = new List <SudokuColumn>(); this.Squares = new List <SudokuSquare>(); if (numbersPerUnit % 3 != 0) { throw new Exception("Number of cells in a row must be divisible by 3"); } for (int y = 0; y < numbersPerUnit; y++) { for (int x = 0; x < numbersPerUnit; x++) { var cell = new SudokuCell(x, y); var row = GetRow(y); row.AddCell(cell); var column = GetColumn(x); column.AddCell(cell); var square = GetSquare(y, x); square.AddCell(cell); } } }
int FoundNakedMatchingCandidates(List <SudokuCell> matchingGroup, SudokuRegion region, int regionIndex) { List <int> groupValues = matchingGroup[0].Candidates.ToList(); DebugWrite("Found: Naked Matching Candidates! GroupSize=\"{0}\", Region=\"{1} {2}\", Candidates=\"{3}\".", matchingGroup.Count, Enum.GetName(typeof(SudokuRegion), region), regionIndex, StaticSudoku.ArrayToString(groupValues, ",")); SudokuCell cell = matchingGroup[0]; foreach (SudokuCell seen in matchingGroup) { visitedGroups.Add(seen.GridPosition.ToString(), seen.FormatCandidatesString_Compact()); } int totalEliminated = 0; if (InSameRow(matchingGroup)) { List <SudokuCell> rowScope = _sudokuGrid.GetRowScope(cell.Row).Except(matchingGroup).ToList(); totalEliminated += RemoveCandidatesValues(groupValues, rowScope); } else if (InSameColumn(matchingGroup)) { List <SudokuCell> columnScope = _sudokuGrid.GetColumnScope(cell.Column).Except(matchingGroup).ToList(); totalEliminated += RemoveCandidatesValues(groupValues, columnScope); } if (InSameBlock(matchingGroup)) { List <SudokuCell> blockScope = _sudokuGrid.GetBlockScope(cell.Block).Except(matchingGroup).ToList(); totalEliminated += RemoveCandidatesValues(groupValues, blockScope); } return(totalEliminated); }
protected void InitComponents(string[] rows) { m_columns = new List<SudokuGridComponent>(); m_boxes = new List<SudokuGridComponent>(); m_rows = new List<SudokuGridComponent>(); for (int size = 0; size < Dimension; size++) { m_rows.Add(new SudokuGridComponent(Dimension)); m_boxes.Add(new SudokuGridComponent(Dimension)); m_columns.Add(new SudokuGridComponent(Dimension)); } for (int row = 0; row < Dimension; row++) { for (int column = 0; column < Dimension; column++) { SudokuCell cell = new SudokuCell(rows[row][column * 2], Dimension); cell.Row = row; cell.Column = column; cell.Box = ((int)Math.Sqrt(Dimension) * (row / (int)Math.Sqrt(Dimension)) + column / (int)Math.Sqrt(Dimension)); AddCell(cell); } } }
private void AddValue(SudokuCell cell, int value) { if (SolverResults.Any(x => x == SolverResult.Guessed)) { cell.CalculatedAfterGuess = value; } else { cell.CalculatedValue = value; } }
private bool AddIfIntersect(SudokuCell cell, IEnumerable<int> possibleValues, int possibleValue) { if (possibleValues.Count(x => x == possibleValue) != 1) return false; AddValue(cell, possibleValue); return true; }
int ExploreHiddenSubset(List <int> hiddenSubset, List <SudokuCell> block) { if (hiddenSubset.Count > 0) { DebugWrite("HiddenSubset: Candidate(s) ({0}) has only {1} entries in block {2}.", StaticSudoku.ArrayToString(hiddenSubset, ", "), hiddenSubset.Count, block[0].Block); List <SudokuCell> subsetCells = GetCellsWithSubset_Any(block, hiddenSubset); if (subsetCells.Count == 0) { return(0); } if (subsetCells.Count == 1 && hiddenSubset.Count == 1) { SudokuCell cell = subsetCells[0]; int val = hiddenSubset[0]; DebugWrite("ELIMINATED NAKED Candidate \"{0}\": Block {1}, column {2}, row {3}.", val, cell.Block, cell.Column, cell.Row); cell.Value = val; return(RemoveCandidatesValues(hiddenSubset, _sudokuGrid.GetCellsInScope(cell).ToList())); } else if (subsetCells.Count == 2 && hiddenSubset.Count == 2) { int col = subsetCells[0].GridPosition.Column; int row = subsetCells[0].GridPosition.Row; bool columnMatch = InSameColumn(subsetCells); bool rowMatch = InSameRow(subsetCells); if (columnMatch) { // search columns List <SudokuCell> scope = _sudokuGrid.GetColumnScope(col).Except(subsetCells).ToList(); DebugWrite("HIDDEN PAIR: Eliminated candidates ({0}) on column {1}.", StaticSudoku.ArrayToString(hiddenSubset, ","), col); return(RemoveCandidatesValues(hiddenSubset, scope)); } else if (rowMatch) { // search rows List <SudokuCell> scope = _sudokuGrid.GetRowScope(row).Except(subsetCells).ToList(); DebugWrite("HIDDEN PAIR: Eliminated candidates ({0}) on row {1}.", StaticSudoku.ArrayToString(hiddenSubset, ","), row); return(RemoveCandidatesValues(hiddenSubset, scope)); } } else if (subsetCells.Count == 3 && hiddenSubset.Count == 3) { bool columnMatch = InSameColumn(subsetCells); bool rowMatch = InSameRow(subsetCells); if (columnMatch) { int col = subsetCells[0].GridPosition.Column; DebugWrite("_____HIDDEN TRIPLE: On column {0}", col); } else if (rowMatch) { int row = subsetCells[0].GridPosition.Row; DebugWrite("_____HIDDEN TRIPLE: On row {0}", row); } } } return(0); }
public GridEnumerator(SudokuCell[] list) { cells = list; }
public bool Equals(SudokuCell p_cell) { return(p_cell.Row == Row && p_cell.Column == Column && p_cell.Value == Value); }
protected void AddCell(SudokuCell cellToAdd) { m_rows[cellToAdd.Row].AddCell(cellToAdd); m_columns[cellToAdd.Column].AddCell(cellToAdd); m_boxes[cellToAdd.Box].AddCell(cellToAdd); }