xxxxxxxxxx
222
let cols, rows;
let cellSize = 70; // SIZE OF EACH CELL
let grid = []; // AN ARRAY TO STORE ALL THE CELLS
let available = []; // AN ARRAY TO STORE ALL THE UNVISITED CELLS
let current; // THE CURRENT CELL BEING VISITED
let playerAx = 0;
let playerAy = 0;
let playerBx = 0;
let playerBy = 0;
let selected; // CURRENTLY SELECTED CELL
let sets = []; // SETS OF CELLS THAT ARE CONNECTED
let wallsRemoved = 0; // COUNTER FOR THE NUMBER OF WALLS REMOVED
// MAZE BUILDING CLASS
class mazeBuilder {
constructor(i, j) {
this.i = i;
this.j = j;
this.cellWalls = [true, true, true, true]; // BORDERS ON FOUR SIDES OF THE CELL
this.id = i * cols + (j + 1); // UNIQUE ID FOR THE CELL
this.isFinished = false; // CHECK IF ALL NEIGHBORS ARE IN SAME SET
}
// CHECK IF NEIGHBORING CELL IS CONNECTED TO CURRENT CELL
isConnected(neighbor) {
//ITERATE THROUGH A LIST OF SETS AND CHECK IF BOTH THE CURRENT CELL AND NEIGHBOR CELL ARE IN THE SAME SET
for (let i = 0; i < sets.length; i++) {
if (sets[i].includes(this.id) && sets[i].includes(neighbor.id)) {
return true;
}
}
return false;
}
// GET A RANDOM UNVISITED NEIGHBOR CELL
randomNeighbor() {
let neighbors = [];
let top = grid[index(this.i, this.j - 1)];
let right = grid[index(this.i + 1, this.j)];
let bottom = grid[index(this.i, this.j + 1)];
let left = grid[index(this.i - 1, this.j)];
//CHECK IF HAS NEIGHBORS, WASN'T VISITED, AND IS NOT CONNECTED TO THE CURRENT CELL
//IF MEETS ALL CRITERIA -> ADD TO ARRAY OF AVAILABLE NEIGHBORS
if (this.cellWalls[0] && top && !this.isConnected(top)) {
neighbors.push(top);
}
if (this.cellWalls[1] && right && !this.isConnected(right)) {
neighbors.push(right);
}
if (this.cellWalls[2] && bottom && !this.isConnected(bottom)) {
neighbors.push(bottom);
}
if (this.cellWalls[3] && left && !this.isConnected(left)) {
neighbors.push(left);
}
//RANDOMLY CHOOSE ONE OF THE NEIGHBORS AND RETURN TO CONNECT
//IF NO NEIGHBORS -> RETURN UNDEFINED
if (neighbors.length > 0) {
let r = floor(random(0, neighbors.length));
return neighbors[r];
} else {
return undefined;
}
}
// HIGHLIGHT CURRENT PLAYER POSITION AND MAZE END
highlight(isRed) {
let x = this.i * cellSize;
let y = this.j * cellSize;
noStroke();
strokeWeight(35);
if (isRed) {
fill(255, 0, 0);
rect(x + 2, y + 2, cellSize - 4, cellSize - 4);
} else {
fill(0, 255, 255);
rect(x, y, cellSize, cellSize);
}
}
// DRAW THE CELL WITH BORDERS
show() {
let x = this.i * cellSize;
let y = this.j * cellSize;
stroke(0, 255, 0);
//ITERATE THROUGH CellWalls ARRAY
//IF WALL IS TRUE -> DRAW A LINE
if (this.cellWalls[0]) {
line(x, y, x + cellSize, y);
}
if (this.cellWalls[1]) {
line(x + cellSize, y, x + cellSize, y + cellSize);
}
if (this.cellWalls[2]) {
line(x + cellSize, y + cellSize, x, y + cellSize);
}
if (this.cellWalls[3]) {
line(x, y + cellSize, x, y);
}
}
}
function setup() {
createCanvas(980, 740);
//CALCULATE THE NUMBER OF COLS AND ROWS THAT CAN FIT ON CANVAS
cols = floor(width / cellSize);
rows = floor(height / cellSize);
for (let j = 0; j < rows; j++) {
for (let i = 0; i < cols; i++) {
let cell = new mazeBuilder(i, j);
//INITIALIZE TWO ARRAYS
grid.push(cell); //HOLD ALL CELLS ON CANVAS
sets.push([cell.id]); //HOLD ALL SETS OF CONNECTED CELLS
}
}
available = grid;
current = grid[int(random(0, rows * cols))];
}
function draw() {
background(24, 54, 22);
for (let i = 0; i < grid.length; i++) {
grid[i].show();
}
if (wallsRemoved < cols * rows - 1) {
if (!current.isFinished) {
current.highlight();
// CHOOSE RANDOM NEIGHBOR
let neighbor = current.randomNeighbor();
let mergedSet, removedSet, removedIndex;
if (neighbor) {
// FIND THE SETS THAT CURRENT AND NEIGHBOR ARE IN
for (let i = 0; i < sets.length; i++) {
if (sets[i].includes(current.id)) {
mergedSet = sets[i];
} else if (sets[i].includes(neighbor.id)) {
removedSet = sets[i];
removedIndex = i;
}
}
// ADD NEIGHBOR TO CURRENT SET AND DELETE NEIGHBOR'S SET
if (removedSet !== undefined) {
for (let i = 0; i < removedSet.length; i++) {
mergedSet.push(removedSet[i]);
}
sets.splice(removedIndex, 1);
// REMOVE WALLS FROM BETWEEN CURRENT AND NEIGHBOR
removeWalls(current, neighbor);
}
} else if (sets.length > 1) {
current.isFinished = true;
available = available.filter((cell) => cell.id !== current.id);
}
}
// GET NEW CURRENT (RANDOM)
current = available[int(random(0, available.length))];
} else {
selected = grid.filter(
(cell) => cell.i === playerAx && cell.j === playerAy
)[0];
selected.highlight();
grid[grid.length - 1].highlight(true);
}
}
function keyPressed() {
//PLAYER1 CONTROLS
if ((key == "W" || key == "w") && playerAy > 0) {
if (!selected.cellWalls[0]) {
playerAy--;
}
} else if ((key == "A" || key == "a") && playerAx > 0) {
if (!selected.cellWalls[3]) {
playerAx--;
}
} else if ((key == "S" || key == "s") && playerAy < rows - 1) {
if (!selected.cellWalls[2]) {
playerAy++;
}
} else if ((key == "D" || key == "d") && playerAx < cols - 1) {
if (!selected.cellWalls[1]) {
playerAx++;
}
}
//PLAYER2 CONTROLS
// else if ((keyCode == UP_ARROW))
}
function index(i, j) {
if (i < 0 || j < 0 || i > cols - 1 || j > rows - 1) {
return -1;
}
return i + j * cols;
}
function removeWalls(a, b) {
let x = a.i - b.i;
if (x === 1) {
a.cellWalls[3] = false;
b.cellWalls[1] = false;
} else if (x === -1) {
a.cellWalls[1] = false;
b.cellWalls[3] = false;
}
let y = a.j - b.j;
if (y === 1) {
a.cellWalls[0] = false;
b.cellWalls[2] = false;
} else if (y === -1) {
a.cellWalls[2] = false;
b.cellWalls[0] = false;
}
wallsRemoved++;
}