Initial commit

This commit is contained in:
NightBits 2018-12-19 20:11:50 +01:00
parent 0a3c422be8
commit d6bcf95595
69 changed files with 4395 additions and 0 deletions

8
Complete/App.xaml Normal file
View File

@ -0,0 +1,8 @@
<Application x:Class="SudokuWeek4.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Views\MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

13
Complete/App.xaml.cs Normal file
View File

@ -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
{
}
}

Binary file not shown.

View File

@ -0,0 +1,2 @@
C:\Windows\System32\regsvr32 E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll

View File

@ -0,0 +1,2 @@
C:\Windows\System32\regsvr32 /u E:\Programmering\C#\Sudoku\Complete\Libraries\Sudoku.dll

View File

@ -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<IntegerPoint, int> _cheatDictionary = new Dictionary<IntegerPoint, int>();
// 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<IntegerPoint> optionPoints)
{
try
{
Dictionary<int, int> dictionaryCount = new Dictionary<int, int>();
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<IntegerPoint> GetPointsInParentBigCell(int x, int y)
{
int x0 = x - x % GameFieldCount;
int y0 = y - y % GameFieldCount;
List<IntegerPoint> cellPoints = new List<IntegerPoint>();
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<IntegerPoint> GetPointsInRow(int y)
{
List<IntegerPoint> cellPoints = new List<IntegerPoint>();
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<IntegerPoint> GetPointsInColumn(int x)
{
List<IntegerPoint> cellPoints = new List<IntegerPoint>();
for (int i = 0; i < GameFieldSize; i++)
{
cellPoints.Add(new IntegerPoint(x, i));
}
return cellPoints;
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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<int>) || targetType != typeof(Brush) || !(parameter is int))
throw new InvalidCastException();
HashSet<int> set = (HashSet<int>)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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,6 @@
<UserControl x:Class="SudokuWeek4.Models.LargeCell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Padding="1,1,0,0">
<UniformGrid Name="bigCellGrid" />
</UserControl>

View File

@ -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]; }
}
}
}

View File

@ -0,0 +1,11 @@
<UserControl x:Class="SudokuWeek4.Models.LittleCell"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Sudoku="clr-namespace:SudokuWeek4">
<Border Name="smallBorder" BorderThickness="4">
<Grid>
<Grid Name="inputGrid" />
<UniformGrid Name="optionsGrid" />
</Grid>
</Border>
</UserControl>

View File

@ -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<int> _options = new HashSet<int>();
// Define a hashSet of the possible solutions
private readonly HashSet<int> _solutions = new HashSet<int>();
// 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<int> 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");
}
}
}
}
}

View File

@ -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<string, DrawingBrush> cachedBrushes = new Dictionary<string, DrawingBrush>();
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;
}
}
}

View File

@ -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
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> 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" )]

View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SudokuWeek4.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</root>

26
Complete/Properties/Settings.Designer.cs generated Normal file
View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

238
Complete/Sudoku.csproj Normal file
View File

@ -0,0 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>