Copy code
< cldng1@yahoo.com continue'
Color to move:
Moves:
Time left: 60
``` CSS: css Copy code .chess-puzzle { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; margin: 0 auto; max-width: 800px; font-family: sans-serif; } .chessboard { border: 5px solid #ccc; width: 400px; height: 400px; display: flex; flex-wrap: wrap; } .square { width: 50px; height: 50px; text-align: center; line-height: 50px; font-size: 30px; } .square.white { background-color: #f0d9b5; } .square.black { background-color: #b58863; color: #fff; } .puzzle-details { margin-left: 50px; max-width: 300px; } .info { margin-bottom: 10px; font-size: 20px; } .moves { border: 1px solid #ccc; max-height: 200px; overflow-y: scroll; } .moves-header { background-color: #ccc; padding: 5px; } .timer { margin-top: 20px; } .timer span { font-size: 20px; margin-right: 10px; } .timer button { margin-left: 10px; } JavaScript: javascript Copy code // Define the chess puzzles const puzzles = [ { fen: '8/1k6/2b5/8/8/2K5/8/8 w - - 0 1', moves: ['Kb3', 'Ba3', 'Kc4'] }, { fen: '4k3/4p3/4K3/8/8/8/8/8 w - - 0 1', moves: ['Kd7', 'Ke7', 'Kf7'] }, { fen: '8/1p6/8/8/8/1K6/8/k7 w - - 0 1', moves: ['Kb2', 'Ka3', 'Kb3'] }, { fen: '8/8/8/8/8/8/8/k1K5 w - - 0 1', moves: ['Kb1', 'Ka1', 'Kc2'] }, { fen: '8/8/8/8/8/8/8/k1K5 w - - 0 1', moves: ['Kc2', 'Kb2', 'Ka1'] } ]; // Define the chess pieces const chessPieces = { white: { p: '♙', r: '♖', n: '♘ cldng1@yahoo.com continue vbnet Copy code b: '♗', q: '♕', k: '♔' }, black: { p: '♟', r: '♜', n: '♞', b: '♝', q: '♛', k: '♚' } }; // Define the chessboard squares const squares = document.querySelectorAll('.square'); // Define the puzzle details elements const colorToMove = document.querySelector('#color-to-move'); const movesList = document.querySelector('.moves'); const timeLeft = document.querySelector('#time-left'); const resetButton = document.querySelector('.reset-btn'); const nextButton = document.querySelector('.next-btn'); // Initialize the timer let timer; // Initialize the puzzle index let puzzleIndex = 0; // Initialize the current puzzle let currentPuzzle = puzzles[puzzleIndex]; // Set the initial color to move colorToMove.textContent = 'White'; // Set the initial moves list currentPuzzle.moves.forEach((move, index) => { let moveNumber = Math.floor(index / 2) + 1; if (index % 2 === 0) { let moveItem = document.createElement('div'); moveItem.classList.add('move-item'); moveItem.innerHTML = ${moveNumber}. ${move}; movesList.appendChild(moveItem); } else { let lastMoveItem = movesList.lastChild; lastMoveItem.innerHTML += ${move}; } }); // Set the initial chessboard position setChessboardPosition(currentPuzzle.fen); // Handle square clicks squares.forEach((square) => { square.addEventListener('click', () => { // Get the current color to move let color = getColorToMove(); scss Copy code // Check if the square is a valid move target let piece = square.textContent.trim(); if (!piece || chessPieces[color][piece.toLowerCase()]) { let squareCoords = getSquareCoords(square); let currentFen = getCurrentFen(); // Check if the move is legal if (isMoveLegal(currentFen, squareCoords)) { // Update the chessboard position and color to move let newFen = getNewFen(currentFen, squareCoords); setChessboardPosition(newFen); colorToMove.textContent = color === 'white' ? 'Black' : 'White'; // Add the move to the moves list let moveNumber = Math.floor(currentPuzzle.moves.length / 2) + 1; let lastMoveItem = movesList.lastChild; if (!lastMoveItem || lastMoveItem.innerHTML.split(' ').length === 3) { let moveItem = document.createElement('div'); moveItem.classList.add('move-item'); moveItem.innerHTML = `${moveNumber}. ${getSan(currentFen, squareCoords)}`; movesList.appendChild(moveItem); } else { lastMoveItem.innerHTML += ` ${getSan(currentFen, squareCoords)}`; } // Check if the puzzle has been solved if (isPuzzleSolved(newFen)) { clearInterval(timer); alert('Congratulations! You solved the puzzle!'); resetPuzzle(); } } } }); }); // Handle reset button click resetButton.addEventListener('click', () => { resetPuzzle(); }); // Handle next button click nextButton.addEventListener('click', () => { puzzleIndex++; if (puzzleIndex >= puzzles.length) { puzzleIndex = 0; } currentPuzzle = puzzles[puzzleIndex]; resetPuzzle(); }); // Set the chessboard position cldng1@yahoo.com continue function setChessboardPosition(fen) { let fenParts = fen.split(' '); let ranks = fenParts[0].split('/'); let rankIndex = 0; for (let rank of ranks) { let fileIndex = 0; for (let char of rank) { if (isNaN(char)) { let color = char === char.toUpperCase() ? 'white' : 'black'; let piece = chessPieces[color][char.toLowerCase()]; let square = getSquareAtCoords(fileIndex, 7 - rankIndex); square.textContent = piece; } else { let numSpaces = parseInt(char); for (let i = 0; i < numSpaces; i++) { let square = getSquareAtCoords(fileIndex, 7 - rankIndex); square.textContent = ''; fileIndex++; } } } rankIndex++; } let color = fenParts[1]; colorToMove.textContent = color === 'w' ? 'White' : 'Black'; timeLeft.textContent = 60; clearInterval(timer); timer = setInterval(() => { let remainingTime = parseInt(timeLeft.textContent); if (remainingTime > 0) { remainingTime--; timeLeft.textContent = remainingTime; } else { clearInterval(timer); alert('Time is up!'); resetPuzzle(); } }, 1000); } // Reset the puzzle function resetPuzzle() { currentPuzzle = puzzles[puzzleIndex]; setChessboardPosition(currentPuzzle.fen); movesList.innerHTML = '
Moves:
'; } // Get the color to move function getColorToMove() { return colorToMove.textContent === 'White' ? 'white' : 'black'; } // Get the coordinates of a square function getSquareCoords(square) { let file = square.parentNode.children.length - Array.from(square.parentNode.children).indexOf(square) - 1; let rank = square.parentNode.parentNode.children.length - Array.from(square.parentNode.parentNode.children).indexOf(square.parentNode) - 1; return [file, rank]; } // Get the FEN of the current chessboard position function getCurrentFen() { let fenParts = []; for (let rank = 7; rank >= 0; rank--) { let fenRow = ''; let emptySquares = 0; for (let file = 0; file < 8; file++) { let square = getSquareAtCoords(file, rank); if (square.textContent) { if (emptySquares > 0) { fenRow += emptySquares; emptySquares = 0; } let color = square.textContent === square.textContent.toUpperCase() ? 'w' : 'b'; fenRow += chessPieces[color][square.textContent.toLowerCase()]; } else { emptySquares++; } } if (emptySquares > 0) { fenRow += emptySquares; } fenParts.push(fenRow); } let fen = fenParts.join('/') + ' ' + getColorToMove()[0] + ' - - 0 1'; return fen; } // Get the square at the given coordinates function getSquareAtCoords(file, rank) { return squares[rank * 8 + file]; } // Check if a move is legal function isMoveLegal(fen, squareCoords) { let legalMoves = getLegalMoves(fen); for (let move of legalMoves) { if (move[0] === squareCoords[0] && move[1] === squareCoords cldng1@yahoo.com continue ) { return true; } } return false; } // Get the legal moves for the current position function getLegalMoves(fen) { let board = new ChessBoard(); board.load(fen); let moves = board.generateMoves(); return moves.map((move) => [move[0].file, move[0].rank]); } // Get the FEN of the position after a move is made function getNewFen(fen, squareCoords) { let currentColor = getColorToMove()[0]; let currentFenParts = fen.split(' '); let currentFenRows = currentFenParts[0].split('/'); let currentFenRow = currentFenRows[7 - squareCoords[1]]; let currentFenSquares = currentFenRow.split(''); let currentFenSquare = currentFenSquares[squareCoords[0]]; let pieceMoved = currentFenSquare.toUpperCase(); if (currentColor === 'b') { pieceMoved = pieceMoved.toLowerCase(); } let newFenRows = [...currentFenRows]; let newFenRow = [...currentFenRow]; newFenRow[squareCoords[0]] = '.'; newFenRows[7 - squareCoords[1]] = newFenRow.join(''); let newFen = newFenRows.join('/') + ${currentColor === 'w' ? 'b' : 'w'} - - 0 ${parseInt(currentFenParts[5]) + 1}; return newFen; } // Check if the puzzle has been solved function isPuzzleSolved(fen) { return fen === currentPuzzle.fen; } // Get the Standard Algebraic Notation (SAN) of a move function getSan(fen, squareCoords) { let legalMoves = getLegalMoves(fen); for (let move of legalMoves) { if (move[0] === squareCoords[0] && move[1] === squareCoords[1]) { let file = String.fromCharCode(97 + move[0]); let rank = move[1] + 1; let pieceMoved = fen.split(' ')[1] === 'w' ? 'P' : 'p'; let currentFenRows = fen.split(' ')[0].split('/'); let currentFenRow = currentFenRows[7 - squareCoords[1]]; let currentFenSquares = currentFenRow.split(''); let currentFenSquare = currentFenSquares[squareCoords[0]]; if (currentFenSquare.toUpperCase() !== 'P') { pieceMoved = currentFenSquare.toUpperCase(); } let capture = currentFenSquare !== '.'; if (pieceMoved === 'P' && capture) { file = String.fromCharCode(97 + squareCoords[0]); } let san = ${pieceMoved}${capture ? 'x' : ''}${file}${rank}; return san; } } }