I implemented the algorithm from the answer in here Maze (recursive division) algorithm design.
but I ran into a problem that there isn't always a path from start(+) to finish(-) like this image.
also there is another problem that the start(+) or finish(-) node will be surrounded by wall see start node (+)
but I think it's easy to fix.
remove the walls around that node [x-1][y], [x][y+1], [x+1][y] and [x][y-1].
I don't know if it's the right fix or not.
that's my maze class
class Maze {
private G: INode[][];
private rows: number;
private cols: number;
constructor(G: INode[][]) {
this.G = G.map((row) =>
row.map((node) => ({
...node,
isWall: false,
}))
);
this.rows = this.G.length;
this.cols = this.G[0].length;
// border walls
for (let i = 0; i < this.rows; i++) {
this.G[i][0].isWall = true;
this.G[i][this.cols - 1].isWall = true;
}
for (let i = 0; i < this.cols; i++) {
this.G[0][i].isWall = true;
this.G[this.rows - 1][i].isWall = true;
}
}
private rand(min: number, max: number) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
private isNodeStartOrFinish(row: number, col: number) {
return this.G[row][col].isStart || this.G[row][col].isFinish;
}
// call perfectMaze to get the generate the maze
public perfectMaze() {
this.divide(true, 1, this.cols - 2, 1, this.rows - 2);
}
private divide(
h: boolean,
minX: number,
maxX: number,
minY: number,
maxY: number
) {
if (h) {
if (maxX - minX < 2) return;
const y = Math.floor(this.rand(minY, maxY) / 2) * 2;
this.addHWall(minX, maxX, y);
this.divide(!h, minX, maxX, minY, y - 1);
this.divide(!h, minX, maxX, y + 1, maxY);
} else {
if (maxY - minY < 2) return;
const x = Math.floor(this.rand(minX, maxX) / 2) * 2;
this.addVWall(minY, maxY, x);
this.divide(!h, minX, x - 1, minY, maxY);
this.divide(!h, x + 1, maxX, minY, maxY);
}
}
private addHWall(minX: number, maxX: number, y: number) {
const hole = Math.floor(this.rand(minX, maxX) / 2) * 2 + 1;
for (let i = minX; i <= maxX; i++) {
if (i !== hole && !this.isNodeStartOrFinish(y, i)) {
this.G[y][i].isWall = true;
}
}
}
private addVWall(minY: number, maxY: number, x: number) {
const hole = Math.floor(this.rand(minY, maxY) / 2) * 2 + 1;
for (let i = minY; i <= maxY; i++) {
if (i !== hole && !this.isNodeStartOrFinish(i, x)) {
this.G[i][x].isWall = true;
}
}
}
public getMaze() {
return this.G;
}
}
okay i was stupid
i didn't remove the wall when i === hole
in the addHWall and addVWall methods
you must delete the wall if i === hole otherwise the wall will be added again
private addHWall(minX: number, maxX: number, y: number) {
const hole = Math.floor(this.rand(minX, maxX) / 2) * 2 + 1;
for (let i = minX; i <= maxX; i++) {
if (i === hole || this.isNodeStartOrFinish(y, i)) {
this.G[y][i].isWall = false;
} else {
this.G[y][i].isWall = true;
}
}
}
the same with addVWall
if (i === hole || this.isNodeStartOrFinish(i, x)) {
this.G[y][i].isWall = false;
} else {
this.G[i][x].isWall = true;
}
and i ended up deleting the walls around the start and finish node still don't know if it's the right solution or not