C#
ASP.NET
VSTO
Sudoku Class
A class for representing Sudoku puzzles.
public class Sudoku9 : Sudoku { public Sudoku9() : base( 9 ) { this.__characterSet = "123456789".ToCharArray(); } private readonly char[] __characterSet; public override char[] CharacterSet { get { return this.__characterSet; } } }
public abstract class Sudoku { private int __length; private int __blockLength; private char[,] __grid; public const char NULL_CHAR = '#'; private ISudokuSolver __solver; //constructor public Sudoku( int length ) { __blockLength = (int) Math.Sqrt( length ); __length = length; __grid = new char[ __length, __length ]; for ( int i = 0; i < __length; i++ ) { for ( int j = 0; j < __length; j++ ) { __grid[ i, j ] = NULL_CHAR; } } } #region Public Interface public abstract char[] CharacterSet { get; } public int Length { get { return this.__length; } } public int BlockLength { get { return this.__blockLength; } } //'Strategy' pattern public ISudokuSolver Solver { get { return this.__solver; } set { this.__solver = value; } } public void Solve() { __solver.Sudoku = this; __solver.Solve(); } //indexer public char this[ int row, int col ] { get { __verifyIsInRange( row, col ); return __grid[ row, col ]; } set { __verifyIsInRange( row, col ); __grid[ row, col ] = value; } } public char[] GetCellValidCharacters( int row, int col ) { ArrayList possibles = new ArrayList( this.CharacterSet ); foreach ( char ch in this.CharacterSet ) { if ( !IsValidInCell( ch, row, col) ) { possibles.Remove( ch ); } } return (char[]) possibles.ToArray( typeof(char) ); } public bool IsValidInCell( char ch, int row, int col ) { return IsValidInRow( ch, row ) && IsValidInColumn( ch, col ) && IsValidInBlock( ch, row, col ); } public bool IsValidInRow( char ch, int row ) { for ( int j = 0; j < __length; j++ ) { if ( ch == __grid[ row, j ] ) { return false; } } return true; } public bool IsValidInColumn( char ch, int col ) { for ( int i = 0; i < __length; i++ ) { if ( ch == __grid[ i, col ] ) { return false; } } return true; } public bool IsValidInBlock( char ch, int row, int col ) { int col_offset = col - (col % __blockLength); int row_offset = row - (row % __blockLength); for ( int i = row_offset; i < row_offset + __blockLength; i++ ) { for ( int j = col_offset; j < col_offset + __blockLength; j++ ) { if ( ch == __grid[ i, j ] ) { return false; } } } return true; } #endregion //Let equality be value- rather than reference-based. So two instances are //equal if they have the same length, and contain the same characters. public static bool operator ==(Sudoku hic, Sudoku ille) { if ( hic.__length != ille.__length ) { return false; } for ( int row = 0; row < hic.__length; row++ ) { for ( int col = 0; col < hic.__length; col++ ) { if ( hic.__grid[row,col] != ille.__grid[row,col] ) { return false; } } } return true; } public static bool operator !=(Sudoku hic, Sudoku ille) { return !( hic == ille ); } public override bool Equals(object obj) { return this == (Sudoku) obj; } public override int GetHashCode() { return (int) this.__grid.GetHashCode(); } private void __verifyIsInRange( int row, int col ) { if ( __isNotInRange( row ) || __isNotInRange( col ) ) { throw new IndexOutOfRangeException( "Row and column indices must be nonnegative and less than " + __length.ToString() ); } } private bool __isNotInRange( int index ) { return ( index < 0 ) || ( index >= __length ); } }//end class