public void SolveBoard() { ReducePossibleValues(Board); //int a=int.TryParse() var linearIndices = Enumerable.Range(0, 9) .SelectMany(i => Enumerable.Range(0, 9) .Select(j => new { Row = i, Col = j })); var list = linearIndices .Select(t => new { SudoCell = Board.SudoArray[t.Row, t.Col], RowIndex = t.Row, ColumnIndex = t.Col }) .Where(x => x.SudoCell.CellValue == 0 && x.SudoCell.PossibleValues != null) .Select(x => new { x.SudoCell, x.RowIndex, x.ColumnIndex, PVCount = x.SudoCell.PossibleValues.Count }) .OrderBy(x => x.PVCount) .ToList(); // this looks like a bad logic (iterating over every single possible value and running the algorithm) // but in reality the board will be solved much earlier ... needs more testing though foreach (var a in list) { foreach (var pv in a.SudoCell.PossibleValues) { var newBoard = Board.CreateCopy(); newBoard.SolveCell(pv, a.RowIndex, a.ColumnIndex); bool isSolved = SudokuHelper.IsBoardSolved(newBoard); if (isSolved) { //IsSolved = true; Board = newBoard; return; } } } }
public static SudokoBoard CreateBoard(int[,] array) { SudokoBoard newBoard = new SudokoBoard { SudoArray = new SudokuCell[9, 9], Rows = new List <int> [9], Columns = new List <int> [9] }; //populate the rows and columns arrays for (int i = 0; i < 9; i++) { newBoard.Rows[i] = new List <int>(); for (int j = 0; j < 9; j++) { if (array[i, j] != 0) { newBoard.Rows[i].Add(array[i, j]); } } } for (int i = 0; i < 9; i++) { newBoard.Columns[i] = new List <int>(); for (int j = 0; j < 9; j++) { if (array[j, i] != 0) { newBoard.Columns[i].Add(array[j, i]); } } } // fill board and possible values for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { newBoard.SudoArray[i, j] = new SudokuCell(); newBoard.SudoArray[i, j].CellValue = array[i, j]; // if the cell dosent't have a number if (array[i, j] == 0) { //first PossibleValues array with all values from 1-9 newBoard.SudoArray[i, j].PossibleValues = new List <int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; } } } return(newBoard); }
public SudokoBoard CreateCopy() { SudokoBoard newBoard = new SudokoBoard { SudoArray = new SudokuCell[9, 9], Rows = new List <int> [9], Columns = new List <int> [9] }; // Todo : optimize this method //populate the rows and columns arrays for (int i = 0; i < 9; i++) { newBoard.Rows[i] = new List <int>(); for (int j = 0; j < 9; j++) { if (this.SudoArray[i, j].CellValue != 0) { newBoard.Rows[i].Add(this.SudoArray[i, j].CellValue); } } } for (int i = 0; i < 9; i++) { newBoard.Columns[i] = new List <int>(); for (int j = 0; j < 9; j++) { if (this.SudoArray[j, i].CellValue != 0) { newBoard.Columns[i].Add(this.SudoArray[j, i].CellValue); } } } // fill board and possible values for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { newBoard.SudoArray[i, j] = new SudokuCell(); newBoard.SudoArray[i, j].CellValue = this.SudoArray[i, j].CellValue; var possibleValues = this.SudoArray[i, j].PossibleValues; if (possibleValues != null) { newBoard.SudoArray[i, j].PossibleValues = possibleValues.Select(x => x).ToList(); } } } return(newBoard); }
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; } } } } }
/// <summary> /// Checks whether a sudoku board is valid or not based on repetition of values in a column, row or box /// </summary> /// <param name="board">Sudoku board to be tested for solution</param> /// <returns>True if input board is valid</returns> public static bool IsBoardValid(SudokoBoard board) { if (board.Rows.Any(lst => lst.Count(x => x != 0) != lst.Where(x => x != 0).Distinct().Count())) { return(false); } if (board.Columns.Any(lst => lst.Count(x => x != 0) != lst.Where(x => x != 0).Distinct().Count())) { return(false); } var boxValuesList = board.GetBoxValuesList(); if (boxValuesList.Any(lst => lst.Count(x => x != 0) != lst.Where(x => x != 0).Distinct().Count())) { return(false); } return(true); }
/// <summary> /// Checks whether a sudoku board is solved or not based on column, row or box sums /// </summary> /// <param name="board">Sudoku board to be tested for solution</param> /// <returns>True if input board is solved</returns> public static bool IsBoardSolved(SudokoBoard board) { if (board.Rows.Any(row => row.GetDistinctSum() != 45)) { return(false); } else if (board.Columns.Any(col => col.GetDistinctSum() != 45)) { return(false); } else { var lists = board.GetBoxValuesList(); if (lists.Any(list => list.GetDistinctSum() != 45)) { return(false); } } return(true); }
//private bool IsSolved { get; set; } public SudokoSolver(SudokoBoard board) { Board = board; }