diff --git a/Complete/App.xaml b/Complete/App.xaml new file mode 100644 index 0000000..1093c01 --- /dev/null +++ b/Complete/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Complete/App.xaml.cs b/Complete/App.xaml.cs new file mode 100644 index 0000000..77619ef --- /dev/null +++ b/Complete/App.xaml.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace SudokuWeek4 +{ + public partial class App : Application + { + } +} diff --git a/Complete/Libraries/Sudoku.dll b/Complete/Libraries/Sudoku.dll new file mode 100644 index 0000000..925b872 Binary files /dev/null and b/Complete/Libraries/Sudoku.dll differ diff --git a/Complete/Libraries/register.bat b/Complete/Libraries/register.bat new file mode 100644 index 0000000..f54409a --- /dev/null +++ b/Complete/Libraries/register.bat @@ -0,0 +1,2 @@ + +C:\Windows\System32\regsvr32 E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll diff --git a/Complete/Libraries/unregister.bat b/Complete/Libraries/unregister.bat new file mode 100644 index 0000000..74dc2c7 --- /dev/null +++ b/Complete/Libraries/unregister.bat @@ -0,0 +1,2 @@ + +C:\Windows\System32\regsvr32 /u E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll diff --git a/Complete/Models/BoardModel.cs b/Complete/Models/BoardModel.cs new file mode 100644 index 0000000..3c38b6b --- /dev/null +++ b/Complete/Models/BoardModel.cs @@ -0,0 +1,551 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Controls.Primitives; + +namespace SudokuWeek4.Models +{ + public partial class BoardModel + { + // Define an array to hold the bigCells + private LargeCell[,] bigCells; + + // Define an array to hold the smallCells + private LittleCell[,] smallCells; + + // Define the current X position + private int currentX = 0; + + // Define the current Y position + private int currentY = 0; + + // This property will get or set the cheatmode + public static Boolean CheatMode { get; set; } + + // Define the gameFieldSize + public static int GameFieldSize; + + // Define the gameFieldCount + public static int GameFieldCount; + + // Define the GameField + private UniformGrid _gameField = new UniformGrid(); + + // Define the sodukuGame (if the DLL is enabled) + private Sudoku.IGame _sudokuGame; + + // Create a dictionary that holds the cheatDicisions + private readonly Dictionary _cheatDictionary = new Dictionary(); + + // Define if the sudokuDLL is used + private Boolean _sudokuDLL = true; + + // Define a gameFinished boolean + private Boolean _gameFinished = false; + + private int _inputCount; + + public BoardModel() + { + // Just keep smiling ^_^ + } + + // This property will get the gameField + public UniformGrid GameField + { + get { return _gameField; } + } + + // This method will set the cheatmode + public void Cheat(Boolean cheatMode = false) + { + CheatMode = cheatMode; + RefreshAllCells(); + } + + // Refresh all the cells on the gameField + public void RefreshAllCells() + { + for (int x = 0; x < GameFieldSize; x++) + { + for (int y = 0; y < GameFieldSize; y++) + { + smallCells[x, y].Refresh(); + } + } + } + + public void Reset(int gameFieldSize = 3) + { + // Clear the gameField + GameField.Children.Clear(); + + // Reset the inputCount + _inputCount = 0; + + // Reset the game Finished Boolean + _gameFinished = false; + + // Set the boardCount + GameFieldCount = gameFieldSize; + + // Set the boardSize + GameFieldSize = GameFieldCount * GameFieldCount; + + // Create all the gameField columns (depending on GameFieldSize) + GameField.Columns = GameField.Rows = GameFieldCount; + + // Create all the big cells (2D array of gamefield size) + bigCells = new LargeCell[GameFieldCount, GameFieldCount]; + + // Create the gameField + for (int i = 0; i < GameFieldSize; i++) + { + // Create a new border + Border border = new Border(); + + // Set the border thickness + border.BorderThickness = new Thickness(1); + + // Set the borderBrush color + border.BorderBrush = Brushes.Blue; + + // Add the border to the gameField + GameField.Children.Add(border); + + // Create a bigCell + LargeCell bigCell = new LargeCell(); + + // Add the bigCell as a child to the created border + border.Child = bigCell; + + // Set the bigcells relative to the gameField size + bigCells[i % GameFieldCount, i / GameFieldCount] = bigCell; + } + + // Load all the small cells + LoadAllSmallCells(); + + // Clear all the filled in values + _cheatDictionary.Clear(); + } + + // Load all the smallCells + private void LoadAllSmallCells() + { + // Check if the selected gameMode is for 3 x 3 (if not we need to disable the sudoku DLL) + if (GameFieldCount != 3) + { + _sudokuDLL = false; + MessageBox.Show("This gamemode cannot be played with the sudoku DLL. SudokuDLL unloaded"); + } + // If the sudoDLL is used we need to create a game + if (SudokuDLL) + { + try + { + _sudokuGame = new Sudoku.Game(); + _sudokuGame.create(); + Console.WriteLine("Sudoku DLL loaded successfully"); + } + catch (Exception ex) + { + Console.WriteLine("Error while loading sudoku DLL: \n\n" + ex.Message + "\n\n"); + SudokuDLL = false; + } + } + + // Create the new smallCells + smallCells = new LittleCell[GameFieldSize, GameFieldSize]; + + // Reset the current X and Y position (Selected cell) + currentX = 0; + currentY = 0; + + for (int x = 0; x < GameFieldSize; x++) + { + for (int y = 0; y < GameFieldSize; y++) + { + smallCells[x, y] = bigCells[x / GameFieldCount, y / GameFieldCount][x % GameFieldCount, y % GameFieldCount]; + smallCells[x, y].X = x; + smallCells[x, y].Y = y; + } + } + + // If the sudoku DLL is loaded we need to fill in the gameField + if (SudokuDLL) + { + FillSudokuFields(); + } + + + /* // Check array contents + Console.WriteLine("Soduku DLL contents: \n\n -------------------------------\n\n"); + for (int x = 1; x <= GameFieldSize; x++) + { + for (int y = 1; y <= GameFieldSize; y++) + { + int sudokuValue; + _sudokuGame.get(x, y, out sudokuValue); + Console.Write(sudokuValue); + if (sudokuValue == -1) + { + Console.WriteLine(); + } + } + } */ + + + smallCells[0, 0].Selected = true; + } + + // This method will fill in all the sudokuFields + private void FillSudokuFields() + { + for (int x = 0; x < GameFieldSize; x++) + { + for (int y = 0; y < GameFieldSize; y++) + { + try + { + int sudokuValue; + _sudokuGame.get(x + 1, y + 1, out sudokuValue); + + // Check if the sudoku value is not an empty (0) value + if (sudokuValue > 0) + { + // Set the specified value + SetNumber(x, y, sudokuValue, false, true); + _cheatDictionary[new IntegerPoint(x, y)] = sudokuValue; + } + } + catch (Exception ex) + { + Console.WriteLine("Error while generating the sudoku field when using the Sudoku DLL: \n\n" + ex.Message + "\n\n"); + break; + } + } + } + } + + // This method will solve the sudoku puzzle (partially) + public void solvePuzzle(int cellsOver = 0) + { + for (int i = _inputCount; i < smallCells.Length - cellsOver; i++) + { + ShowHint(); + System.Console.WriteLine(i); + } + } + + // This method will get the current clicked cell + public void MouseClicked(object sender, MouseEventArgs click) + { + /* if (sender != null) + { + UniformGrid _grid = sender as UniformGrid; + int _row = (int)_grid.GetValue(Grid.RowProperty); + int _column = (int)_grid.GetValue(Grid.ColumnProperty); + MessageBox.Show(string.Format("Grid clicked at column {0}, row {1}", _column, _row)); + } */ + } + + // This method will check what to do if a key is pressed + public void KeyPressed(KeyEventArgs e) + { + // Check if the keys left, right, up or down are pressed + if (e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down) + { + // Disable the current selected cell + smallCells[currentX, currentY].Selected = false; + + // Check which key is pressed and do the appropriate action + switch (e.Key) + { + case Key.Left: + currentX = (currentX + GameFieldSize - 1) % GameFieldSize; + break; + case Key.Right: + currentX = (currentX + 1) % GameFieldSize; + break; + case Key.Up: + currentY = (currentY + GameFieldSize - 1) % GameFieldSize; + break; + case Key.Down: + currentY = (currentY + 1) % GameFieldSize; + break; + } + + // Set the current (new) cell to be selected + smallCells[currentX, currentY].Selected = true; + } + + // Check if the numberkeys where pressed + if ((e.Key >= Key.D1 && e.Key <= Key.D9) || (e.Key >= Key.NumPad1 && e.Key <= Key.NumPad9)) + { + int number = 0; + if (e.Key >= Key.D1 && e.Key <= Key.D9) + { + number = e.Key - Key.D0; + } + else + { + number = e.Key - Key.NumPad0; + } + + IntegerPoint cellPoint = new IntegerPoint(currentX, currentY); + + // Check if the cheatmode contains the key to be pressed + if (_cheatDictionary.ContainsKey(cellPoint)) + { + // Remove the userinput at the specified location + _cheatDictionary.Remove(cellPoint); + } + + // Check if the cheatMode does not contains the pressed numberKey and if the current has a candidate that can be selected + if (!_cheatDictionary.ContainsKey(cellPoint) && smallCells[currentX, currentY].CanSet(number)) + { + if (SetNumber(currentX, currentY, number)) + { + _cheatDictionary[cellPoint] = number; + } + } + } + + if (e.Key == Key.Delete && !smallCells[currentX, currentY].ReadOnly) + { + // Add the option at the specified column + foreach (IntegerPoint cellPoint in GetPointsInColumn(currentX)) + { + smallCells[cellPoint.X, cellPoint.Y].AddOption(smallCells[currentX, currentY].Determined); + } + + // Add the option at the specified row + foreach (IntegerPoint cellPoint in GetPointsInRow(currentY)) + { + smallCells[cellPoint.X, cellPoint.Y].AddOption(smallCells[currentX, currentY].Determined); + } + + // Add the option at the specified BigCell + foreach (IntegerPoint cellPoint in GetPointsInParentBigCell(currentX, currentY)) + { + smallCells[cellPoint.X, cellPoint.Y].AddOption(smallCells[currentX, currentY].Determined); + } + + smallCells[currentX, currentY].RemoveNumber(smallCells[currentX, currentY].Determined); + } + } + + // Set the specified number + private Boolean SetNumber(int x, int y, int number, Boolean hint = false, Boolean readOnly = false) + { + if (!_gameFinished) + { + if (number < 1 || number > GameFieldSize || smallCells[x, y].ReadOnly) + { + Console.WriteLine("Cannot set the value: The value is less or greater than the GameField size. (Or the cell is readOnly)\nActual Value: " + number + "\n"); + return false; + } + + // Remove the option at the specified column + foreach (IntegerPoint cellPoint in GetPointsInColumn(x)) + { + smallCells[cellPoint.X, cellPoint.Y].RemoveOption(number); + } + + // Remove the option at the specified row + foreach (IntegerPoint cellPoint in GetPointsInRow(y)) + { + smallCells[cellPoint.X, cellPoint.Y].RemoveOption(number); + } + + // Remove the option at the specified BigCell + foreach (IntegerPoint cellPoint in GetPointsInParentBigCell(x, y)) + { + smallCells[cellPoint.X, cellPoint.Y].RemoveOption(number); + } + + // Set the userInput on the specified cell + smallCells[x, y].MakeDecision(number, hint, readOnly); + + _inputCount++; + + if (_sudokuDLL) + { + int canAdapt; + _sudokuGame.set(x + 1, y + 1, number, out canAdapt); + } + + if (CheatMode) + { + // Check which numbers are still posible to set + FindCheatNumbers(GetPointsInColumn(x)); + FindCheatNumbers(GetPointsInRow(y)); + FindCheatNumbers(GetPointsInParentBigCell(x, y)); + } + + // Check if we got a winner + if (_inputCount == smallCells.Length) + { + if (CheckWinner()) + { + _gameFinished = true; + MessageBox.Show("Game finished!"); + return false; + } + } + return true; + } + return false; + } + + // Show a hint + public void ShowHint() + { + if (_sudokuDLL) + { + int hintPossible, value, x, y; + _sudokuGame.hint(out hintPossible, out x, out y, out value); + + if (hintPossible == 1) + { + // Todo: We need to decrease the inputCount if the hint overrides a value that was already set + SetNumber(--x, --y , value, true); + } + } + } + + // Save the game + public void Save() + { + if (_sudokuDLL) + { + int write; + _sudokuGame.write(out write); + + if (write == 1) + { + MessageBox.Show("File has been saved succesfully"); + RefreshAllCells(); + } + } + } + + // Load the game + public void Load() + { + if (_sudokuDLL) + { + int read; + _sudokuGame.read(out read); + + if (read == 1) + { + MessageBox.Show("File has been loaded succesfully"); + RefreshAllCells(); + } + } + } + + public Boolean CheckWinner() + { + int endGame; + _sudokuGame.isValid(out endGame); + return endGame == 1; + } + + // Find the numbers that can be set (Cheat mode) + private void FindCheatNumbers(List optionPoints) + { + try + { + Dictionary dictionaryCount = new Dictionary(); + for (int i = 1; i <= GameFieldSize; i++) + { + dictionaryCount[i] = 0; + } + + foreach (IntegerPoint optionPoint in optionPoints) + { + foreach (int option in smallCells[optionPoint.X, optionPoint.Y].Options) + { + dictionaryCount[option]++; + } + } + + foreach (int cell in (from keys in dictionaryCount.Keys where dictionaryCount[keys] == 1 select keys).ToArray()) + { + foreach (IntegerPoint cellPoint in optionPoints) + { + if (smallCells[cellPoint.X, cellPoint.Y].CanSet(cell)) + smallCells[cellPoint.X, cellPoint.Y].SetPossible(cell); + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + // Get the current points that where set in the bigCell + private static List GetPointsInParentBigCell(int x, int y) + { + int x0 = x - x % GameFieldCount; + int y0 = y - y % GameFieldCount; + + List cellPoints = new List(); + for (int i = 0; i < GameFieldSize; i++) + { + cellPoints.Add(new IntegerPoint(x0 + i % GameFieldCount, y0 + i / GameFieldCount)); + } + return cellPoints; + } + + // Get the current points that where set in the current row + private static List GetPointsInRow(int y) + { + List cellPoints = new List(); + for (int i = 0; i < GameFieldSize; i++) + { + cellPoints.Add(new IntegerPoint(i, y)); + } + return cellPoints; + } + + // Create a property to check if the sudokuDLL is used + public Boolean SudokuDLL + { + get { return _sudokuDLL; } + set + { + _sudokuDLL = value; + Reset(GameFieldCount); + } + } + + + // Get the current points that where set in the current column + private static List GetPointsInColumn(int x) + { + List cellPoints = new List(); + for (int i = 0; i < GameFieldSize; i++) + { + cellPoints.Add(new IntegerPoint(x, i)); + } + return cellPoints; + } + } +} \ No newline at end of file diff --git a/Complete/Models/Constants.cs b/Complete/Models/Constants.cs new file mode 100644 index 0000000..f6172ee --- /dev/null +++ b/Complete/Models/Constants.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; + +namespace SudokuWeek4.Models +{ + public static class Constants + { + public static Color DefaultSmallCellFontColor = Colors.Green; + public static Color DefaultSmallCellReadOnlyFontColor = Colors.Red; + public static Color DefaultSmallCellHintFontColor = Colors.Orange; + + public static Color CheatActivedFontColor = Colors.Blue; + + } +} diff --git a/Complete/Models/Converters/BackgroundValueConverter.cs b/Complete/Models/Converters/BackgroundValueConverter.cs new file mode 100644 index 0000000..c00bd47 --- /dev/null +++ b/Complete/Models/Converters/BackgroundValueConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class BackgroundValueConverter : IValueConverter + { + private static readonly BackgroundValueConverter _instance = new BackgroundValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Boolean && targetType == typeof(Brush)) + { + Boolean color = (Boolean)value; + if (color) + return Brushes.Red; + else + return Brushes.Transparent; + } + + // The type is not a brush + return null; + } + + // Create a property to get the instance of the BackgroundValue + public static BackgroundValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Complete/Models/Converters/BorderValueConverter.cs b/Complete/Models/Converters/BorderValueConverter.cs new file mode 100644 index 0000000..b03a8e4 --- /dev/null +++ b/Complete/Models/Converters/BorderValueConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class BorderValueConverter : IValueConverter + { + private static readonly BorderValueConverter _instance = new BorderValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Boolean && targetType == typeof(Brush)) + { + Boolean color = (Boolean)value; + if (color) + return Brushes.Orange; + else + return Brushes.Transparent; + } + + // The type is not a brush + return null; + } + + // Create a property to get the instance of the BorderValue + public static BorderValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Complete/Models/Converters/Number2BrushValueConverter.cs b/Complete/Models/Converters/Number2BrushValueConverter.cs new file mode 100644 index 0000000..6b99cba --- /dev/null +++ b/Complete/Models/Converters/Number2BrushValueConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class Number2BrushValueConverter : IValueConverter + { + private static readonly Number2BrushValueConverter _instance = new Number2BrushValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is int) || targetType != typeof(Brush)) + throw new InvalidCastException(); + + int number = (int)value; + return NumberBrushes.GetBrush(number, (Color)parameter); + } + + // Create a property to get the instance of the Number2BrushValue + public static Number2BrushValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Complete/Models/Converters/OptionsValueConverter.cs b/Complete/Models/Converters/OptionsValueConverter.cs new file mode 100644 index 0000000..cfcc3df --- /dev/null +++ b/Complete/Models/Converters/OptionsValueConverter.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class OptionsValueConverter : IValueConverter + { + private static readonly OptionsValueConverter _instance = new OptionsValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is HashSet) || targetType != typeof(Brush) || !(parameter is int)) + throw new InvalidCastException(); + + HashSet set = (HashSet)value; + int number = (int)parameter; + + if (set.Contains(number) && BoardModel.CheatMode) + return NumberBrushes.GetBrush(number, Constants.CheatActivedFontColor); + else + return Brushes.Transparent; + } + + // Create a property to get the instance of the OptionsValue + public static OptionsValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Complete/Models/Converters/VisibilityValueConverter.cs b/Complete/Models/Converters/VisibilityValueConverter.cs new file mode 100644 index 0000000..ba9d832 --- /dev/null +++ b/Complete/Models/Converters/VisibilityValueConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows; + +namespace SudokuWeek4.Models.Converters +{ + internal class VisibilityValueConverter : IValueConverter + { + private static readonly VisibilityValueConverter _instance = new VisibilityValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is bool) || targetType != typeof(Visibility)) + throw new InvalidCastException(); + + bool visible = (bool)value; + if (parameter != null) + visible =! visible; + + if (visible) + return Visibility.Visible; + else + return Visibility.Hidden; + } + + // Create a property to get the instance of the OptionsValue + public static VisibilityValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Complete/Models/IntegerPoint.cs b/Complete/Models/IntegerPoint.cs new file mode 100644 index 0000000..19f1086 --- /dev/null +++ b/Complete/Models/IntegerPoint.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SudokuWeek4.Models +{ + internal struct IntegerPoint + { + public int X; + public int Y; + + public IntegerPoint(int x, int y) + { + X = x; + Y = y; + } + + // Check if the given objectPoint is an IntegerPoint + public override bool Equals(object objectPoint) + { + if( objectPoint == null || objectPoint.GetType() != typeof(IntegerPoint) ) + return false; + + return Equals((IntegerPoint)objectPoint); + } + + // Check if the X and Y are equal to eachother + public bool Equals(IntegerPoint objectPoint) + { + return objectPoint.X == X && objectPoint.Y == Y; + } + + // We do not need this (just to have all the overrides) + public override int GetHashCode() + { + return 0; + } + } +} \ No newline at end of file diff --git a/Complete/Models/LargeCell.xaml b/Complete/Models/LargeCell.xaml new file mode 100644 index 0000000..170c11e --- /dev/null +++ b/Complete/Models/LargeCell.xaml @@ -0,0 +1,6 @@ + + + diff --git a/Complete/Models/LargeCell.xaml.cs b/Complete/Models/LargeCell.xaml.cs new file mode 100644 index 0000000..7948e3a --- /dev/null +++ b/Complete/Models/LargeCell.xaml.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using SudokuWeek4.Models; + +namespace SudokuWeek4.Models +{ + public partial class LargeCell : UserControl + { + // This array will hold the smallCells + private LittleCell[,] _littleCells; + + // Create the contructor + public LargeCell() + { + try + { + InitializeComponent(); + Initialize(); + } + catch (Exception) { + System.Console.WriteLine("Cannot create the largeCell Sudoku Error."); + } + } + + // Intialize the game + private void Initialize() + { + // Clear all the contents of the bigCellGrid + bigCellGrid.Children.Clear(); + + // Set the rows and columns to the size of the gameField + bigCellGrid.Columns = bigCellGrid.Rows = BoardModel.GameFieldCount; + + // Create a new array with all the smallCells to the size of the gameField + _littleCells = new LittleCell[BoardModel.GameFieldCount, BoardModel.GameFieldCount]; + + // Create all the smallCells that will come inside the bigCells + for (int i = 0; i < BoardModel.GameFieldSize; i++) + { + Border border = new Border(); + border.BorderThickness = new Thickness (1); + border.BorderBrush = Brushes.Green; + border.Margin = new Thickness (-1, -1, 0, 0); + bigCellGrid.Children.Add (border); + + LittleCell smallCell = new LittleCell (); + border.Child = smallCell; + + _littleCells[i % BoardModel.GameFieldCount, i / BoardModel.GameFieldCount] = smallCell; + } + } + + // This property returns the specified SmallCell + public LittleCell this[int x, int y] + { + get { return _littleCells[x, y]; } + } + } +} \ No newline at end of file diff --git a/Complete/Models/LittleCell.xaml b/Complete/Models/LittleCell.xaml new file mode 100644 index 0000000..d0ec1a1 --- /dev/null +++ b/Complete/Models/LittleCell.xaml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Complete/Models/LittleCell.xaml.cs b/Complete/Models/LittleCell.xaml.cs new file mode 100644 index 0000000..cc60486 --- /dev/null +++ b/Complete/Models/LittleCell.xaml.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using SudokuWeek4.Models.Converters; +using SudokuWeek4.Models; + +namespace SudokuWeek4.Models +{ + public partial class LittleCell : UserControl, INotifyPropertyChanged + { + // Define a hashSet of the available options + private readonly HashSet _options = new HashSet(); + + // Define a hashSet of the possible solutions + private readonly HashSet _solutions = new HashSet(); + + // Define if the cell is selected + private Boolean _selected; + + // This will hold the X and Y position of the cell + public int X, Y; + + // Set the cell to be readOnly + private Boolean _readOnly; + + // Set the cell fontColor + private Color _fontColor; + + // Create a nullable int to check if the cell is already filled-in + private int? _inputPlaced; + + // Create the OnPropertyChanged Event + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged(string name) + { + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + + // Create the constructor + public LittleCell() + { + InitializeComponent(); + + // Set the color to the default color + FontColor = Colors.Green; + + // Bind the currently selected cell + Binding bind = new Binding("Selected"); + bind.Source = this; + bind.Converter = BorderValueConverter.Instance; + smallBorder.SetBinding(Border.BorderBrushProperty, bind); + + // Bind the cell if there is a solution (possible) + bind = new Binding("Solution"); + bind.Source = this; + bind.Converter = BackgroundValueConverter.Instance; + this.SetBinding(BackgroundProperty, bind); + + // Set the columns and the rows of the Options to the size of the gameField + optionsGrid.Columns = optionsGrid.Rows = BoardModel.GameFieldCount; + for (int i = 1; i <= BoardModel.GameFieldSize; i++) + { + Grid child = new Grid(); + child.Margin = new Thickness(2); + optionsGrid.Children.Add(child); + + // Bind the available options to the cells (Cheat Mode) + bind = new Binding("Options"); + bind.Source = this; + bind.Converter = OptionsValueConverter.Instance; + bind.ConverterParameter = i; + child.SetBinding(BackgroundProperty, bind); + } + + // Bind if the grid was placed + bind = new Binding("Determined"); + bind.Source = this; + bind.ConverterParameter = Constants.DefaultSmallCellFontColor; + bind.Converter = Number2BrushValueConverter.Instance; + inputGrid.SetBinding(BackgroundProperty, bind); + + // Bind if the inputGrid needs to be visible + bind = new Binding("IsDetermined"); + bind.Source = this; + bind.Converter = VisibilityValueConverter.Instance; + inputGrid.SetBinding(VisibilityProperty, bind); + + // Bind if the optionsGrid is determined + bind = new Binding("IsDetermined"); + bind.Source = this; + bind.Converter = VisibilityValueConverter.Instance; + bind.ConverterParameter = 0; + optionsGrid.SetBinding(VisibilityProperty, bind); + + Clear(); + } + + // This property will change the FontColor + public Color FontColor + { + get { return _fontColor; } + set { _fontColor = value; } + } + + // This function will clear the cell + public void Clear() + { + // Clear all the available options + _options.Clear(); + + // Add all the available options to the optionsGrid + for (int i = 1; i <= BoardModel.GameFieldSize; i++) + _options.Add(i); + + _inputPlaced = null; + _solutions.Clear(); + Refresh(); + } + + // Refresh all the bindings + public void Refresh() + { + OnPropertyChanged(null); + } + + // Create a property to get available Options (CheatMode) + public HashSet Options + { + get { return _options; } + } + + // Check if the cell can be set with a number + public Boolean CanSet(int number) + { + if (BoardModel.CheatMode) + return _options.Contains(number); + else + return true; + } + + // Remove the number from the specified cell + public void RemoveNumber(int number) + { + _inputPlaced = null; + Refresh(); + } + + // Add the option from the specified cell + public void AddOption(int number) + { + _options.Add(number); + Refresh(); + } + + // Remove the option from the specified cell + public void RemoveOption(int number) + { + _options.Remove(number); + Refresh(); + } + + // Create a property to check if the cell has a number + public bool IsDetermined + { + get { return _inputPlaced.HasValue; } + } + + // Create a property to get the current cellNumber + public int Determined + { + get { return _inputPlaced.GetValueOrDefault(); } + } + + // This method will make a decision on a specified cell + public void MakeDecision(int number, Boolean hint = false, Boolean readOnly = false) + { + if (!_readOnly) + { + _inputPlaced = number; + _readOnly = readOnly; + + if (readOnly || hint) + { + if (readOnly) + { + // Set the color of the font to the readOnly Font + FontColor = Constants.DefaultSmallCellReadOnlyFontColor; + } + else if (hint) + { + // Set the color of the font to the hint Font + FontColor = Constants.DefaultSmallCellHintFontColor; + } + + // Rebind the cell (with the new color) + Binding bind = new Binding("Determined"); + bind.Source = this; + bind.Converter = Number2BrushValueConverter.Instance; + bind.ConverterParameter = FontColor; + inputGrid.SetBinding(BackgroundProperty, bind); + } + Refresh(); + } + } + + // Create a property to check if the cell is readOnly + public Boolean ReadOnly + { + get { return _readOnly; } + } + + // Create a property to check if there is a solution + public Boolean Solution + { + get + { + if (!BoardModel.CheatMode) + return false; + + if (_inputPlaced.HasValue) + return false; + + if (_solutions.Count > 1) + return true; + + return _options.Count == 0; + } + } + + // Set the specified cell to a possible solution + public void SetPossible(int cell) + { + _solutions.Add(cell); + Refresh(); + } + + // Create a property to check which cell is selected + public Boolean Selected + { + get { return _selected; } + set + { + if (value != _selected) + { + _selected = value; + OnPropertyChanged("Selected"); + } + } + } + } +} \ No newline at end of file diff --git a/Complete/Models/NumberBrushes.cs b/Complete/Models/NumberBrushes.cs new file mode 100644 index 0000000..14b02a5 --- /dev/null +++ b/Complete/Models/NumberBrushes.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Media; +using SudokuWeek4.Models; + +namespace SudokuWeek4 +{ + internal static class NumberBrushes + { + // Create a dictionary for the cached brushes (per cell) + private static readonly Dictionary cachedBrushes = new Dictionary(); + + public static DrawingBrush GetBrush(int number, Color colorBrush) + { + // Check if the index is out of bounds + if (number < 0 || number > BoardModel.GameFieldSize) + throw new IndexOutOfRangeException(); + + // Get the cached brush (if exists) + string key = number + colorBrush.ToString(); + DrawingBrush brush; + + if (cachedBrushes.TryGetValue(key, out brush)) + return brush; + + // Create a new brush (not in cache) + FormattedText formtxt = new FormattedText(number.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Times New Roman"), 100, Brushes.Black); + Geometry textGeometry = formtxt.BuildGeometry(new Point(0, 0)); + brush = new DrawingBrush(new GeometryDrawing(new SolidColorBrush(colorBrush), null, textGeometry)); + brush.Stretch = Stretch.Uniform; + + cachedBrushes[key] = brush; + return brush; + } + } +} \ No newline at end of file diff --git a/Complete/Properties/AssemblyInfo.cs b/Complete/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..aca0baf --- /dev/null +++ b/Complete/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Sudoku" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany("SuperSmash")] +[assembly: AssemblyProduct( "Sudoku" )] +[assembly: AssemblyCopyright("Copyright © SuperSmash 2012")] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Complete/Properties/Resources.Designer.cs b/Complete/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d56fec4 --- /dev/null +++ b/Complete/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.544 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SudokuWeek4.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SudokuWeek4.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Complete/Properties/Resources.resx b/Complete/Properties/Resources.resx new file mode 100644 index 0000000..04e2214 --- /dev/null +++ b/Complete/Properties/Resources.resx @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + \ No newline at end of file diff --git a/Complete/Properties/Settings.Designer.cs b/Complete/Properties/Settings.Designer.cs new file mode 100644 index 0000000..9ff9493 --- /dev/null +++ b/Complete/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.544 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SudokuWeek4.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Complete/Properties/Settings.settings b/Complete/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Complete/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Complete/Sudoku.csproj b/Complete/Sudoku.csproj new file mode 100644 index 0000000..d5d79b6 --- /dev/null +++ b/Complete/Sudoku.csproj @@ -0,0 +1,238 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC} + WinExe + Properties + SudokuWeek4 + Sudoku + v4.0 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + + + + + 3.5 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + bin\Debug\Sudoku.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + bin\Release\Sudoku.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + false + + + + + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + 3.0 + + + 3.0 + + + 3.0 + + + 3.0 + + + + + MSBuild:Compile + Designer + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + + + + + MainWindow.xaml + Code + + + + + LargeCell.xaml + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + LittleCell.xaml + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + {FC98639C-8987-42D6-B20C-8BE179AB7C55} + 1 + 0 + 0 + tlbimp + False + True + + + + + \ No newline at end of file diff --git a/Complete/Sudoku.sln b/Complete/Sudoku.sln new file mode 100644 index 0000000..be91157 --- /dev/null +++ b/Complete/Sudoku.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sudoku", "Sudoku.csproj", "{C835CFCA-0A38-40C5-BEA8-3822441B27EC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|x86.ActiveCfg = Debug|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|x86.Build.0 = Debug|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|Any CPU.Build.0 = Release|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|x86.ActiveCfg = Release|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Complete/ViewModels/MainViewModel.cs b/Complete/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..c2c2205 --- /dev/null +++ b/Complete/ViewModels/MainViewModel.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using SudokuWeek4.Models; + +namespace SudokuWeek4.ViewModels +{ + public class MainViewModel + { + private BoardModel _board; + private UniformGrid _gameField; + + public MainViewModel(UniformGrid gameField) + { + _board = new BoardModel(); + _gameField = gameField; + _gameField.Children.Add(GameField()); + } + + public void Reset(int boardSize) + { + _board.Reset(boardSize); + } + + public void Cheat(Boolean cheatMode) + { + _board.Cheat(cheatMode); + } + + public void ShowHint() + { + _board.ShowHint(); + } + + public void Save() + { + _board.Save(); + } + + public void Load() + { + _board.Load(); + } + + public UniformGrid GameField() + { + return _board.GameField; + } + + public void EnableDLL(Boolean state) + { + _board.SudokuDLL = state; + } + + public void SolvePuzzle(int cellsOver = 0) + { + _board.solvePuzzle(cellsOver); + } + + public void keyPressed(KeyEventArgs key) + { + _board.KeyPressed(key); + } + + public void mouseClicked(object sender, MouseEventArgs click) + { + _board.MouseClicked(sender, click); + } + } +} diff --git a/Complete/Views/MainWindow.xaml b/Complete/Views/MainWindow.xaml new file mode 100644 index 0000000..be575ab --- /dev/null +++ b/Complete/Views/MainWindow.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Complete/Views/MainWindow.xaml.cs b/Complete/Views/MainWindow.xaml.cs new file mode 100644 index 0000000..183d603 --- /dev/null +++ b/Complete/Views/MainWindow.xaml.cs @@ -0,0 +1,95 @@ +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System; +using SudokuWeek4.ViewModels; +using System.Windows.Input; + +namespace SudokuWeek4 +{ + public partial class MainWindow : Window + { + private int _boardSize = 3; + private Boolean _cheatMode = false; + private Boolean _sudokuDLL = true; + private MainViewModel _mainViewModel; + + public MainWindow() + { + InitializeComponent(); + _mainViewModel = new MainViewModel(mainGrid); + Reset(_boardSize); + } + + // Reset the gameField + private void Reset(int boardSize) { + _mainViewModel.Reset(boardSize); + } + + // Save the game + private void MenuItem_Save(object sender, RoutedEventArgs e) + { + _mainViewModel.Save(); + } + + // Load the game + private void MenuItem_Load(object sender, RoutedEventArgs e) + { + _mainViewModel.Load(); + } + + // Reset the gameField + private void MenuItem_ResetBoard(object sender, RoutedEventArgs e) + { + Reset(int.Parse(((MenuItem)sender).Tag.ToString())); + } + + // Get a hint + private void MenuItem_Hint(object sender, RoutedEventArgs e) + { + _mainViewModel.ShowHint(); + } + + // Enable the sudoku DLL + private void MenuItem_EnableDLL(object sender, RoutedEventArgs e) + { + _mainViewModel.EnableDLL(_sudokuDLL =! _sudokuDLL); + } + + // Solve the sudoku puzzle + private void MenuItem_Solve(object sender, RoutedEventArgs e) + { + _mainViewModel.SolvePuzzle(); + } + + // Solve the sudoku puzzle partially + private void MenuItem_SolvePartially(object sender, RoutedEventArgs e) + { + _mainViewModel.SolvePuzzle(2); + } + + // Cheat + private void MenuItem_CheatMode(object sender, RoutedEventArgs e) + { + _mainViewModel.Cheat(_cheatMode =! _cheatMode); + } + + // Exit the application + private void MenuItem_Quit(object sender, RoutedEventArgs e) + { + Application.Current.Shutdown(1); + } + + // This method will check what to do if a key is pressed + private void mainGrid_PreviewKeyDown(object sender, KeyEventArgs key) + { + _mainViewModel.keyPressed(key); + } + + private void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs click) + { + _mainViewModel.mouseClicked(sender, click); + } + } +} \ No newline at end of file diff --git a/Complete/app.config b/Complete/app.config new file mode 100644 index 0000000..e365603 --- /dev/null +++ b/Complete/app.config @@ -0,0 +1,3 @@ + + + diff --git a/Sudoku_-_DLL/Libraries/Sudoku.dll b/Sudoku_-_DLL/Libraries/Sudoku.dll new file mode 100644 index 0000000..925b872 Binary files /dev/null and b/Sudoku_-_DLL/Libraries/Sudoku.dll differ diff --git a/Sudoku_-_DLL/Libraries/SudokuDLL.dll b/Sudoku_-_DLL/Libraries/SudokuDLL.dll new file mode 100644 index 0000000..24bafe5 Binary files /dev/null and b/Sudoku_-_DLL/Libraries/SudokuDLL.dll differ diff --git a/Sudoku_-_DLL/Libraries/register.bat b/Sudoku_-_DLL/Libraries/register.bat new file mode 100644 index 0000000..f54409a --- /dev/null +++ b/Sudoku_-_DLL/Libraries/register.bat @@ -0,0 +1,2 @@ + +C:\Windows\System32\regsvr32 E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll diff --git a/Sudoku_-_DLL/Libraries/unregister.bat b/Sudoku_-_DLL/Libraries/unregister.bat new file mode 100644 index 0000000..74dc2c7 --- /dev/null +++ b/Sudoku_-_DLL/Libraries/unregister.bat @@ -0,0 +1,2 @@ + +C:\Windows\System32\regsvr32 /u E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll diff --git a/Sudoku_-_DLL/Models/BoardModel.cs b/Sudoku_-_DLL/Models/BoardModel.cs new file mode 100644 index 0000000..3c38b6b --- /dev/null +++ b/Sudoku_-_DLL/Models/BoardModel.cs @@ -0,0 +1,551 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Windows.Controls.Primitives; + +namespace SudokuWeek4.Models +{ + public partial class BoardModel + { + // Define an array to hold the bigCells + private LargeCell[,] bigCells; + + // Define an array to hold the smallCells + private LittleCell[,] smallCells; + + // Define the current X position + private int currentX = 0; + + // Define the current Y position + private int currentY = 0; + + // This property will get or set the cheatmode + public static Boolean CheatMode { get; set; } + + // Define the gameFieldSize + public static int GameFieldSize; + + // Define the gameFieldCount + public static int GameFieldCount; + + // Define the GameField + private UniformGrid _gameField = new UniformGrid(); + + // Define the sodukuGame (if the DLL is enabled) + private Sudoku.IGame _sudokuGame; + + // Create a dictionary that holds the cheatDicisions + private readonly Dictionary _cheatDictionary = new Dictionary(); + + // Define if the sudokuDLL is used + private Boolean _sudokuDLL = true; + + // Define a gameFinished boolean + private Boolean _gameFinished = false; + + private int _inputCount; + + public BoardModel() + { + // Just keep smiling ^_^ + } + + // This property will get the gameField + public UniformGrid GameField + { + get { return _gameField; } + } + + // This method will set the cheatmode + public void Cheat(Boolean cheatMode = false) + { + CheatMode = cheatMode; + RefreshAllCells(); + } + + // Refresh all the cells on the gameField + public void RefreshAllCells() + { + for (int x = 0; x < GameFieldSize; x++) + { + for (int y = 0; y < GameFieldSize; y++) + { + smallCells[x, y].Refresh(); + } + } + } + + public void Reset(int gameFieldSize = 3) + { + // Clear the gameField + GameField.Children.Clear(); + + // Reset the inputCount + _inputCount = 0; + + // Reset the game Finished Boolean + _gameFinished = false; + + // Set the boardCount + GameFieldCount = gameFieldSize; + + // Set the boardSize + GameFieldSize = GameFieldCount * GameFieldCount; + + // Create all the gameField columns (depending on GameFieldSize) + GameField.Columns = GameField.Rows = GameFieldCount; + + // Create all the big cells (2D array of gamefield size) + bigCells = new LargeCell[GameFieldCount, GameFieldCount]; + + // Create the gameField + for (int i = 0; i < GameFieldSize; i++) + { + // Create a new border + Border border = new Border(); + + // Set the border thickness + border.BorderThickness = new Thickness(1); + + // Set the borderBrush color + border.BorderBrush = Brushes.Blue; + + // Add the border to the gameField + GameField.Children.Add(border); + + // Create a bigCell + LargeCell bigCell = new LargeCell(); + + // Add the bigCell as a child to the created border + border.Child = bigCell; + + // Set the bigcells relative to the gameField size + bigCells[i % GameFieldCount, i / GameFieldCount] = bigCell; + } + + // Load all the small cells + LoadAllSmallCells(); + + // Clear all the filled in values + _cheatDictionary.Clear(); + } + + // Load all the smallCells + private void LoadAllSmallCells() + { + // Check if the selected gameMode is for 3 x 3 (if not we need to disable the sudoku DLL) + if (GameFieldCount != 3) + { + _sudokuDLL = false; + MessageBox.Show("This gamemode cannot be played with the sudoku DLL. SudokuDLL unloaded"); + } + // If the sudoDLL is used we need to create a game + if (SudokuDLL) + { + try + { + _sudokuGame = new Sudoku.Game(); + _sudokuGame.create(); + Console.WriteLine("Sudoku DLL loaded successfully"); + } + catch (Exception ex) + { + Console.WriteLine("Error while loading sudoku DLL: \n\n" + ex.Message + "\n\n"); + SudokuDLL = false; + } + } + + // Create the new smallCells + smallCells = new LittleCell[GameFieldSize, GameFieldSize]; + + // Reset the current X and Y position (Selected cell) + currentX = 0; + currentY = 0; + + for (int x = 0; x < GameFieldSize; x++) + { + for (int y = 0; y < GameFieldSize; y++) + { + smallCells[x, y] = bigCells[x / GameFieldCount, y / GameFieldCount][x % GameFieldCount, y % GameFieldCount]; + smallCells[x, y].X = x; + smallCells[x, y].Y = y; + } + } + + // If the sudoku DLL is loaded we need to fill in the gameField + if (SudokuDLL) + { + FillSudokuFields(); + } + + + /* // Check array contents + Console.WriteLine("Soduku DLL contents: \n\n -------------------------------\n\n"); + for (int x = 1; x <= GameFieldSize; x++) + { + for (int y = 1; y <= GameFieldSize; y++) + { + int sudokuValue; + _sudokuGame.get(x, y, out sudokuValue); + Console.Write(sudokuValue); + if (sudokuValue == -1) + { + Console.WriteLine(); + } + } + } */ + + + smallCells[0, 0].Selected = true; + } + + // This method will fill in all the sudokuFields + private void FillSudokuFields() + { + for (int x = 0; x < GameFieldSize; x++) + { + for (int y = 0; y < GameFieldSize; y++) + { + try + { + int sudokuValue; + _sudokuGame.get(x + 1, y + 1, out sudokuValue); + + // Check if the sudoku value is not an empty (0) value + if (sudokuValue > 0) + { + // Set the specified value + SetNumber(x, y, sudokuValue, false, true); + _cheatDictionary[new IntegerPoint(x, y)] = sudokuValue; + } + } + catch (Exception ex) + { + Console.WriteLine("Error while generating the sudoku field when using the Sudoku DLL: \n\n" + ex.Message + "\n\n"); + break; + } + } + } + } + + // This method will solve the sudoku puzzle (partially) + public void solvePuzzle(int cellsOver = 0) + { + for (int i = _inputCount; i < smallCells.Length - cellsOver; i++) + { + ShowHint(); + System.Console.WriteLine(i); + } + } + + // This method will get the current clicked cell + public void MouseClicked(object sender, MouseEventArgs click) + { + /* if (sender != null) + { + UniformGrid _grid = sender as UniformGrid; + int _row = (int)_grid.GetValue(Grid.RowProperty); + int _column = (int)_grid.GetValue(Grid.ColumnProperty); + MessageBox.Show(string.Format("Grid clicked at column {0}, row {1}", _column, _row)); + } */ + } + + // This method will check what to do if a key is pressed + public void KeyPressed(KeyEventArgs e) + { + // Check if the keys left, right, up or down are pressed + if (e.Key == Key.Left || e.Key == Key.Right || e.Key == Key.Up || e.Key == Key.Down) + { + // Disable the current selected cell + smallCells[currentX, currentY].Selected = false; + + // Check which key is pressed and do the appropriate action + switch (e.Key) + { + case Key.Left: + currentX = (currentX + GameFieldSize - 1) % GameFieldSize; + break; + case Key.Right: + currentX = (currentX + 1) % GameFieldSize; + break; + case Key.Up: + currentY = (currentY + GameFieldSize - 1) % GameFieldSize; + break; + case Key.Down: + currentY = (currentY + 1) % GameFieldSize; + break; + } + + // Set the current (new) cell to be selected + smallCells[currentX, currentY].Selected = true; + } + + // Check if the numberkeys where pressed + if ((e.Key >= Key.D1 && e.Key <= Key.D9) || (e.Key >= Key.NumPad1 && e.Key <= Key.NumPad9)) + { + int number = 0; + if (e.Key >= Key.D1 && e.Key <= Key.D9) + { + number = e.Key - Key.D0; + } + else + { + number = e.Key - Key.NumPad0; + } + + IntegerPoint cellPoint = new IntegerPoint(currentX, currentY); + + // Check if the cheatmode contains the key to be pressed + if (_cheatDictionary.ContainsKey(cellPoint)) + { + // Remove the userinput at the specified location + _cheatDictionary.Remove(cellPoint); + } + + // Check if the cheatMode does not contains the pressed numberKey and if the current has a candidate that can be selected + if (!_cheatDictionary.ContainsKey(cellPoint) && smallCells[currentX, currentY].CanSet(number)) + { + if (SetNumber(currentX, currentY, number)) + { + _cheatDictionary[cellPoint] = number; + } + } + } + + if (e.Key == Key.Delete && !smallCells[currentX, currentY].ReadOnly) + { + // Add the option at the specified column + foreach (IntegerPoint cellPoint in GetPointsInColumn(currentX)) + { + smallCells[cellPoint.X, cellPoint.Y].AddOption(smallCells[currentX, currentY].Determined); + } + + // Add the option at the specified row + foreach (IntegerPoint cellPoint in GetPointsInRow(currentY)) + { + smallCells[cellPoint.X, cellPoint.Y].AddOption(smallCells[currentX, currentY].Determined); + } + + // Add the option at the specified BigCell + foreach (IntegerPoint cellPoint in GetPointsInParentBigCell(currentX, currentY)) + { + smallCells[cellPoint.X, cellPoint.Y].AddOption(smallCells[currentX, currentY].Determined); + } + + smallCells[currentX, currentY].RemoveNumber(smallCells[currentX, currentY].Determined); + } + } + + // Set the specified number + private Boolean SetNumber(int x, int y, int number, Boolean hint = false, Boolean readOnly = false) + { + if (!_gameFinished) + { + if (number < 1 || number > GameFieldSize || smallCells[x, y].ReadOnly) + { + Console.WriteLine("Cannot set the value: The value is less or greater than the GameField size. (Or the cell is readOnly)\nActual Value: " + number + "\n"); + return false; + } + + // Remove the option at the specified column + foreach (IntegerPoint cellPoint in GetPointsInColumn(x)) + { + smallCells[cellPoint.X, cellPoint.Y].RemoveOption(number); + } + + // Remove the option at the specified row + foreach (IntegerPoint cellPoint in GetPointsInRow(y)) + { + smallCells[cellPoint.X, cellPoint.Y].RemoveOption(number); + } + + // Remove the option at the specified BigCell + foreach (IntegerPoint cellPoint in GetPointsInParentBigCell(x, y)) + { + smallCells[cellPoint.X, cellPoint.Y].RemoveOption(number); + } + + // Set the userInput on the specified cell + smallCells[x, y].MakeDecision(number, hint, readOnly); + + _inputCount++; + + if (_sudokuDLL) + { + int canAdapt; + _sudokuGame.set(x + 1, y + 1, number, out canAdapt); + } + + if (CheatMode) + { + // Check which numbers are still posible to set + FindCheatNumbers(GetPointsInColumn(x)); + FindCheatNumbers(GetPointsInRow(y)); + FindCheatNumbers(GetPointsInParentBigCell(x, y)); + } + + // Check if we got a winner + if (_inputCount == smallCells.Length) + { + if (CheckWinner()) + { + _gameFinished = true; + MessageBox.Show("Game finished!"); + return false; + } + } + return true; + } + return false; + } + + // Show a hint + public void ShowHint() + { + if (_sudokuDLL) + { + int hintPossible, value, x, y; + _sudokuGame.hint(out hintPossible, out x, out y, out value); + + if (hintPossible == 1) + { + // Todo: We need to decrease the inputCount if the hint overrides a value that was already set + SetNumber(--x, --y , value, true); + } + } + } + + // Save the game + public void Save() + { + if (_sudokuDLL) + { + int write; + _sudokuGame.write(out write); + + if (write == 1) + { + MessageBox.Show("File has been saved succesfully"); + RefreshAllCells(); + } + } + } + + // Load the game + public void Load() + { + if (_sudokuDLL) + { + int read; + _sudokuGame.read(out read); + + if (read == 1) + { + MessageBox.Show("File has been loaded succesfully"); + RefreshAllCells(); + } + } + } + + public Boolean CheckWinner() + { + int endGame; + _sudokuGame.isValid(out endGame); + return endGame == 1; + } + + // Find the numbers that can be set (Cheat mode) + private void FindCheatNumbers(List optionPoints) + { + try + { + Dictionary dictionaryCount = new Dictionary(); + for (int i = 1; i <= GameFieldSize; i++) + { + dictionaryCount[i] = 0; + } + + foreach (IntegerPoint optionPoint in optionPoints) + { + foreach (int option in smallCells[optionPoint.X, optionPoint.Y].Options) + { + dictionaryCount[option]++; + } + } + + foreach (int cell in (from keys in dictionaryCount.Keys where dictionaryCount[keys] == 1 select keys).ToArray()) + { + foreach (IntegerPoint cellPoint in optionPoints) + { + if (smallCells[cellPoint.X, cellPoint.Y].CanSet(cell)) + smallCells[cellPoint.X, cellPoint.Y].SetPossible(cell); + } + } + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + // Get the current points that where set in the bigCell + private static List GetPointsInParentBigCell(int x, int y) + { + int x0 = x - x % GameFieldCount; + int y0 = y - y % GameFieldCount; + + List cellPoints = new List(); + for (int i = 0; i < GameFieldSize; i++) + { + cellPoints.Add(new IntegerPoint(x0 + i % GameFieldCount, y0 + i / GameFieldCount)); + } + return cellPoints; + } + + // Get the current points that where set in the current row + private static List GetPointsInRow(int y) + { + List cellPoints = new List(); + for (int i = 0; i < GameFieldSize; i++) + { + cellPoints.Add(new IntegerPoint(i, y)); + } + return cellPoints; + } + + // Create a property to check if the sudokuDLL is used + public Boolean SudokuDLL + { + get { return _sudokuDLL; } + set + { + _sudokuDLL = value; + Reset(GameFieldCount); + } + } + + + // Get the current points that where set in the current column + private static List GetPointsInColumn(int x) + { + List cellPoints = new List(); + for (int i = 0; i < GameFieldSize; i++) + { + cellPoints.Add(new IntegerPoint(x, i)); + } + return cellPoints; + } + } +} \ No newline at end of file diff --git a/Sudoku_-_DLL/Models/Constants.cs b/Sudoku_-_DLL/Models/Constants.cs new file mode 100644 index 0000000..f6172ee --- /dev/null +++ b/Sudoku_-_DLL/Models/Constants.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; + +namespace SudokuWeek4.Models +{ + public static class Constants + { + public static Color DefaultSmallCellFontColor = Colors.Green; + public static Color DefaultSmallCellReadOnlyFontColor = Colors.Red; + public static Color DefaultSmallCellHintFontColor = Colors.Orange; + + public static Color CheatActivedFontColor = Colors.Blue; + + } +} diff --git a/Sudoku_-_DLL/Models/Converters/BackgroundValueConverter.cs b/Sudoku_-_DLL/Models/Converters/BackgroundValueConverter.cs new file mode 100644 index 0000000..c00bd47 --- /dev/null +++ b/Sudoku_-_DLL/Models/Converters/BackgroundValueConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class BackgroundValueConverter : IValueConverter + { + private static readonly BackgroundValueConverter _instance = new BackgroundValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Boolean && targetType == typeof(Brush)) + { + Boolean color = (Boolean)value; + if (color) + return Brushes.Red; + else + return Brushes.Transparent; + } + + // The type is not a brush + return null; + } + + // Create a property to get the instance of the BackgroundValue + public static BackgroundValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Sudoku_-_DLL/Models/Converters/BorderValueConverter.cs b/Sudoku_-_DLL/Models/Converters/BorderValueConverter.cs new file mode 100644 index 0000000..b03a8e4 --- /dev/null +++ b/Sudoku_-_DLL/Models/Converters/BorderValueConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class BorderValueConverter : IValueConverter + { + private static readonly BorderValueConverter _instance = new BorderValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (value is Boolean && targetType == typeof(Brush)) + { + Boolean color = (Boolean)value; + if (color) + return Brushes.Orange; + else + return Brushes.Transparent; + } + + // The type is not a brush + return null; + } + + // Create a property to get the instance of the BorderValue + public static BorderValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Sudoku_-_DLL/Models/Converters/Number2BrushValueConverter.cs b/Sudoku_-_DLL/Models/Converters/Number2BrushValueConverter.cs new file mode 100644 index 0000000..6b99cba --- /dev/null +++ b/Sudoku_-_DLL/Models/Converters/Number2BrushValueConverter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class Number2BrushValueConverter : IValueConverter + { + private static readonly Number2BrushValueConverter _instance = new Number2BrushValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is int) || targetType != typeof(Brush)) + throw new InvalidCastException(); + + int number = (int)value; + return NumberBrushes.GetBrush(number, (Color)parameter); + } + + // Create a property to get the instance of the Number2BrushValue + public static Number2BrushValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Sudoku_-_DLL/Models/Converters/OptionsValueConverter.cs b/Sudoku_-_DLL/Models/Converters/OptionsValueConverter.cs new file mode 100644 index 0000000..cfcc3df --- /dev/null +++ b/Sudoku_-_DLL/Models/Converters/OptionsValueConverter.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows.Media; + +namespace SudokuWeek4.Models.Converters +{ + internal class OptionsValueConverter : IValueConverter + { + private static readonly OptionsValueConverter _instance = new OptionsValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is HashSet) || targetType != typeof(Brush) || !(parameter is int)) + throw new InvalidCastException(); + + HashSet set = (HashSet)value; + int number = (int)parameter; + + if (set.Contains(number) && BoardModel.CheatMode) + return NumberBrushes.GetBrush(number, Constants.CheatActivedFontColor); + else + return Brushes.Transparent; + } + + // Create a property to get the instance of the OptionsValue + public static OptionsValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Sudoku_-_DLL/Models/Converters/VisibilityValueConverter.cs b/Sudoku_-_DLL/Models/Converters/VisibilityValueConverter.cs new file mode 100644 index 0000000..ba9d832 --- /dev/null +++ b/Sudoku_-_DLL/Models/Converters/VisibilityValueConverter.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Data; +using System.Globalization; +using System.Windows; + +namespace SudokuWeek4.Models.Converters +{ + internal class VisibilityValueConverter : IValueConverter + { + private static readonly VisibilityValueConverter _instance = new VisibilityValueConverter(); + + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + if (!(value is bool) || targetType != typeof(Visibility)) + throw new InvalidCastException(); + + bool visible = (bool)value; + if (parameter != null) + visible =! visible; + + if (visible) + return Visibility.Visible; + else + return Visibility.Hidden; + } + + // Create a property to get the instance of the OptionsValue + public static VisibilityValueConverter Instance + { + get { return _instance; } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Sudoku_-_DLL/Models/IntegerPoint.cs b/Sudoku_-_DLL/Models/IntegerPoint.cs new file mode 100644 index 0000000..19f1086 --- /dev/null +++ b/Sudoku_-_DLL/Models/IntegerPoint.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SudokuWeek4.Models +{ + internal struct IntegerPoint + { + public int X; + public int Y; + + public IntegerPoint(int x, int y) + { + X = x; + Y = y; + } + + // Check if the given objectPoint is an IntegerPoint + public override bool Equals(object objectPoint) + { + if( objectPoint == null || objectPoint.GetType() != typeof(IntegerPoint) ) + return false; + + return Equals((IntegerPoint)objectPoint); + } + + // Check if the X and Y are equal to eachother + public bool Equals(IntegerPoint objectPoint) + { + return objectPoint.X == X && objectPoint.Y == Y; + } + + // We do not need this (just to have all the overrides) + public override int GetHashCode() + { + return 0; + } + } +} \ No newline at end of file diff --git a/Sudoku_-_DLL/Models/LargeCell.xaml b/Sudoku_-_DLL/Models/LargeCell.xaml new file mode 100644 index 0000000..170c11e --- /dev/null +++ b/Sudoku_-_DLL/Models/LargeCell.xaml @@ -0,0 +1,6 @@ + + + diff --git a/Sudoku_-_DLL/Models/LargeCell.xaml.cs b/Sudoku_-_DLL/Models/LargeCell.xaml.cs new file mode 100644 index 0000000..7948e3a --- /dev/null +++ b/Sudoku_-_DLL/Models/LargeCell.xaml.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using SudokuWeek4.Models; + +namespace SudokuWeek4.Models +{ + public partial class LargeCell : UserControl + { + // This array will hold the smallCells + private LittleCell[,] _littleCells; + + // Create the contructor + public LargeCell() + { + try + { + InitializeComponent(); + Initialize(); + } + catch (Exception) { + System.Console.WriteLine("Cannot create the largeCell Sudoku Error."); + } + } + + // Intialize the game + private void Initialize() + { + // Clear all the contents of the bigCellGrid + bigCellGrid.Children.Clear(); + + // Set the rows and columns to the size of the gameField + bigCellGrid.Columns = bigCellGrid.Rows = BoardModel.GameFieldCount; + + // Create a new array with all the smallCells to the size of the gameField + _littleCells = new LittleCell[BoardModel.GameFieldCount, BoardModel.GameFieldCount]; + + // Create all the smallCells that will come inside the bigCells + for (int i = 0; i < BoardModel.GameFieldSize; i++) + { + Border border = new Border(); + border.BorderThickness = new Thickness (1); + border.BorderBrush = Brushes.Green; + border.Margin = new Thickness (-1, -1, 0, 0); + bigCellGrid.Children.Add (border); + + LittleCell smallCell = new LittleCell (); + border.Child = smallCell; + + _littleCells[i % BoardModel.GameFieldCount, i / BoardModel.GameFieldCount] = smallCell; + } + } + + // This property returns the specified SmallCell + public LittleCell this[int x, int y] + { + get { return _littleCells[x, y]; } + } + } +} \ No newline at end of file diff --git a/Sudoku_-_DLL/Models/LittleCell.xaml b/Sudoku_-_DLL/Models/LittleCell.xaml new file mode 100644 index 0000000..d0ec1a1 --- /dev/null +++ b/Sudoku_-_DLL/Models/LittleCell.xaml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/Sudoku_-_DLL/Models/LittleCell.xaml.cs b/Sudoku_-_DLL/Models/LittleCell.xaml.cs new file mode 100644 index 0000000..cc60486 --- /dev/null +++ b/Sudoku_-_DLL/Models/LittleCell.xaml.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using SudokuWeek4.Models.Converters; +using SudokuWeek4.Models; + +namespace SudokuWeek4.Models +{ + public partial class LittleCell : UserControl, INotifyPropertyChanged + { + // Define a hashSet of the available options + private readonly HashSet _options = new HashSet(); + + // Define a hashSet of the possible solutions + private readonly HashSet _solutions = new HashSet(); + + // Define if the cell is selected + private Boolean _selected; + + // This will hold the X and Y position of the cell + public int X, Y; + + // Set the cell to be readOnly + private Boolean _readOnly; + + // Set the cell fontColor + private Color _fontColor; + + // Create a nullable int to check if the cell is already filled-in + private int? _inputPlaced; + + // Create the OnPropertyChanged Event + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged(string name) + { + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs(name)); + } + + // Create the constructor + public LittleCell() + { + InitializeComponent(); + + // Set the color to the default color + FontColor = Colors.Green; + + // Bind the currently selected cell + Binding bind = new Binding("Selected"); + bind.Source = this; + bind.Converter = BorderValueConverter.Instance; + smallBorder.SetBinding(Border.BorderBrushProperty, bind); + + // Bind the cell if there is a solution (possible) + bind = new Binding("Solution"); + bind.Source = this; + bind.Converter = BackgroundValueConverter.Instance; + this.SetBinding(BackgroundProperty, bind); + + // Set the columns and the rows of the Options to the size of the gameField + optionsGrid.Columns = optionsGrid.Rows = BoardModel.GameFieldCount; + for (int i = 1; i <= BoardModel.GameFieldSize; i++) + { + Grid child = new Grid(); + child.Margin = new Thickness(2); + optionsGrid.Children.Add(child); + + // Bind the available options to the cells (Cheat Mode) + bind = new Binding("Options"); + bind.Source = this; + bind.Converter = OptionsValueConverter.Instance; + bind.ConverterParameter = i; + child.SetBinding(BackgroundProperty, bind); + } + + // Bind if the grid was placed + bind = new Binding("Determined"); + bind.Source = this; + bind.ConverterParameter = Constants.DefaultSmallCellFontColor; + bind.Converter = Number2BrushValueConverter.Instance; + inputGrid.SetBinding(BackgroundProperty, bind); + + // Bind if the inputGrid needs to be visible + bind = new Binding("IsDetermined"); + bind.Source = this; + bind.Converter = VisibilityValueConverter.Instance; + inputGrid.SetBinding(VisibilityProperty, bind); + + // Bind if the optionsGrid is determined + bind = new Binding("IsDetermined"); + bind.Source = this; + bind.Converter = VisibilityValueConverter.Instance; + bind.ConverterParameter = 0; + optionsGrid.SetBinding(VisibilityProperty, bind); + + Clear(); + } + + // This property will change the FontColor + public Color FontColor + { + get { return _fontColor; } + set { _fontColor = value; } + } + + // This function will clear the cell + public void Clear() + { + // Clear all the available options + _options.Clear(); + + // Add all the available options to the optionsGrid + for (int i = 1; i <= BoardModel.GameFieldSize; i++) + _options.Add(i); + + _inputPlaced = null; + _solutions.Clear(); + Refresh(); + } + + // Refresh all the bindings + public void Refresh() + { + OnPropertyChanged(null); + } + + // Create a property to get available Options (CheatMode) + public HashSet Options + { + get { return _options; } + } + + // Check if the cell can be set with a number + public Boolean CanSet(int number) + { + if (BoardModel.CheatMode) + return _options.Contains(number); + else + return true; + } + + // Remove the number from the specified cell + public void RemoveNumber(int number) + { + _inputPlaced = null; + Refresh(); + } + + // Add the option from the specified cell + public void AddOption(int number) + { + _options.Add(number); + Refresh(); + } + + // Remove the option from the specified cell + public void RemoveOption(int number) + { + _options.Remove(number); + Refresh(); + } + + // Create a property to check if the cell has a number + public bool IsDetermined + { + get { return _inputPlaced.HasValue; } + } + + // Create a property to get the current cellNumber + public int Determined + { + get { return _inputPlaced.GetValueOrDefault(); } + } + + // This method will make a decision on a specified cell + public void MakeDecision(int number, Boolean hint = false, Boolean readOnly = false) + { + if (!_readOnly) + { + _inputPlaced = number; + _readOnly = readOnly; + + if (readOnly || hint) + { + if (readOnly) + { + // Set the color of the font to the readOnly Font + FontColor = Constants.DefaultSmallCellReadOnlyFontColor; + } + else if (hint) + { + // Set the color of the font to the hint Font + FontColor = Constants.DefaultSmallCellHintFontColor; + } + + // Rebind the cell (with the new color) + Binding bind = new Binding("Determined"); + bind.Source = this; + bind.Converter = Number2BrushValueConverter.Instance; + bind.ConverterParameter = FontColor; + inputGrid.SetBinding(BackgroundProperty, bind); + } + Refresh(); + } + } + + // Create a property to check if the cell is readOnly + public Boolean ReadOnly + { + get { return _readOnly; } + } + + // Create a property to check if there is a solution + public Boolean Solution + { + get + { + if (!BoardModel.CheatMode) + return false; + + if (_inputPlaced.HasValue) + return false; + + if (_solutions.Count > 1) + return true; + + return _options.Count == 0; + } + } + + // Set the specified cell to a possible solution + public void SetPossible(int cell) + { + _solutions.Add(cell); + Refresh(); + } + + // Create a property to check which cell is selected + public Boolean Selected + { + get { return _selected; } + set + { + if (value != _selected) + { + _selected = value; + OnPropertyChanged("Selected"); + } + } + } + } +} \ No newline at end of file diff --git a/Sudoku_-_DLL/Models/NumberBrushes.cs b/Sudoku_-_DLL/Models/NumberBrushes.cs new file mode 100644 index 0000000..14b02a5 --- /dev/null +++ b/Sudoku_-_DLL/Models/NumberBrushes.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using System.Windows; +using System.Windows.Media; +using SudokuWeek4.Models; + +namespace SudokuWeek4 +{ + internal static class NumberBrushes + { + // Create a dictionary for the cached brushes (per cell) + private static readonly Dictionary cachedBrushes = new Dictionary(); + + public static DrawingBrush GetBrush(int number, Color colorBrush) + { + // Check if the index is out of bounds + if (number < 0 || number > BoardModel.GameFieldSize) + throw new IndexOutOfRangeException(); + + // Get the cached brush (if exists) + string key = number + colorBrush.ToString(); + DrawingBrush brush; + + if (cachedBrushes.TryGetValue(key, out brush)) + return brush; + + // Create a new brush (not in cache) + FormattedText formtxt = new FormattedText(number.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Times New Roman"), 100, Brushes.Black); + Geometry textGeometry = formtxt.BuildGeometry(new Point(0, 0)); + brush = new DrawingBrush(new GeometryDrawing(new SolidColorBrush(colorBrush), null, textGeometry)); + brush.Stretch = Stretch.Uniform; + + cachedBrushes[key] = brush; + return brush; + } + } +} \ No newline at end of file diff --git a/Sudoku_-_DLL/Properties/AssemblyInfo.cs b/Sudoku_-_DLL/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..aca0baf --- /dev/null +++ b/Sudoku_-_DLL/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Sudoku" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany("SuperSmash")] +[assembly: AssemblyProduct( "Sudoku" )] +[assembly: AssemblyCopyright("Copyright © SuperSmash 2012")] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Sudoku_-_DLL/Properties/Resources.Designer.cs b/Sudoku_-_DLL/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d56fec4 --- /dev/null +++ b/Sudoku_-_DLL/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.544 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SudokuWeek4.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SudokuWeek4.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Sudoku_-_DLL/Properties/Resources.resx b/Sudoku_-_DLL/Properties/Resources.resx new file mode 100644 index 0000000..04e2214 --- /dev/null +++ b/Sudoku_-_DLL/Properties/Resources.resx @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + \ No newline at end of file diff --git a/Sudoku_-_DLL/Properties/Settings.Designer.cs b/Sudoku_-_DLL/Properties/Settings.Designer.cs new file mode 100644 index 0000000..9ff9493 --- /dev/null +++ b/Sudoku_-_DLL/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.544 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SudokuWeek4.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Sudoku_-_DLL/Properties/Settings.settings b/Sudoku_-_DLL/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Sudoku_-_DLL/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Sudoku_-_DLL/Sudoku.csproj b/Sudoku_-_DLL/Sudoku.csproj new file mode 100644 index 0000000..3f06601 --- /dev/null +++ b/Sudoku_-_DLL/Sudoku.csproj @@ -0,0 +1,217 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC} + Library + Properties + SudokuWeek4 + SudokuDLL + v4.0 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + + + + + 3.5 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + bin\Debug\Sudoku.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + bin\Release\Sudoku.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + false + + + + + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + 3.0 + + + 3.0 + + + 3.0 + + + 3.0 + + + + + Designer + MSBuild:Compile + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + MSBuild:Compile + Designer + + + + + + + + + + + + + LargeCell.xaml + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + LittleCell.xaml + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + {FC98639C-8987-42D6-B20C-8BE179AB7C55} + 1 + 0 + 0 + tlbimp + False + True + + + + + \ No newline at end of file diff --git a/Sudoku_-_DLL/Sudoku.sln b/Sudoku_-_DLL/Sudoku.sln new file mode 100644 index 0000000..be91157 --- /dev/null +++ b/Sudoku_-_DLL/Sudoku.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sudoku", "Sudoku.csproj", "{C835CFCA-0A38-40C5-BEA8-3822441B27EC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|x86.ActiveCfg = Debug|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|x86.Build.0 = Debug|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|Any CPU.Build.0 = Release|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|x86.ActiveCfg = Release|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sudoku_-_DLL/ViewModels/MainViewModel.cs b/Sudoku_-_DLL/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..c2c2205 --- /dev/null +++ b/Sudoku_-_DLL/ViewModels/MainViewModel.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using SudokuWeek4.Models; + +namespace SudokuWeek4.ViewModels +{ + public class MainViewModel + { + private BoardModel _board; + private UniformGrid _gameField; + + public MainViewModel(UniformGrid gameField) + { + _board = new BoardModel(); + _gameField = gameField; + _gameField.Children.Add(GameField()); + } + + public void Reset(int boardSize) + { + _board.Reset(boardSize); + } + + public void Cheat(Boolean cheatMode) + { + _board.Cheat(cheatMode); + } + + public void ShowHint() + { + _board.ShowHint(); + } + + public void Save() + { + _board.Save(); + } + + public void Load() + { + _board.Load(); + } + + public UniformGrid GameField() + { + return _board.GameField; + } + + public void EnableDLL(Boolean state) + { + _board.SudokuDLL = state; + } + + public void SolvePuzzle(int cellsOver = 0) + { + _board.solvePuzzle(cellsOver); + } + + public void keyPressed(KeyEventArgs key) + { + _board.KeyPressed(key); + } + + public void mouseClicked(object sender, MouseEventArgs click) + { + _board.MouseClicked(sender, click); + } + } +} diff --git a/Sudoku_-_View/App.xaml b/Sudoku_-_View/App.xaml new file mode 100644 index 0000000..1093c01 --- /dev/null +++ b/Sudoku_-_View/App.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/Sudoku_-_View/App.xaml.cs b/Sudoku_-_View/App.xaml.cs new file mode 100644 index 0000000..77619ef --- /dev/null +++ b/Sudoku_-_View/App.xaml.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Windows; + +namespace SudokuWeek4 +{ + public partial class App : Application + { + } +} diff --git a/Sudoku_-_View/Libraries/SudokuDLL.dll b/Sudoku_-_View/Libraries/SudokuDLL.dll new file mode 100644 index 0000000..24bafe5 Binary files /dev/null and b/Sudoku_-_View/Libraries/SudokuDLL.dll differ diff --git a/Sudoku_-_View/Libraries/register.bat b/Sudoku_-_View/Libraries/register.bat new file mode 100644 index 0000000..f54409a --- /dev/null +++ b/Sudoku_-_View/Libraries/register.bat @@ -0,0 +1,2 @@ + +C:\Windows\System32\regsvr32 E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll diff --git a/Sudoku_-_View/Libraries/unregister.bat b/Sudoku_-_View/Libraries/unregister.bat new file mode 100644 index 0000000..74dc2c7 --- /dev/null +++ b/Sudoku_-_View/Libraries/unregister.bat @@ -0,0 +1,2 @@ + +C:\Windows\System32\regsvr32 /u E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll diff --git a/Sudoku_-_View/Properties/AssemblyInfo.cs b/Sudoku_-_View/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..aca0baf --- /dev/null +++ b/Sudoku_-_View/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle( "Sudoku" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany("SuperSmash")] +[assembly: AssemblyProduct( "Sudoku" )] +[assembly: AssemblyCopyright("Copyright © SuperSmash 2012")] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible( false )] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion( "1.0.0.0" )] +[assembly: AssemblyFileVersion( "1.0.0.0" )] diff --git a/Sudoku_-_View/Properties/Resources.Designer.cs b/Sudoku_-_View/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d56fec4 --- /dev/null +++ b/Sudoku_-_View/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.544 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SudokuWeek4.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SudokuWeek4.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Sudoku_-_View/Properties/Resources.resx b/Sudoku_-_View/Properties/Resources.resx new file mode 100644 index 0000000..04e2214 --- /dev/null +++ b/Sudoku_-_View/Properties/Resources.resx @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + \ No newline at end of file diff --git a/Sudoku_-_View/Properties/Settings.Designer.cs b/Sudoku_-_View/Properties/Settings.Designer.cs new file mode 100644 index 0000000..9ff9493 --- /dev/null +++ b/Sudoku_-_View/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.544 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SudokuWeek4.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Sudoku_-_View/Properties/Settings.settings b/Sudoku_-_View/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Sudoku_-_View/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Sudoku_-_View/Sudoku.csproj b/Sudoku_-_View/Sudoku.csproj new file mode 100644 index 0000000..f41e44a --- /dev/null +++ b/Sudoku_-_View/Sudoku.csproj @@ -0,0 +1,202 @@ + + + + Debug + AnyCPU + 9.0.21022 + 2.0 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC} + WinExe + Properties + SudokuWeek4 + Sudoku + v4.0 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + + + + + + + 3.5 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + bin\Debug\Sudoku.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + bin\Release\Sudoku.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + AllRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + true + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + true + false + + + + + + + Libraries\SudokuDLL.dll + + + + 3.5 + + + + + 3.5 + + + 3.5 + + + + + 3.0 + + + 3.0 + + + 3.0 + + + 3.0 + + + + + MSBuild:Compile + Designer + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + + + + + + + \ No newline at end of file diff --git a/Sudoku_-_View/Sudoku.sln b/Sudoku_-_View/Sudoku.sln new file mode 100644 index 0000000..be91157 --- /dev/null +++ b/Sudoku_-_View/Sudoku.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sudoku", "Sudoku.csproj", "{C835CFCA-0A38-40C5-BEA8-3822441B27EC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|x86.ActiveCfg = Debug|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Debug|x86.Build.0 = Debug|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|Any CPU.Build.0 = Release|Any CPU + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|x86.ActiveCfg = Release|x86 + {C835CFCA-0A38-40C5-BEA8-3822441B27EC}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sudoku_-_View/Views/MainWindow.xaml b/Sudoku_-_View/Views/MainWindow.xaml new file mode 100644 index 0000000..be575ab --- /dev/null +++ b/Sudoku_-_View/Views/MainWindow.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sudoku_-_View/Views/MainWindow.xaml.cs b/Sudoku_-_View/Views/MainWindow.xaml.cs new file mode 100644 index 0000000..183d603 --- /dev/null +++ b/Sudoku_-_View/Views/MainWindow.xaml.cs @@ -0,0 +1,95 @@ +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System; +using SudokuWeek4.ViewModels; +using System.Windows.Input; + +namespace SudokuWeek4 +{ + public partial class MainWindow : Window + { + private int _boardSize = 3; + private Boolean _cheatMode = false; + private Boolean _sudokuDLL = true; + private MainViewModel _mainViewModel; + + public MainWindow() + { + InitializeComponent(); + _mainViewModel = new MainViewModel(mainGrid); + Reset(_boardSize); + } + + // Reset the gameField + private void Reset(int boardSize) { + _mainViewModel.Reset(boardSize); + } + + // Save the game + private void MenuItem_Save(object sender, RoutedEventArgs e) + { + _mainViewModel.Save(); + } + + // Load the game + private void MenuItem_Load(object sender, RoutedEventArgs e) + { + _mainViewModel.Load(); + } + + // Reset the gameField + private void MenuItem_ResetBoard(object sender, RoutedEventArgs e) + { + Reset(int.Parse(((MenuItem)sender).Tag.ToString())); + } + + // Get a hint + private void MenuItem_Hint(object sender, RoutedEventArgs e) + { + _mainViewModel.ShowHint(); + } + + // Enable the sudoku DLL + private void MenuItem_EnableDLL(object sender, RoutedEventArgs e) + { + _mainViewModel.EnableDLL(_sudokuDLL =! _sudokuDLL); + } + + // Solve the sudoku puzzle + private void MenuItem_Solve(object sender, RoutedEventArgs e) + { + _mainViewModel.SolvePuzzle(); + } + + // Solve the sudoku puzzle partially + private void MenuItem_SolvePartially(object sender, RoutedEventArgs e) + { + _mainViewModel.SolvePuzzle(2); + } + + // Cheat + private void MenuItem_CheatMode(object sender, RoutedEventArgs e) + { + _mainViewModel.Cheat(_cheatMode =! _cheatMode); + } + + // Exit the application + private void MenuItem_Quit(object sender, RoutedEventArgs e) + { + Application.Current.Shutdown(1); + } + + // This method will check what to do if a key is pressed + private void mainGrid_PreviewKeyDown(object sender, KeyEventArgs key) + { + _mainViewModel.keyPressed(key); + } + + private void Window_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs click) + { + _mainViewModel.mouseClicked(sender, click); + } + } +} \ No newline at end of file diff --git a/Sudoku_-_View/app.config b/Sudoku_-_View/app.config new file mode 100644 index 0000000..e365603 --- /dev/null +++ b/Sudoku_-_View/app.config @@ -0,0 +1,3 @@ + + +