/**
* @fileoverview Renderer für das Springerproblem.
* Zeichnet das Brett mit einem verbesserten Farbschema.
*/
const KnightRenderer = {
/**
* @param {HTMLCanvasElement} canvas
* @param {KnightBoard} board
* @param {Object} config
*/
draw(canvas, board, config = {}) {
const ctx = canvas.getContext('2d');
const size = board.size;
const showMoves = config.showPossibleMoves || false;
const showWarnsdorf = config.showWarnsdorf || false;
// --- NEUES FARBSCHEMA ---
const COLORS = {
bg: '#ffffff',
cellEven: '#ecf0f1', // Helles Grau
cellOdd: '#bdc3c7', // Dunkleres Grau
visited: '#2ecc71', // Grün (angenehm)
visitedPrev: '#178a3a', // Dunkleres Grün für vorletzten Zug
visitedText: '#ffffff',
current: '#e67e22', // Orange für den Springer
possible: 'rgba(52, 152, 219, 0.6)', // Blau transparent
warnsdorfText: '#3498db', // Blau für Zahlen
coord: '#7f8c8d'
};
// Layout
const paddingLeft = 30;
const paddingBottom = 30;
const availWidth = canvas.width - paddingLeft;
const availHeight = canvas.height - paddingBottom;
const cellSize = Math.min(availWidth, availHeight) / size;
// Reset
ctx.fillStyle = COLORS.bg;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 1. Koordinaten (A-H, 1-8)
ctx.fillStyle = COLORS.coord;
ctx.font = "12px 'Segoe UI'";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for(let i=0; i<size; i++) {
// Buchstaben unten
const char = String.fromCharCode(65 + i);
ctx.fillText(char, paddingLeft + i * cellSize + cellSize/2, canvas.height - (paddingBottom / 2));
// Zahlen links
const num = size - i;
ctx.fillText(num, paddingLeft / 2, i * cellSize + cellSize/2);
}
// Canvas verschieben für das Grid
ctx.save();
ctx.translate(paddingLeft, 0);
// 2. Gitter & Zellen zeichnen
// Vorletztes Feld bestimmen
let prevPos = null;
if (board.history && board.history.length >= 2) {
prevPos = board.history[board.history.length - 2];
}
for (let r = 0; r < size; r++) {
for (let c = 0; c < size; c++) {
const x = c * cellSize;
const y = r * cellSize;
const val = board.grid[r][c];
// Grundfarbe (Schachbrett)
if ((r + c) % 2 === 0) ctx.fillStyle = COLORS.cellEven;
else ctx.fillStyle = COLORS.cellOdd;
ctx.fillRect(x, y, cellSize, cellSize);
// Vorletztes Feld hervorheben (dunkelgrün, aber NICHT aktueller Springer)
if (prevPos && prevPos.r === r && prevPos.c === c) {
ctx.fillStyle = COLORS.visitedPrev;
const pad = 2;
ctx.fillRect(x + pad, y + pad, cellSize - pad*2, cellSize - pad*2);
}
// Besuchte Felder
if (val > 0) {
// Normale besuchte Felder (außer vorletztes und aktuelles)
// Das aktuelle Feld wird später orange gemalt
if (!(prevPos && prevPos.r === r && prevPos.c === c)) {
ctx.fillStyle = COLORS.visited;
const pad = 2;
ctx.fillRect(x + pad, y + pad, cellSize - pad*2, cellSize - pad*2);
}
// Zugnummer
ctx.fillStyle = COLORS.visitedText;
ctx.font = `bold ${cellSize * 0.4}px sans-serif`;
ctx.fillText(val, x + cellSize/2, y + cellSize/2);
}
}
}
// 3. Mögliche Züge (Vorschau)
if (showMoves && !board.won && !config.hideHints) {
const moves = board.getPossibleMoves();
if (showWarnsdorf) {
// Zeige Warnsdorf-Zahlen statt Punkte
moves.forEach(m => {
const cx = m.c * cellSize + cellSize/2;
const cy = m.r * cellSize + cellSize/2;
const degree = board.getDegree(m.r, m.c);
ctx.fillStyle = COLORS.warnsdorfText;
ctx.font = `bold ${cellSize * 0.35}px sans-serif`;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(degree, cx, cy);
});
} else {
// Zeige blaue Punkte
moves.forEach(m => {
const cx = m.c * cellSize + cellSize/2;
const cy = m.r * cellSize + cellSize/2;
ctx.beginPath();
ctx.fillStyle = COLORS.possible;
ctx.arc(cx, cy, cellSize * 0.2, 0, Math.PI * 2);
ctx.fill();
});
}
}
// 4. Springer (Aktuelle Position)
if (board.currentPos) {
const { r, c } = board.currentPos;
const x = c * cellSize;
const y = r * cellSize;
// Highlight Box
ctx.fillStyle = COLORS.current;
ctx.fillRect(x, y, cellSize, cellSize);
// Springer Icon
ctx.fillStyle = "white";
ctx.font = `${cellSize * 0.7}px serif`;
ctx.fillText("♞", x + cellSize/2, y + cellSize/2 + 2);
}
ctx.restore();
}
};