forked from PKRoma/LinqSudokuSolver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Page.xaml.cs
237 lines (224 loc) · 9.41 KB
/
Page.xaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
namespace SilverlightSudokuHelper
{
public partial class Page : Canvas
{
private enum SoundEffect { New, Move, Conflict, Complete };
private const double FadeSecondsNormal = 0.5;
private const double FadeSecondsLoading = 3;
private const string BoardBlank =
" " +
" " +
" " +
" " +
" " +
" " +
" " +
" " +
" ";
private const string BoardWikipediaSample =
"53 7 " +
"6 195 " +
" 98 6 " +
"8 6 3" +
"4 8 3 1" +
"7 2 6" +
" 6 28 " +
" 419 5" +
" 8 79";
private const string BoardSudopediaSample =
"7 1 682 " +
" 3 " +
" 8 9 4 " +
" 79 " +
" 53 1 " +
"1 92 6 " +
" 93 " +
" 5 2" +
" 4 7 ";
private const string BoardAlmostFinished =
"123456789" +
"456789123" +
"789123456" +
"231564897" +
"5648 7231" +
"897231564" +
"312645978" +
"645978312" +
"978312645";
// _primaryBoardDisplay renders the current board
private BoardDisplay _primaryBoardDisplay;
// _fadingBoardDisplay renders the previous board and fades away when changes are made
private BoardDisplay _fadingBoardDisplay;
private double _defaultVolume;
private Content BrowserHost;
public Page()
{
InitializeComponent();
}
public void Page_Loaded(object o, EventArgs e)
{
// Initialize variables
_defaultVolume = mediaElement.Volume;
BrowserHost = App.Current.Host.Content;
// Initialize UI
_primaryBoardDisplay = new BoardDisplay();
Children.Add(_primaryBoardDisplay);
_fadingBoardDisplay = new BoardDisplay();
Children.Add(_fadingBoardDisplay);
// Initialize handlers
KeyUp += new KeyEventHandler(HandleKeyUp);
MouseLeftButtonDown += new MouseButtonEventHandler(HandleMouseLeftButtonDown);
BrowserHost.Resized += new EventHandler(HandleResize);
// Create the starting board, play the "new" sound, and fade it in
_primaryBoardDisplay.Board = Board.FromString(BoardWikipediaSample);
PlaySoundEffect(SoundEffect.New);
_fadingBoardDisplay.Fade(FadeSecondsLoading);
}
private void HandleKeyUp(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Escape: // Escape
_primaryBoardDisplay.Solve();
break;
case Key.Left: // Left arrow
case Key.Up: // Up arrow
case Key.Right: // Right arrow
case Key.Down: // Down arrow
// Move the marker
var markerPosition = _primaryBoardDisplay.MarkerPosition;
switch (e.Key)
{
case Key.Left: markerPosition.X--; break;
case Key.Up: markerPosition.Y--; break;
case Key.Right: markerPosition.X++; break;
case Key.Down: markerPosition.Y++; break;
}
_primaryBoardDisplay.MarkerPosition = markerPosition;
_fadingBoardDisplay.MarkerPosition = markerPosition;
break;
case Key.Delete: // Delete
// Clear the cell's value
PrepareFade();
if (_primaryBoardDisplay.ChangeSelectedValue(Digit.Unknown, Digit.Kind.Normal))
{
// Play the appropriate sound and fade it
PlaySoundEffect(SoundEffect.Move);
_fadingBoardDisplay.Fade(FadeSecondsNormal);
}
break;
case Key.D1: // 1
case Key.D2: // 2
case Key.D3: // 3
case Key.D4: // 4
case Key.D5: // 5
case Key.D6: // 6
case Key.D7: // 7
case Key.D8: // 8
case Key.D9: // 9
// Set the cell's value
PrepareFade();
if (_primaryBoardDisplay.ChangeSelectedValue(e.Key - Key.D0, ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift ? Digit.Kind.Given : ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control ? Digit.Kind.Guess : Digit.Kind.Normal))))
{
// Normal move; play the appropriate sound and fade it
PlaySoundEffect(_primaryBoardDisplay.Board.Complete ? SoundEffect.Complete : SoundEffect.Move);
_fadingBoardDisplay.Fade(FadeSecondsNormal);
}
else
{
// Invalid move, play the conflict sound
PlaySoundEffect(SoundEffect.Conflict);
}
break;
case Key.B: // B
case Key.F: // F
case Key.S: // S
case Key.W: // W
// Switch to the specified board
PrepareFade();
var boardString = "";
switch (e.Key)
{
case Key.B: boardString = BoardBlank; break;
case Key.F: boardString = BoardAlmostFinished; break;
case Key.S: boardString = BoardSudopediaSample; break;
case Key.W: boardString = BoardWikipediaSample; break;
}
_primaryBoardDisplay.Board = Board.FromString(boardString);
PlaySoundEffect(SoundEffect.New);
_fadingBoardDisplay.Fade(FadeSecondsNormal);
break;
case Key.C: // C
// Toggle the candidate display
PrepareFade();
_primaryBoardDisplay.CandidatesVisible = !_primaryBoardDisplay.CandidatesVisible;
_fadingBoardDisplay.Fade(FadeSecondsNormal);
break;
}
}
private void HandleMouseLeftButtonDown(object sender, MouseEventArgs e)
{
// Set the marker position to the cell under the specified location
var position = e.GetPosition(null);
var markerPosition = new Point { X = (position.X / Width) * Board.Size, Y = (position.Y / Height) * Board.Size };
_primaryBoardDisplay.MarkerPosition = markerPosition;
_fadingBoardDisplay.MarkerPosition = markerPosition;
}
// Prepare to fade by syncing _fadingBoardDisplay with _primaryBoardDisplay
private void PrepareFade()
{
_fadingBoardDisplay.Board = _primaryBoardDisplay.Board;
_fadingBoardDisplay.CandidatesVisible = _primaryBoardDisplay.CandidatesVisible;
}
private void PlaySoundEffect(SoundEffect soundEffect)
{
// Prepare to play the sound
mediaElement.Volume = _defaultVolume;
var soundFile = "";
switch (soundEffect)
{
case SoundEffect.New:
soundFile = "WindowsLogonSound.wma";
break;
case SoundEffect.Move:
soundFile = "WindowsNavigationStart.wma";
mediaElement.Volume *= 0.5; // Volume for this sound is lowered some to keep it the same as the others
break;
case SoundEffect.Conflict:
soundFile = "WindowsCriticalStop.wma";
break;
case SoundEffect.Complete:
soundFile = "Tada.wma";
mediaElement.Volume = 1.0; // Success sound is full volume to celebrate
break;
}
// Set the source and play the sound
mediaElement.Source = new Uri(HtmlPage.Document.DocumentUri, soundFile);
mediaElement.Play();
}
private void HandleResize(object sender, EventArgs e)
{
// If this is a valid resize
if ((0 < BrowserHost.ActualWidth) && (0 < BrowserHost.ActualHeight))
{
// Size the root element to fill the host
var root = _primaryBoardDisplay.Parent as Canvas;
root.Width = BrowserHost.ActualWidth;
root.Height = BrowserHost.ActualHeight;
// Size each board to match
foreach (var boardDisplay in new BoardDisplay[] { _primaryBoardDisplay, _fadingBoardDisplay })
{
boardDisplay.Width = BrowserHost.ActualWidth;
boardDisplay.Height = BrowserHost.ActualHeight;
boardDisplay.Layout();
}
}
}
}
}