BUG
keyPressed() - movement validation
The constrain() function at the end of keyPressed() is redundant because wall checks already prevent out-of-bounds movement. However, if a wall check is somehow skipped, constrain() would silently allow movement to an invalid cell.
๐ก Remove the constrain() calls and instead ensure all directional checks include proper boundary validation: if (!currentCell.walls[3] && player.i > 0) instead of relying on constrain() as a safety net.
FEATURE
solveMaze() and draw()
Once the solution is shown, it remains visible until the player moves. There's no way to hide the solution without moving, making it impossible to try solving the maze yourself after seeing the solution.
๐ก Add a 'Hide Solution' button in createUI() that sets solvingMaze = false and solutionPath = []. This gives players control over when they want to see the solution.
STYLE
Cell class - walls array indexing
The walls array uses numeric indices [0, 1, 2, 3] which is not immediately clear. Code like walls[3] requires checking comments to understand it means 'left'.
๐ก Create a constant object like const WALLS = {TOP: 0, RIGHT: 1, BOTTOM: 2, LEFT: 3} and use it throughout: if (!currentCell.walls[WALLS.LEFT]) instead of if (!currentCell.walls[3]). This makes the code more readable.
FEATURE
draw() and keyPressed()
There's no win condition. The player can reach the goal but nothing happens - no message, no visual feedback, no ability to restart easily.
๐ก Add a check in draw() or keyPressed(): if (player.i === goal.i && player.j === goal.j) { console.log('You reached the goal!'); } and optionally show a visual celebration or automatically generate a new maze.
STYLE
Global variables
Many global variables (cols, rows, cellWidth, grid, stack, current, player, goal, etc.) clutter the global scope. This makes the code harder to maintain and debug.
๐ก Consider wrapping the sketch in an object or using a class to encapsulate these variables, or at least group related variables with comments to organize the global scope better.