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

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