-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTypes.cs
More file actions
executable file
·299 lines (283 loc) · 10.8 KB
/
Types.cs
File metadata and controls
executable file
·299 lines (283 loc) · 10.8 KB
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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#region Copyright (c) 2010, Pavel Poltavets
/*
{*********************************************************}
{ }
{ Sapper .NET application }
{ }
{ Copyright (c) 2010, Pavel Poltavets }
{ poltavets-pavel@mail.ru }
{ }
{ ALL RIGHTS RESERVED }
{ }
{*********************************************************}
*/
#endregion Copyright (c) 2010, Pavel Poltavets
using System;
using System.Collections.ObjectModel;
namespace Sapper.Types {
public class FieldMessageEventArgs : EventArgs {
private bool hasCellSelected;
private int countLabels;
private FieldMessage messageField;
public FieldMessageEventArgs(FieldMessage fieldMessage) {
this.messageField = fieldMessage;
}
public FieldMessageEventArgs(FieldMessage fieldMessage, int labelsCount, bool hasSelectedCell)
: this(fieldMessage) {
this.countLabels = labelsCount;
this.hasCellSelected = hasSelectedCell;
}
public bool HasSelectedCell { get { return hasCellSelected; } }
public int LabelsCount { get { return countLabels; } }
public FieldMessage Message { get { return messageField; } }
}
public class FieldSettings : ICloneable {
[FlagsAttribute]
private enum FieldOptions {
None = 0,
UseEffect3D = 0x1,
HasCenter = 0x2,
Unused01 = 0x4,
Unused02 = 0x8,
Unused03 = 0x10
}
public static readonly float MinesMaxPercent = 0.8f;
public static readonly int MaximumColumnCount = 50;
public static readonly int MaximumRowCount = MaximumColumnCount;
public static readonly int MaximumMineCount = (int)(MaximumColumnCount * MaximumRowCount * MinesMaxPercent);
public static readonly int MaximumErrorCount = MaximumMineCount - 1;
public static readonly int MinimumMineCount = 1;
public static readonly int MinimumColumnCount = 3;
public static readonly int MinimumRowCount = MinimumColumnCount;
public static readonly int DefaultMineCount = 8;
public static readonly int DefaultColumnCount = 9;
public static readonly int DefaultHeight = 16 * MinimumRowCount;
public static readonly int DefaultRowCount = DefaultColumnCount;
public static readonly int DefaultWidth = 16 * MinimumColumnCount;
private int countMines = DefaultMineCount;
private int countError;
private int countColumns = DefaultColumnCount;
private FieldOptions options;
private int countRows = DefaultRowCount;
private bool GetOption(FieldOptions option) {
return (options & option) != 0;
}
private void SetOption(FieldOptions option, bool value) {
options = value ? (options | option) : (options & ~option);
}
public FieldSettings() {
options = FieldOptions.HasCenter | FieldOptions.UseEffect3D;
}
public virtual Object Clone() {
FieldSettings fieldSettings = Activator.CreateInstance(this.GetType()) as FieldSettings;
fieldSettings.countColumns = countColumns;
fieldSettings.countError = countError;
fieldSettings.countMines = countMines;
fieldSettings.countRows = countRows;
fieldSettings.options = options;
return fieldSettings;
}
public int ColumnCount {
get { return countColumns; }
set {
if(value < MinimumColumnCount)
value = MinimumColumnCount;
countColumns = value;
}
}
public int ErrorCount {
get { return countError; }
set {
if(value > 0 && value < MineCount) {
countError = value;
}
}
}
public bool HasCenter {
get { return GetOption(FieldOptions.HasCenter); }
set { SetOption(FieldOptions.HasCenter, value); }
}
public int MineCount {
get { return countMines; }
set {
int count = (int)(countColumns * countRows * MinesMaxPercent);
if(count < value)
value = count;
countMines = value;
}
}
public int RowCount {
get { return countRows; }
set {
if(value < MinimumRowCount)
value = MinimumRowCount;
countRows = value;
}
}
public bool UseEffect3D {
get { return GetOption(FieldOptions.UseEffect3D); }
set { SetOption(FieldOptions.UseEffect3D, value); }
}
}
public class VisualFieldSettings<TBox> : FieldSettings where TBox : struct {
private TBox boxBounds;
protected virtual TBox CorrectBoundsBox(TBox box) {
return box;
}
public TBox BoundsBox { get { return boxBounds; } set { boxBounds = CorrectBoundsBox(value); } }
public override Object Clone() {
VisualFieldSettings<TBox> fieldSettings = base.Clone() as VisualFieldSettings<TBox>;
fieldSettings.boxBounds = boxBounds;
return fieldSettings;
}
}
public enum CellBackfillType : int { Closed, Opened, Detonated }
public enum FieldMessage : int { Initialized, SelectCell, ChangeLabelsCount, MinesDetonated, RegenerationNeeded, AllMinesDetonated, AllMinesLabeled, AllEmptyCellsOpened }
public interface IPainter<TVertex, TBox> {
void BeginPaint(TBox box);
void DrawBorder3D(TVertex[] vertices);
void DrawInteger(TVertex centerPosition, TBox box, int value);
void DrawLabel(TVertex centerPosition, TBox box);
void DrawMine(TVertex centerPosition, TBox box, bool isRealMine);
void DrawPolygon(TVertex[] vertices);
void DrawUndefined(TVertex centerPosition, TBox box);
void EndPaint();
void FillPolygon(TVertex[] vertices, CellBackfillType fillType);
bool IsValid { get; }
}
public interface ISelector<TVertex, TBox> {
void AddCell(ICell cell, TVertex[] cellContour);
void Initialize(TBox box);
ICell GetCell(TVertex position);
}
public interface IDraw<TVertex, TBox> {
void Draw(IPainter<TVertex, TBox> painter, ISelector<TVertex, TBox> selector);
}
public interface IField {
event EventHandler<FieldMessageEventArgs> Message;
void ClearMessage();
void Initialize(FieldSettings settings);
void NextStateCell(ICell cell);
void OpenCell(ICell cell, bool isWithAround);
void SelectCell(ICell cell, bool isWithAround);
int MineCount { get; }
int CellCount { get; }
int LabelCount { get; }
}
public interface IVisualField<TVertex, TBox> : IField, IDraw<TVertex, TBox> {
void ChangeBox(TBox box);
}
public interface ICell {
void AddAroundCell(ICell cell);
bool ChangeState();
bool MarkLabel();
CellOperationOpening Open(bool isWithAround);
int SetNextState();
void ShowMine();
bool CanOpened { get; }
CellsCollection<ICell> CellsAround { get; }
bool Closed { get; set; }
bool HasMine { get; set; }
bool HasVisited { get; set; }
bool IsLabelState { get; }
bool IsMineDetonated { get; set; }
bool IsSelected { get; set; }
bool IsSelectedAround { get; set; }
int MinesNumber { get; }
}
public interface IVisualCell<TVertex, TBox> : ICell, IDraw<TVertex, TBox> {
void Initialize(CellOperationInitialize<TVertex, TBox> cellInit);
}
public class CellsCollection<TCell> : Collection<TCell> where TCell : ICell {
}
public struct CellOperationOpening : IEquatable<CellOperationOpening> {
private int countMines;
private int countOpened;
public CellOperationOpening(int mines, int opened) {
countMines = mines;
countOpened = opened;
}
public void Add(CellOperationOpening opening) {
countMines += opening.MineCount;
countOpened += opening.OpenedCount;
}
public override int GetHashCode() {
return countMines ^ countOpened;
}
public override bool Equals(object obj) {
if(!(obj is CellOperationOpening))
return false;
return Equals((CellOperationOpening)obj);
}
public bool Equals(CellOperationOpening other) {
if(countMines != other.countMines)
return false;
return countOpened == other.countOpened;
}
public static bool operator ==(CellOperationOpening opening1, CellOperationOpening opening2) {
return opening1.Equals(opening2);
}
public static bool operator !=(CellOperationOpening opening1, CellOperationOpening opening2) {
return !opening1.Equals(opening2);
}
public static CellOperationOpening operator +(CellOperationOpening opening1, CellOperationOpening opening2) {
CellOperationOpening opening = opening1;
opening.Add(opening2);
return opening;
}
public int MineCount { get { return countMines; } set { countMines = value; } }
public bool HasMines { get { return countMines > 0; } }
public int OpenedCount { get { return countOpened; } set { countOpened = value; } }
}
public struct CellOperationInitialize<TVertex, TBox> : IEquatable<CellOperationInitialize<TVertex, TBox>> {
private double angleStart;
private double angleSweep;
private TBox boxBig;
private TBox boxExtents;
private TBox boxSmall;
private bool notUseEffect3D;
public TBox BigBox { get { return boxBig; } set { boxBig = value; } }
public TBox ExtentsBox { get { return boxExtents; } set { boxExtents = value; } }
public TBox SmallBox { get { return boxSmall; } set { boxSmall = value; } }
public double StartAngle { get { return angleStart; } set { angleStart = value; } }
public double SweepAngle { get { return angleSweep; } set { angleSweep = value; } }
public bool UseEffect3D { get { return !notUseEffect3D; } set { notUseEffect3D = !value; } }
public override int GetHashCode() {
return 0;
}
public override bool Equals(object obj) {
if(!(obj is CellOperationInitialize<TVertex, TBox>))
return false;
return Equals((CellOperationInitialize<TVertex, TBox>)obj);
}
public bool Equals(CellOperationInitialize<TVertex, TBox> other) {
if(!boxBig.Equals(other.boxBig) || (notUseEffect3D != other.notUseEffect3D))
return false;
return (boxSmall.Equals(other.boxSmall)) && (boxExtents.Equals(other.boxExtents)) && (angleStart == other.angleStart) && (angleSweep == other.angleSweep);
}
public static bool operator ==(CellOperationInitialize<TVertex, TBox> cellOperation1, CellOperationInitialize<TVertex, TBox> cellOperation2) {
return cellOperation1.Equals(cellOperation2);
}
public static bool operator !=(CellOperationInitialize<TVertex, TBox> cellOperation1, CellOperationInitialize<TVertex, TBox> cellOperation2) {
return !cellOperation1.Equals(cellOperation2);
}
public CellOperationInitialize(TBox big, TBox small, TBox extents, double start, double sweep, bool useEffect3D) {
angleStart = start;
angleSweep = sweep;
boxBig = big;
boxSmall = small;
boxExtents = extents;
notUseEffect3D = !useEffect3D;
}
public CellOperationInitialize(bool useEffect3D)
: this() {
angleStart = 0;
angleSweep = 360;
notUseEffect3D = !useEffect3D;
}
public CellOperationInitialize(TBox box)
: this(true) {
boxBig = boxSmall = boxExtents = box;
}
}
}