Skip to content

Commit 275e5f0

Browse files
return and enhance generateMaze
1 parent aa0ba24 commit 275e5f0

File tree

1 file changed

+88
-7
lines changed

1 file changed

+88
-7
lines changed

lib/features/grid/view_model/grid_notifier.dart

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:collection';
2+
import 'dart:math';
23
import 'package:collection/collection.dart';
34
import 'package:flutter/material.dart';
45
import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -11,9 +12,10 @@ class GridNotifierCubit extends StateNotifier<GridNotifierState> {
1112
static const Duration scaleAppearDurationForWall = Duration(milliseconds: 700);
1213
static const Duration clearDuration = Duration(microseconds: 10);
1314
static const Duration drawFindingPathDuration = Duration(milliseconds: 2);
14-
static const Duration drawSearcherDuration = Duration(milliseconds: 2);
15+
static const Duration drawSearcherDuration = Duration(milliseconds: 5);
1516

1617
int tapDownIndex = -1;
18+
GridStatus tapDownGridStatus = GridStatus.empty;
1719

1820
void updateGridLayout(Size size) {
1921
final screenWidth = size.width;
@@ -92,12 +94,14 @@ class GridNotifierCubit extends StateNotifier<GridNotifierState> {
9294
return gridStatus;
9395
}
9496

95-
Future<void> _clearTheGrid({required GridNotifierState addState}) async {
97+
Future<void> _clearTheGrid({required GridNotifierState addState, bool keepWall = false}) async {
9698
final elements = addState.gridData;
9799

98100
for (int i = 0; i < elements.length; i++) {
99101
final grid = addState.gridData[i];
102+
100103
if (grid == GridStatus.targetPoint || grid == GridStatus.startPoint) continue;
104+
if (grid == GridStatus.wall && keepWall) continue;
101105

102106
addState.gridData[i] = GridStatus.empty;
103107
state = addState.copyWith(gridData: addState.gridData);
@@ -106,8 +110,8 @@ class GridNotifierCubit extends StateNotifier<GridNotifierState> {
106110
}
107111
}
108112

109-
void clearTheGrid() {
110-
_clearTheGrid(addState: state);
113+
void clearTheGrid({bool keepWall = false}) {
114+
_clearTheGrid(addState: state, keepWall: keepWall);
111115

112116
state = state.copyWith(currentTappedIndex: -1);
113117
}
@@ -131,11 +135,13 @@ class GridNotifierCubit extends StateNotifier<GridNotifierState> {
131135
final currentGrid = updatedGridData[index];
132136

133137
if (updatedGridData[tapDownIndex] == GridStatus.startPoint) {
134-
updatedGridData[tapDownIndex] = GridStatus.empty;
138+
updatedGridData[tapDownIndex] = tapDownGridStatus;
139+
tapDownGridStatus = updatedGridData[index];
135140
updatedGridData[index] = GridStatus.startPoint;
136141
tapDownIndex = index;
137142
} else if (updatedGridData[tapDownIndex] == GridStatus.targetPoint) {
138-
updatedGridData[tapDownIndex] = GridStatus.empty;
143+
updatedGridData[tapDownIndex] = tapDownGridStatus;
144+
tapDownGridStatus = updatedGridData[index];
139145
updatedGridData[index] = GridStatus.targetPoint;
140146
tapDownIndex = index;
141147
} else if (currentGrid == GridStatus.empty) {
@@ -288,7 +294,7 @@ class GridNotifierCubit extends StateNotifier<GridNotifierState> {
288294
bool _isValidNeighbor(
289295
int currentIndex, int neighborIndex, int direction, int cross, List<GridStatus> gridData) {
290296
final isFirstLeftInRowIndex = neighborIndex % cross == 0;
291-
final isEndRightInRowIndex = neighborIndex % (cross - 1) == 0;
297+
final isEndRightInRowIndex = (neighborIndex + 1) % cross == 0;
292298

293299
if (direction == 1 && isFirstLeftInRowIndex) return false; // avoid exiting the boundaries
294300
if (direction == -1 && isEndRightInRowIndex) return false; // avoid exiting the boundaries
@@ -311,4 +317,79 @@ class GridNotifierCubit extends StateNotifier<GridNotifierState> {
311317
traceIndex = previous[traceIndex];
312318
}
313319
}
320+
321+
void generateMaze() {
322+
final gridData = List<GridStatus>.from(state.gridData);
323+
324+
// Clear the maze but keep start and target points
325+
for (int i = 0; i < gridData.length; i++) {
326+
if (gridData[i] != GridStatus.startPoint && gridData[i] != GridStatus.targetPoint) {
327+
gridData[i] = GridStatus.empty;
328+
}
329+
}
330+
331+
// Start the division from the full grid
332+
_recursiveDivision(gridData, 0, state.rowMainAxisCount, 0, state.columnCrossAxisCount);
333+
}
334+
335+
Future<void> _recursiveDivision(
336+
List<GridStatus> gridData, int rowStart, int rowEnd, int colStart, int colEnd) async {
337+
if (rowEnd - rowStart < 2 || colEnd - colStart < 2) return; // Avoid too small segments
338+
339+
bool divideVertically = Random().nextBool();
340+
341+
if (divideVertically) {
342+
return _recursiveVerticalDivision(gridData, rowStart, rowEnd, colStart, colEnd);
343+
} else {
344+
return _recursiveHorizontalDivision(gridData, rowStart, rowEnd, colStart, colEnd);
345+
}
346+
}
347+
348+
Future<void> _recursiveVerticalDivision(
349+
List<GridStatus> gridData, int rowStart, int rowEnd, int colStart, int colEnd) async {
350+
if (rowEnd - rowStart < 2 || colEnd - colStart < 2) return;
351+
352+
int splitCol = Random().nextInt(colEnd - colStart - 1) + colStart + 1;
353+
for (int row = rowStart; row < rowEnd; row++) {
354+
if (row == rowStart || row == rowEnd - 1) continue; // Skip the boundary
355+
final index = row * state.columnCrossAxisCount + splitCol;
356+
final grid = gridData[index];
357+
if (grid == GridStatus.startPoint || grid == GridStatus.targetPoint) return;
358+
gridData[index] = GridStatus.wall;
359+
state = state.copyWith(gridData: List<GridStatus>.from(gridData));
360+
await Future.delayed(const Duration(milliseconds: 10));
361+
}
362+
363+
// Open a passage
364+
int passageAt = Random().nextInt(rowEnd - rowStart) + rowStart;
365+
gridData[passageAt * state.columnCrossAxisCount + splitCol] = GridStatus.empty;
366+
367+
await _recursiveDivision(gridData, rowStart, rowEnd, colStart, splitCol);
368+
await _recursiveDivision(gridData, rowStart, rowEnd, splitCol + 1, colEnd);
369+
}
370+
371+
Future<void> _recursiveHorizontalDivision(
372+
List<GridStatus> gridData, int rowStart, int rowEnd, int colStart, int colEnd) async {
373+
if (rowEnd - rowStart < 2 || colEnd - colStart < 2) return;
374+
375+
int splitRow = Random().nextInt(rowEnd - rowStart - 1) + rowStart + 1;
376+
for (int col = colStart; col < colEnd; col++) {
377+
if (col == colStart || col == colEnd - 1) continue; // Skip the boundary
378+
379+
final index = splitRow * state.columnCrossAxisCount + col;
380+
final grid = gridData[index];
381+
if (grid == GridStatus.startPoint || grid == GridStatus.targetPoint) return;
382+
gridData[index] = GridStatus.wall;
383+
384+
state = state.copyWith(gridData: List<GridStatus>.from(gridData));
385+
await Future.delayed(const Duration(milliseconds: 10));
386+
}
387+
388+
// Open a passage
389+
int passageAt = Random().nextInt(colEnd - colStart) + colStart;
390+
gridData[splitRow * state.columnCrossAxisCount + passageAt] = GridStatus.empty;
391+
392+
await _recursiveDivision(gridData, rowStart, splitRow, colStart, colEnd);
393+
await _recursiveDivision(gridData, splitRow + 1, rowEnd, colStart, colEnd);
394+
}
314395
}

0 commit comments

Comments
 (0)