/// <summary> /// Checks if a given SudokuEntry is valid for the current sudoku. /// </summary> /// <param name="sudokuEntry">The SudokuEntry that we want to check.</param> /// <returns>True if the given SudokuEntry is valid for the current sudoku, otherwise false.</returns> private bool EntryIsValid(SudokuEntry sudokuEntry) { foreach (SudokuEntry entry in Entries) { // First, we check if there is a SudokuEntry with the same value as sudokuEntry in the same block, column or row as sudokuEntry. // If there is, sudokuEntry is invalid, so we return false. if (entry.Value == sudokuEntry.Value) { if (entry.BlockIndex == sudokuEntry.BlockIndex) { return(false); } if (entry.ColumnIndex == sudokuEntry.ColumnIndex) { return(false); } if (entry.RowIndex == sudokuEntry.RowIndex) { return(false); } } // Second, we check whether there already is a SudokuEntry at the same location as sudokuEntry // and if there is, and it's locked, sudokuEntry is also invalid, so we return false. if (entry.ColumnIndex == sudokuEntry.ColumnIndex && entry.RowIndex == sudokuEntry.RowIndex && entry.Locked) { return(false); } } return(true); }
/// <summary> /// Checks whether a SudokuEntry is locked or not. /// </summary> /// <param name="columnIndex">The columnIndex of the SudokuEntry that we want to check.</param> /// <param name="rowIndex">The rowIndex of the SudokuEntry that we want to check.</param> /// <returns>True if the SudokuEntry for the given rowIndex and columnIndex is locked, otherwise false.</returns> public bool EntryIsLocked(int columnIndex, int rowIndex) { SudokuEntry sudokuEntry = FindEntry(columnIndex, rowIndex); // If there isn't a SudokuEntry for the specified rowIndex and columnIndex, it çan't be locked. if (sudokuEntry == null || sudokuEntry.Locked == false) { return(false); } else { return(true); } }
/// <summary> /// Removes a SudokuEntry from the 'Entries' list. /// </summary> /// <param name="columnIndex">The columnIndex of the SudokuEntry that needs to be removed.</param> /// <param name="rowIndex">The rowIndex of the SudokuEntry that needs to be removed.</param> /// <returns>True if the SudokuEntry was removed successfully, otherwise false.</returns> public bool RemoveEntry(int columnIndex, int rowIndex) { SudokuEntry sudokuEntry = FindEntry(columnIndex, rowIndex); // If there isn't a SudokuEntry for the specified rowIndex and columnIndex, // or the found SudokuEntry is locked, we can't remove it, so return false. if (sudokuEntry == null || sudokuEntry.Locked) { return(false); } else { Entries.Remove(sudokuEntry); return(true); } }
/// <summary> /// Solve the sudoku. /// </summary> /// <param name="sudokuViewer">The current ViewerForm instance.</param> public void Solve(ViewerForm sudokuViewer) { // Here 'i' represents the columnIndex, while 'i2' respresents the rowIndex. for (int i = 0; i < GridSize; i++) { for (int i2 = 0; i2 < GridSize; i2++) { int blockIndex = Convert.ToInt32((Math.Floor((double)(i / BlockSize.Horizontal))) + ((Math.Floor((double)(i2 / BlockSize.Vertical))) * (GridSize / BlockSize.Horizontal))); SudokuEntry currentEntry = EntriesList.FindEntry(i, i2); // If there isn't a SudokuEntry at this location yet, set current value to 0. int value = currentEntry == null ? 0 : currentEntry.Value; // If the SudokuEntry at this location is locked, continue to the next location by incrementing the inner for-loop. if (currentEntry != null && currentEntry.Locked) { continue; } // If there already is a SudokuEntry at this location, which is unlocked, remove it from the 'EntriesList' // so we don't end up with multiple instances of SudokuEntry for the same location. if (value > 0) { EntriesList.RemoveEntry(i, i2); } // Here we increment 'value' so we don't end up in an endless loop where Solve() constantly finds the same value for the same location // after backtracking. if (Solve((value + 1), blockIndex, i, i2) == false) { // If we couldn't find a valid value for this location, backtrack. int[] vars = DetermineNext(i, i2); i = vars[0]; i2 = vars[1]; } // Update the progress bar to reflect current progress. (sudokuViewer.Controls[1] as ProgressBar).Value = (int)Math.Round((100d / ((double)GridSize * (double)GridSize)) * ((double)(i + 1) * (double)(GridSize))); } } // Set the progress bar to 100% when we are finished, to account for the user entering a sudoku // where the final column is already completely solved. (sudokuViewer.Controls[1] as ProgressBar).Value = 100; }
/// <summary> /// Adds a new SudokuEntry to the 'Entries' list, provided the new SudokuEntry is valid for the current sudoku. /// </summary> /// <param name="value">The 'value' the new SudokuEntry should take.</param> /// <param name="blockIndex">The 'blockIndex' for the new SudokuEntry.</param> /// <param name="columnIndex">The 'columnIndex' for the new SudokuEntry.</param> /// <param name="rowIndex">The 'rowIndex' for the new SudokuEntry.</param> /// <param name="initialRead"> /// Is true when the SudokuEntry is being added through Sudoku.ReadEntries(), /// which means that the value for this SudokuEntry was added by the user, so it should be locked. /// </param> /// <returns>True if the new SudokuEntry is valid and was added successfully, otherwise false.</returns> public bool AddEntry(int value, int blockIndex, int columnIndex, int rowIndex, bool initialRead) { // A value in a sudoku must always be >=1, so a value of 0 is invalid. if (value == 0) { return(false); } SudokuEntry sudokuEntry = new SudokuEntry(value, blockIndex, rowIndex, columnIndex, initialRead); // If sudokuEntry is valid for the current sudoku, add it to the 'Entries' list and return true, otherwise return false. if (EntryIsValid(sudokuEntry)) { Entries.Add(sudokuEntry); return(true); } else { return(false); } }