// Canvas visualization for mazes const canvas = document.getElementById('mazeCanvas'); const ctx = canvas.getContext('2d'); const COLORS = { wall: '#000000', background: '#FFFFFF', start: '#FFE500', // Neon yellow end: '#FF10F0', // Neon pink solution: '#39FF14', // Neon green visited: '#E0E0E0' // Light gray }; function renderMaze(mazeData, visitedCells = null, solutionPath = null) { const rows = mazeData.rows; const cols = mazeData.cols; const cellSize = Math.min(Math.floor(600 / Math.max(rows, cols)), 40); const wallThickness = Math.max(2, Math.floor(cellSize / 10)); // Set canvas size canvas.width = cols * cellSize + wallThickness; canvas.height = rows * cellSize + wallThickness; // Clear canvas ctx.fillStyle = COLORS.background; ctx.fillRect(0, 0, canvas.width, canvas.height); // Create sets for quick lookup const visitedSet = new Set(); if (visitedCells) { visitedCells.forEach(([r, c]) => visitedSet.add(`${r},${c}`)); } const solutionSet = new Set(); if (solutionPath) { solutionPath.forEach(([r, c]) => solutionSet.add(`${r},${c}`)); } // Draw cell backgrounds for (let row = 0; row < rows; row++) { for (let col = 0; col < cols; col++) { const x = col * cellSize + wallThickness; const y = row * cellSize + wallThickness; const key = `${row},${col}`; // Determine cell color let color = COLORS.background; if (row === mazeData.start[0] && col === mazeData.start[1]) { color = COLORS.start; } else if (row === mazeData.end[0] && col === mazeData.end[1]) { color = COLORS.end; } else if (solutionSet.has(key)) { color = COLORS.solution; } else if (visitedSet.has(key)) { color = COLORS.visited; } ctx.fillStyle = color; ctx.fillRect(x, y, cellSize - 1, cellSize - 1); } } // Draw walls ctx.strokeStyle = COLORS.wall; ctx.lineWidth = wallThickness; ctx.lineCap = 'square'; for (let row = 0; row < rows; row++) { for (let col = 0; col < cols; col++) { const cellWalls = mazeData.walls[row][col]; const x = col * cellSize + wallThickness / 2; const y = row * cellSize + wallThickness / 2; // Draw north wall if (cellWalls.north) { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x + cellSize, y); ctx.stroke(); } // Draw south wall if (cellWalls.south) { ctx.beginPath(); ctx.moveTo(x, y + cellSize); ctx.lineTo(x + cellSize, y + cellSize); ctx.stroke(); } // Draw west wall if (cellWalls.west) { ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(x, y + cellSize); ctx.stroke(); } // Draw east wall if (cellWalls.east) { ctx.beginPath(); ctx.moveTo(x + cellSize, y); ctx.lineTo(x + cellSize, y + cellSize); ctx.stroke(); } } } // Draw start and end markers with text drawMarker(mazeData.start[0], mazeData.start[1], 'S', cellSize, wallThickness); drawMarker(mazeData.end[0], mazeData.end[1], 'E', cellSize, wallThickness); } function drawMarker(row, col, text, cellSize, wallThickness) { const x = col * cellSize + wallThickness + cellSize / 2; const y = row * cellSize + wallThickness + cellSize / 2; ctx.fillStyle = '#000000'; ctx.font = `bold ${Math.max(12, cellSize / 2)}px Space Grotesk, monospace`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText(text, x, y); }