1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Reflection ;
4
+ using System . Threading ;
3
5
4
6
class Maze {
7
+ private const string WallWithLeftSideEmpty = " " ;
8
+
9
+ private delegate void Go ( ) ;
10
+
11
+ private const string WallWithLeftSideEmptyAndCursor = " ■ " ;
12
+
13
+ private const string WallWithLeftSideFull = "| " ;
14
+
15
+ private const string WallWithLeftSideFullAndCursor = "| ■ " ;
5
16
6
- private const string WallWithLeftSideEmpty = "= " ;
7
- private const string WallWithLeftSideFull = "| " ;
8
17
private const string FloorWithHole = "+ " ;
18
+
9
19
private const string FloorWithoutHole = "+---" ;
20
+
10
21
private const string WallEnd = "|\n " ;
11
- private const string WallEndWithExit = "=\n " ;
22
+
23
+ private const string WallEndWithExit = " \n " ;
24
+
12
25
private const string FloorCorner = "+\n " ;
26
+
13
27
private static Cell [ ] [ ] _maze ;
14
28
15
- static void Main ( string [ ] args ) {
29
+ private static ( int , int ) _cursor ;
30
+
31
+
32
+ static void Main ( string [ ] args ) {
16
33
Console . ForegroundColor = ConsoleColor . Green ;
17
34
Console . CursorVisible = false ;
18
35
Console . Title = "Maze" ;
@@ -68,39 +85,174 @@ private static void GenerateMaze(bool showAnimation) {
68
85
Console . WriteLine ( "Generating maze " + width + "x" + height ) ;
69
86
GenerateEmptyMaze ( width , height ) ;
70
87
71
- MazeGeneratingAlgorithm ( ) ;
88
+ MazeGeneratingAlgorithm ( showAnimation ) ;
72
89
73
- PrintMaze ( ) ;
90
+ PrintMaze ( false ) ;
91
+ Console . WriteLine ( "Press any key to Quit" ) ;
74
92
Console . ReadKey ( ) ;
75
93
}
76
94
77
- private static void MazeGeneratingAlgorithm ( ) {
95
+ private static void MazeGeneratingAlgorithm ( bool showAnimation ) {
96
+ var random = new Random ( ) ;
78
97
// Starting point at (0, 0)
79
98
_maze [ 0 ] [ 0 ] . Left = true ;
80
- var cursor = ( 0 , 0 ) ;
99
+
100
+ // Pick random place (why not?)
101
+ _cursor = ( random . Next ( 0 , _maze . Length ) , random . Next ( 0 , _maze [ 0 ] . Length ) ) ;
102
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Visited = true ;
103
+
104
+ // Add first item to stack
81
105
var logStack = new Stack < ( int , int ) > ( ) ;
106
+ logStack . Push ( _cursor ) ;
107
+
108
+ // Delegate to store method. I just wanted to try it...
109
+ Go go = null ;
110
+
82
111
// Depth-first search algorithm
83
112
84
113
do {
85
- _maze [ cursor . Item1 ] [ cursor . Item2 ] . Visited = true ;
86
- logStack . Push ( cursor ) ;
87
-
88
- if ( IsDeadEnd ( cursor ) ) {
114
+ if ( IsDeadEnd ( _cursor ) ) {
115
+ if ( logStack . Count <= 1 ) break ;
89
116
logStack . Pop ( ) ;
90
- if ( logStack . Count == 0 ) break ;
117
+ _cursor = logStack . Peek ( ) ;
118
+ if ( showAnimation ) {
119
+ Thread . Sleep ( 100 ) ;
120
+ PrintMaze ( true ) ;
121
+ }
122
+ continue ;
91
123
}
92
124
125
+ if ( IsBottomCellNotVisited ( _cursor ) )
126
+ go += GoBottom ;
127
+
128
+ if ( IsTopCellNotVisited ( _cursor ) )
129
+ go += GoTop ;
130
+
131
+ if ( IsLeftCellNotVisited ( _cursor ) )
132
+ go += GoLeft ;
133
+
134
+ if ( IsRightCellNotVisited ( _cursor ) )
135
+ go += GoRight ;
136
+
137
+ go = ( Go ) go . GetInvocationList ( ) [ random . Next ( 0 , go . GetInvocationList ( ) . Length ) ] ;
138
+ go ( ) ;
139
+ go = null ;
140
+ logStack . Push ( _cursor ) ;
141
+ if ( showAnimation ) {
142
+ Thread . Sleep ( 300 ) ;
143
+ PrintMaze ( true ) ;
144
+ }
93
145
146
+ } while ( logStack . Count > 0 ) ;
94
147
95
- } while ( cursor . Equals ( ( 0 , 0 ) ) ) ;
148
+ // Exit at bottom right corner
149
+ _maze [ _maze . Length - 1 ] [ _maze [ 0 ] . Length - 1 ] . Right = true ;
150
+ }
151
+ private static void GoBottom ( ) {
152
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Bottom = true ;
153
+ _cursor . Item1 += 1 ;
154
+ _cursor . Item2 += 0 ;
155
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Visited = true ;
156
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Top = true ;
157
+ }
158
+
159
+ private static void GoTop ( ) {
160
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Top = true ;
161
+ _cursor . Item1 += - 1 ;
162
+ _cursor . Item2 += 0 ;
163
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Visited = true ;
164
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Bottom = true ;
165
+ }
96
166
167
+ private static void GoLeft ( ) {
168
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Left = true ;
169
+ _cursor . Item1 += 0 ;
170
+ _cursor . Item2 += - 1 ;
171
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Visited = true ;
172
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Right = true ;
173
+ }
97
174
98
- // Exit at bottom right corner
99
- _maze [ _maze . Length - 1 ] [ _maze [ 0 ] . Length - 1 ] . Right = true ;
175
+ private static void GoRight ( ) {
176
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Right = true ;
177
+ _cursor . Item1 += 0 ;
178
+ _cursor . Item2 += 1 ;
179
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Visited = true ;
180
+ _maze [ _cursor . Item1 ] [ _cursor . Item2 ] . Left = true ;
100
181
}
101
182
102
- private static bool IsDeadEnd ( ( int , int ) cursor ) {
183
+ private static void PrintMaze ( bool printCursor ) {
184
+ Console . Clear ( ) ;
185
+ PrintTitle ( ) ;
186
+
187
+ //+---+
188
+ //| | 1x1 block
189
+ //+---+
190
+
191
+ var board = "" ;
192
+ // Add first line
193
+ board = AddOneLine ( board ) ;
194
+
195
+ // Crate one maze in one string
196
+ for ( var row = 0 ; row < _maze . Length ; row ++ ) {
197
+ for ( var k = 1 ; k <= 2 ; k ++ ) {
198
+ for ( var column = 0 ; column < _maze [ row ] . Length ; column ++ ) {
199
+ board = AddMazeFragment ( printCursor , board , row , k , column ) ;
200
+ }
201
+ board = AddEndLines ( board , k , row ) ;
202
+ }
203
+ }
204
+
205
+ // Print maze
206
+ Console . WriteLine ( board ) ;
207
+ }
208
+
209
+ private static string AddMazeFragment ( bool printCursor , string board , int row , int k , int column ) {
210
+ if ( ShouldPrintVertical ( k ) ) {
211
+ board = AddWall ( printCursor , board , row , column ) ;
212
+ } else {
213
+ board = AddFloor ( board , row , column ) ;
214
+ }
215
+
216
+ return board ;
217
+ }
218
+
219
+ private static string AddWall ( bool printCursor , string board , int row , int column ) {
220
+ if ( ShouldPrintWall ( row , column ) )
221
+ board = AddWallWithFullSideAndCursor ( printCursor , board , row , column ) ;
222
+ else {
223
+ board = AddWallWithFullSide ( printCursor , board , row , column ) ;
224
+ }
103
225
226
+ return board ;
227
+ }
228
+
229
+ private static string AddFloor ( string board , int row , int column ) {
230
+ if ( ShouldPrintFloor ( row , column ) )
231
+ board += FloorWithoutHole ;
232
+ else {
233
+ board += FloorWithHole ;
234
+ }
235
+
236
+ return board ;
237
+ }
238
+
239
+ private static string AddWallWithFullSide ( bool printCursor , string board , int row , int column ) {
240
+ if ( printCursor && CursorIsAtPosition ( row , column ) )
241
+ board += WallWithLeftSideEmptyAndCursor ;
242
+ else
243
+ board += WallWithLeftSideEmpty ;
244
+ return board ;
245
+ }
246
+
247
+ private static string AddWallWithFullSideAndCursor ( bool printCursor , string board , int row , int column ) {
248
+ if ( printCursor && CursorIsAtPosition ( row , column ) )
249
+ board += WallWithLeftSideFullAndCursor ;
250
+ else
251
+ board += WallWithLeftSideFull ;
252
+ return board ;
253
+ }
254
+
255
+ private static bool IsDeadEnd ( ( int , int ) cursor ) {
104
256
// Cell that has no unvisited neighbors being considered a dead-end ~ Wikipedia
105
257
106
258
// cursor.Item1 - Row (Y)
@@ -117,7 +269,7 @@ private static bool IsDeadEnd((int, int) cursor) {
117
269
}
118
270
119
271
// Left
120
- if ( IsLeftCellNotVisisted ( cursor ) ) {
272
+ if ( IsLeftCellNotVisited ( cursor ) ) {
121
273
return false ;
122
274
}
123
275
@@ -133,7 +285,7 @@ private static bool IsRightCellNotVisited((int, int) cursor) {
133
285
return IsCellOnRight ( cursor ) && ! _maze [ cursor . Item1 ] [ cursor . Item2 + 1 ] . Visited ;
134
286
}
135
287
136
- private static bool IsLeftCellNotVisisted ( ( int , int ) cursor ) {
288
+ private static bool IsLeftCellNotVisited ( ( int , int ) cursor ) {
137
289
return IsCellOnLeft ( cursor ) && ! _maze [ cursor . Item1 ] [ cursor . Item2 - 1 ] . Visited ;
138
290
}
139
291
@@ -146,19 +298,19 @@ private static bool IsTopCellNotVisited((int, int) cursor) {
146
298
}
147
299
148
300
private static bool IsCellOnRight ( ( int , int ) cursor ) {
149
- return cursor . Item2 + 1 <= _maze [ 0 ] . Length ;
301
+ return cursor . Item2 + 1 < _maze [ 0 ] . Length ;
150
302
}
151
303
152
304
private static bool IsCellOnLeft ( ( int , int ) cursor ) {
153
- return cursor . Item2 - 1 > 0 ;
305
+ return cursor . Item2 - 1 >= 0 ;
154
306
}
155
307
156
308
private static bool IsCellBelowCursor ( ( int , int ) cursor ) {
157
- return cursor . Item1 + 1 <= _maze . Length ;
309
+ return cursor . Item1 + 1 < _maze . Length ;
158
310
}
159
311
160
312
private static bool IsCellAboveCursor ( ( int , int ) cursor ) {
161
- return cursor . Item1 - 1 > 0 ;
313
+ return cursor . Item1 - 1 >= 0 ;
162
314
}
163
315
164
316
private static bool CursorIsCorrect ( ( int , int ) cursor ) {
@@ -168,41 +320,8 @@ private static bool CursorIsCorrect((int, int) cursor) {
168
320
cursor . Item2 + 1 < _maze [ 0 ] . Length ;
169
321
}
170
322
171
- private static void PrintMaze ( ) {
172
- Console . Clear ( ) ;
173
- PrintTitle ( ) ;
174
-
175
- //+---+
176
- //| | 1x1 block
177
- //+---+
178
-
179
- var board = "" ;
180
- // Add first line
181
- board = AddOneLine ( board ) ;
182
-
183
- // Add all maze
184
- for ( var row = 0 ; row < _maze . Length ; row ++ ) {
185
- for ( var k = 1 ; k <= 2 ; k ++ ) {
186
- for ( var column = 0 ; column < _maze [ row ] . Length ; column ++ ) {
187
- if ( ShouldPrintVertical ( k ) ) {
188
- if ( ShouldPrintWall ( row , column ) )
189
- board += WallWithLeftSideFull ;
190
- else {
191
- board += WallWithLeftSideEmpty ;
192
- }
193
- } else {
194
- if ( ShouldPrintFloor ( row , column ) )
195
- board += FloorWithoutHole ;
196
- else {
197
- board += FloorWithHole ;
198
- }
199
- }
200
- }
201
- board = AddEndLines ( board , k , row ) ;
202
- }
203
- }
204
- // Print maze
205
- Console . WriteLine ( board ) ;
323
+ private static bool CursorIsAtPosition ( int row , int column ) {
324
+ return _cursor . Item1 == row && _cursor . Item2 == column ;
206
325
}
207
326
208
327
private static bool ShouldPrintFloor ( int row , int column ) {
@@ -215,7 +334,7 @@ private static bool ShouldPrintWall(int row, int column) {
215
334
216
335
private static string AddEndLines ( string board , int k , int row ) {
217
336
if ( ShouldPrintVertical ( k ) ) {
218
- if ( _maze [ row ] [ _maze . Length - 1 ] . Right ) {
337
+ if ( _maze [ row ] [ _maze [ 0 ] . Length - 1 ] . Right ) {
219
338
board += WallEndWithExit ;
220
339
} else {
221
340
board += WallEnd ;
@@ -253,7 +372,7 @@ private static void GenerateEmptyMaze(int width, int height) {
253
372
private static int GetWidthFromPlayer ( ) {
254
373
int width ;
255
374
Console . Write ( "\b Enter width: " ) ;
256
- while ( ! int . TryParse ( Console . ReadLine ( ) , out width ) || width < 2 || width > 100 ) {
375
+ while ( ! int . TryParse ( Console . ReadLine ( ) , out width ) || width < 1 || width > 100 ) {
257
376
Console . WriteLine ( "Wrong value" ) ;
258
377
Console . Write ( "\b Enter width: " ) ;
259
378
}
@@ -264,7 +383,7 @@ private static int GetWidthFromPlayer() {
264
383
private static int GetHeightFromPlayer ( ) {
265
384
int height ;
266
385
Console . Write ( "\b Enter height: " ) ;
267
- while ( ! int . TryParse ( Console . ReadLine ( ) , out height ) || height < 2 || height > 100 ) {
386
+ while ( ! int . TryParse ( Console . ReadLine ( ) , out height ) || height < 1 || height > 100 ) {
268
387
Console . WriteLine ( "Wrong value" ) ;
269
388
Console . Write ( "\b Enter height: " ) ;
270
389
}
0 commit comments