質問編集履歴

1

一部ソースの追加

2018/09/28 14:59

投稿

ptpt
ptpt

スコア22

test CHANGED
File without changes
test CHANGED
@@ -22,12 +22,560 @@
22
22
 
23
23
  ```c#
24
24
 
25
+ using System.Collections;
26
+
27
+ using System.Collections.Generic;
28
+
25
- 長すぎてここには載せられない
29
+ using UnityEngine;
30
+
31
+
32
+
33
+ public class CellScript : MonoBehaviour {
34
+
35
+
36
+
37
+ public GameObject wallL;
38
+
39
+ public GameObject wallR;
40
+
41
+ public GameObject wallU;
42
+
43
+ public GameObject wallD;
44
+
45
+ }
46
+
47
+
26
48
 
27
49
  ```
28
50
 
29
51
 
30
52
 
53
+ ```c#
54
+
55
+
56
+
57
+ using System.Collections;
58
+
59
+ using System.Collections.Generic;
60
+
61
+ using UnityEngine;
62
+
63
+
64
+
65
+ public class MazeGenerator : MonoBehaviour {
66
+
67
+
68
+
69
+
70
+
71
+ private void Start()
72
+
73
+ {
74
+
75
+ GenerateMaze(mazeRows, mazeColumns);
76
+
77
+ }
78
+
79
+
80
+
81
+ private void GenerateMaze(int rows, int columns)
82
+
83
+ {
84
+
85
+ if (mazeParent != null) DeleteMaze();
86
+
87
+
88
+
89
+ mazeRows = rows;
90
+
91
+ mazeColumns = columns;
92
+
93
+ CreateLayout();
94
+
95
+ }
96
+
97
+
98
+
99
+ // Creates the grid of cells.
100
+
101
+ public void CreateLayout()
102
+
103
+ {
104
+
105
+ InitValues();
106
+
107
+
108
+
109
+ // Set starting point, set spawn point to start.
110
+
111
+ Vector2 startPos = new Vector2(-(cellSize * (mazeColumns / 2)) + (cellSize / 2), -(cellSize * (mazeRows / 2)) + (cellSize / 2));
112
+
113
+ Vector2 spawnPos = startPos;
114
+
115
+
116
+
117
+ for (int x = 1; x <= mazeColumns; x++)
118
+
119
+ {
120
+
121
+ for (int y = 1; y <= mazeRows; y++)
122
+
123
+ {
124
+
125
+ GenerateCell(spawnPos, new Vector2(x, y));
126
+
127
+
128
+
129
+ // Increase spawnPos y.
130
+
131
+ spawnPos.y += cellSize;
132
+
133
+ }
134
+
135
+
136
+
137
+ // Reset spawnPos y and increase spawnPos x.
138
+
139
+ spawnPos.y = startPos.y;
140
+
141
+ spawnPos.x += cellSize;
142
+
143
+ }
144
+
145
+
146
+
147
+ CreateCentre();
148
+
149
+ RunAlgorithm();
150
+
151
+ MakeExit();
152
+
153
+ }
154
+
155
+
156
+
157
+ // This is where the fun stuff happens.
158
+
159
+ public void RunAlgorithm()
160
+
161
+ {
162
+
163
+ // Get start cell, make it visited (i.e. remove from unvisited list).
164
+
165
+ unvisited.Remove(currentCell);
166
+
167
+
168
+
169
+ // While we have unvisited cells.
170
+
171
+ while (unvisited.Count > 0)
172
+
173
+ {
174
+
175
+ List<Cell> unvisitedNeighbours = GetUnvisitedNeighbours(currentCell);
176
+
177
+ if (unvisitedNeighbours.Count > 0)
178
+
179
+ {
180
+
181
+ // Get a random unvisited neighbour.
182
+
183
+ checkCell = unvisitedNeighbours[Random.Range(0, unvisitedNeighbours.Count)];
184
+
185
+ // Add current cell to stack.
186
+
187
+ stack.Add(currentCell);
188
+
189
+ // Compare and remove walls.
190
+
191
+ CompareWalls(currentCell, checkCell);
192
+
193
+ // Make currentCell the neighbour cell.
194
+
195
+ currentCell = checkCell;
196
+
197
+ // Mark new current cell as visited.
198
+
199
+ unvisited.Remove(currentCell);
200
+
201
+ }
202
+
203
+ else if (stack.Count > 0)
204
+
205
+ {
206
+
207
+ // Make current cell the most recently added Cell from the stack.
208
+
209
+ currentCell = stack[stack.Count - 1];
210
+
211
+ // Remove it from stack.
212
+
213
+ stack.Remove(currentCell);
214
+
215
+ }
216
+
217
+ }
218
+
219
+ }
220
+
221
+
222
+
223
+ public void MakeExit()
224
+
225
+ {
226
+
227
+ // Create and populate list of all possible edge cells.
228
+
229
+ List<Cell> edgeCells = new List<Cell>();
230
+
231
+
232
+
233
+ foreach (KeyValuePair<Vector2, Cell> cell in allCells)
234
+
235
+ {
236
+
237
+ if (cell.Key.x == 0 || cell.Key.x == mazeColumns || cell.Key.y == 0 || cell.Key.y == mazeRows)
238
+
239
+ {
240
+
241
+ edgeCells.Add(cell.Value);
242
+
243
+ }
244
+
245
+ }
246
+
247
+
248
+
249
+ // Get edge cell randomly from list.
250
+
251
+ Cell newCell = edgeCells[Random.Range(0, edgeCells.Count)];
252
+
253
+
254
+
255
+ // Remove appropriate wall for chosen edge cell.
256
+
257
+ if (newCell.gridPos.x == 0) RemoveWall(newCell.cScript, 1);
258
+
259
+ else if (newCell.gridPos.x == mazeColumns) RemoveWall(newCell.cScript, 2);
260
+
261
+ else if (newCell.gridPos.y == mazeRows) RemoveWall(newCell.cScript, 3);
262
+
263
+ else RemoveWall(newCell.cScript, 4);
264
+
265
+
266
+
267
+ Debug.Log("Maze generation finished.");
268
+
269
+ }
270
+
271
+
272
+
273
+ public List<Cell> GetUnvisitedNeighbours(Cell curCell)
274
+
275
+ {
276
+
277
+ // Create a list to return.
278
+
279
+ List<Cell> neighbours = new List<Cell>();
280
+
281
+ // Create a Cell object.
282
+
283
+ Cell nCell = curCell;
284
+
285
+ // Store current cell grid pos.
286
+
287
+ Vector2 cPos = curCell.gridPos;
288
+
289
+
290
+
291
+ foreach (Vector2 p in neighbourPositions)
292
+
293
+ {
294
+
295
+ // Find position of neighbour on grid, relative to current.
296
+
297
+ Vector2 nPos = cPos + p;
298
+
299
+ // If cell exists.
300
+
301
+ if (allCells.ContainsKey(nPos)) nCell = allCells[nPos];
302
+
303
+ // If cell is unvisited.
304
+
305
+ if (unvisited.Contains(nCell)) neighbours.Add(nCell);
306
+
307
+ }
308
+
309
+
310
+
311
+ return neighbours;
312
+
313
+ }
314
+
315
+
316
+
317
+ // Compare neighbour with current and remove appropriate walls.
318
+
319
+ public void CompareWalls(Cell cCell, Cell nCell)
320
+
321
+ {
322
+
323
+ // If neighbour is left of current.
324
+
325
+ if (nCell.gridPos.x < cCell.gridPos.x)
326
+
327
+ {
328
+
329
+ RemoveWall(nCell.cScript, 2);
330
+
331
+ RemoveWall(cCell.cScript, 1);
332
+
333
+ }
334
+
335
+ // Else if neighbour is right of current.
336
+
337
+ else if (nCell.gridPos.x > cCell.gridPos.x)
338
+
339
+ {
340
+
341
+ RemoveWall(nCell.cScript, 1);
342
+
343
+ RemoveWall(cCell.cScript, 2);
344
+
345
+ }
346
+
347
+ // Else if neighbour is above current.
348
+
349
+ else if (nCell.gridPos.y > cCell.gridPos.y)
350
+
351
+ {
352
+
353
+ RemoveWall(nCell.cScript, 4);
354
+
355
+ RemoveWall(cCell.cScript, 3);
356
+
357
+ }
358
+
359
+ // Else if neighbour is below current.
360
+
361
+ else if (nCell.gridPos.y < cCell.gridPos.y)
362
+
363
+ {
364
+
365
+ RemoveWall(nCell.cScript, 3);
366
+
367
+ RemoveWall(cCell.cScript, 4);
368
+
369
+ }
370
+
371
+ }
372
+
373
+
374
+
375
+ // Function disables wall of your choosing, pass it the script attached to the desired cell
376
+
377
+ // and an 'ID', where the ID = the wall. 1 = left, 2 = right, 3 = up, 4 = down.
378
+
379
+ public void RemoveWall(CellScript cScript, int wallID)
380
+
381
+ {
382
+
383
+ if (wallID == 1) cScript.wallL.SetActive(false);
384
+
385
+ else if (wallID == 2) cScript.wallR.SetActive(false);
386
+
387
+ else if (wallID == 3) cScript.wallU.SetActive(false);
388
+
389
+ else if (wallID == 4) cScript.wallD.SetActive(false);
390
+
391
+ }
392
+
393
+
394
+
395
+ public void CreateCentre()
396
+
397
+ {
398
+
399
+ // Get the 4 centre cells using the rows and columns variables.
400
+
401
+ // Remove the required walls for each.
402
+
403
+ centreCells[0] = allCells[new Vector2((mazeColumns / 2), (mazeRows / 2) + 1)];
404
+
405
+ RemoveWall(centreCells[0].cScript, 4);
406
+
407
+ RemoveWall(centreCells[0].cScript, 2);
408
+
409
+ centreCells[1] = allCells[new Vector2((mazeColumns / 2) + 1, (mazeRows / 2) + 1)];
410
+
411
+ RemoveWall(centreCells[1].cScript, 4);
412
+
413
+ RemoveWall(centreCells[1].cScript, 1);
414
+
415
+ centreCells[2] = allCells[new Vector2((mazeColumns / 2), (mazeRows / 2))];
416
+
417
+ RemoveWall(centreCells[2].cScript, 3);
418
+
419
+ RemoveWall(centreCells[2].cScript, 2);
420
+
421
+ centreCells[3] = allCells[new Vector2((mazeColumns / 2) + 1, (mazeRows / 2))];
422
+
423
+ RemoveWall(centreCells[3].cScript, 3);
424
+
425
+ RemoveWall(centreCells[3].cScript, 1);
426
+
427
+
428
+
429
+ // Create a List of ints, using this, select one at random and remove it.
430
+
431
+ // We then use the remaining 3 ints to remove 3 of the centre cells from the 'unvisited' list.
432
+
433
+ // This ensures that one of the centre cells will connect to the maze but the other three won't.
434
+
435
+ // This way, the centre room will only have 1 entry / exit point.
436
+
437
+ List<int> rndList = new List<int> { 0, 1, 2, 3 };
438
+
439
+ int startCell = rndList[Random.Range(0, rndList.Count)];
440
+
441
+ rndList.Remove(startCell);
442
+
443
+ currentCell = centreCells[startCell];
444
+
445
+ foreach(int c in rndList)
446
+
447
+ {
448
+
449
+ unvisited.Remove(centreCells[c]);
450
+
451
+ }
452
+
453
+ }
454
+
455
+
456
+
457
+ public void GenerateCell(Vector2 pos, Vector2 keyPos)
458
+
459
+ {
460
+
461
+ // Create new Cell object.
462
+
463
+ Cell newCell = new Cell();
464
+
465
+
466
+
467
+ // Store reference to position in grid.
468
+
469
+ newCell.gridPos = keyPos;
470
+
471
+ // Set and instantiate cell GameObject.
472
+
473
+ newCell.cellObject = Instantiate(cellPrefab, pos, cellPrefab.transform.rotation);
474
+
475
+ // Child new cell to parent.
476
+
477
+ if (mazeParent != null) newCell.cellObject.transform.parent = mazeParent.transform;
478
+
479
+ // Set name of cellObject.
480
+
481
+ newCell.cellObject.name = "Cell - X:" + keyPos.x + " Y:" + keyPos.y;
482
+
483
+ // Get reference to attached CellScript.
484
+
485
+ newCell.cScript = newCell.cellObject.GetComponent<CellScript>();
486
+
487
+ // Disable Cell sprite, if applicable.
488
+
489
+ if (disableCellSprite) newCell.cellObject.GetComponent<SpriteRenderer>().enabled = false;
490
+
491
+
492
+
493
+ // Add to Lists.
494
+
495
+ allCells[keyPos] = newCell;
496
+
497
+ unvisited.Add(newCell);
498
+
499
+ }
500
+
501
+
502
+
503
+ public void DeleteMaze()
504
+
505
+ {
506
+
507
+ if (mazeParent != null) Destroy(mazeParent);
508
+
509
+ }
510
+
511
+
512
+
513
+ public void InitValues()
514
+
515
+ {
516
+
517
+ // Check generation values to prevent generation failing.
518
+
519
+ if (IsOdd(mazeRows)) mazeRows--;
520
+
521
+ if (IsOdd(mazeColumns)) mazeColumns--;
522
+
523
+
524
+
525
+ if (mazeRows <= 3) mazeRows = 4;
526
+
527
+ if (mazeColumns <= 3) mazeColumns = 4;
528
+
529
+
530
+
531
+ // Determine size of cell using localScale.
532
+
533
+ cellSize = cellPrefab.transform.localScale.x;
534
+
535
+
536
+
537
+ // Create an empty parent object to hold the maze in the scene.
538
+
539
+ mazeParent = new GameObject();
540
+
541
+ mazeParent.transform.position = Vector2.zero;
542
+
543
+ mazeParent.name = "Maze";
544
+
545
+ }
546
+
547
+
548
+
549
+ public bool IsOdd(int value)
550
+
551
+ {
552
+
553
+ return value % 2 != 0;
554
+
555
+ }
556
+
557
+
558
+
559
+ public class Cell
560
+
561
+ {
562
+
563
+ public Vector2 gridPos;
564
+
565
+ public GameObject cellObject;
566
+
567
+ public CellScript cScript;
568
+
569
+ }
570
+
571
+ }
572
+
573
+
574
+
575
+ ```
576
+
577
+
578
+
31
579
  ### 試したこと
32
580
 
33
581