Файловый менеджер - Редактировать - /home/gqdcvggs/izhak.me/chess.php
Назад
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Chess Game - Izhak</title> <script src="https://cdn.tailwindcss.com"></script> <link rel="icon" href="icon.png" type="image/png"> <link href="https://api.fontshare.com/v2/css?f[]=cabinet-grotesk@400,500,700,800&display=swap" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <style> :root { --bg-light: #ffffff; --bg-dark: #121212; --text-light: #121212; --text-dark: #f5f5f5; --border-light: rgba(0, 0, 0, 0.1); --border-dark: rgba(255, 255, 255, 0.1); } @media (prefers-color-scheme: dark) { body { background-color: var(--bg-dark); color: var(--text-dark); } .header-border { border-top: 1px solid var(--text-dark); border-bottom: 1px solid var(--text-dark); background-color: rgba(18, 18, 18, 0.8); } .border-custom { border-color: var(--border-dark); } .square-white { background-color: #f0d9b5; } .square-black { background-color: #b58863; } .game-panel { background-color: rgba(255, 255, 255, 0.05); border-color: var(--border-dark); } } @media (prefers-color-scheme: light) { body { background-color: var(--bg-light); color: var(--text-light); } .header-border { border-top: 1px solid var(--text-light); border-bottom: 1px solid var(--text-light); background-color: rgba(255, 255, 255, 0.8); } .border-custom { border-color: var(--border-light); } .square-white { background-color: #f0d9b5; } .square-black { background-color: #b58863; } .game-panel { background-color: rgba(0, 0, 0, 0.02); border-color: var(--border-light); } } body { font-family: 'Cabinet Grotesk', sans-serif; transition: background-color 0.3s ease, color 0.3s ease; margin: 0; padding: 0; } .header-border { backdrop-filter: blur(10px); } @keyframes slideUp { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } .slide-up { opacity: 0; animation: slideUp 0.6s cubic-bezier(0.4, 0, 0.2, 1) forwards; } .delay-1 {animation-delay: 0.1s;} .delay-2 {animation-delay: 0.2s;} .delay-3 {animation-delay: 0.3s;} .chess-board { display: grid; grid-template-columns: repeat(8, 1fr); grid-template-rows: repeat(8, 1fr); width: 100%; max-width: 500px; aspect-ratio: 1; border: 2px solid var(--border-light); border-radius: 0.5rem; overflow: hidden; margin: 0 auto; } @media (prefers-color-scheme: dark) { .chess-board { border-color: var(--border-dark); } } .chess-square { display: flex; align-items: center; justify-content: center; font-size: 2rem; cursor: pointer; transition: all 0.2s ease; position: relative; } .chess-square:hover { opacity: 0.8; } .chess-square.selected { box-shadow: inset 0 0 0 3px #22c55e; } .chess-square.possible-move { position: relative; } .chess-square.possible-move::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 20px; height: 20px; background-color: rgba(34, 197, 94, 0.6); border-radius: 50%; } .chess-square.last-move { box-shadow: inset 0 0 0 2px #fbbf24; } .button-custom { background-color: var(--text-light); color: var(--bg-light); padding: 1rem 2rem; border-radius: 2rem; font-size: 0.9rem; font-weight: 300; letter-spacing: 0.05em; transition: opacity 0.2s ease; text-decoration: none; display: inline-block; border: none; cursor: pointer; font-family: 'Cabinet Grotesk', sans-serif; margin: 0.5rem; } @media (prefers-color-scheme: dark) { .button-custom { background-color: var(--text-dark); color: var(--bg-dark); } } .button-custom:hover { opacity: 0.8; } .button-custom:disabled { opacity: 0.5; cursor: not-allowed; } .game-panel { border: 1px solid; border-radius: 0.75rem; padding: 1.5rem; margin: 1rem 0; } .game-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; flex-wrap: wrap; gap: 1rem; } .player-info { display: flex; align-items: center; gap: 0.5rem; font-weight: 500; } .player-info.active { color: #22c55e; } .move-history { max-height: 200px; overflow-y: auto; padding: 1rem; border: 1px solid var(--border-light); border-radius: 0.5rem; font-family: monospace; font-size: 0.9rem; line-height: 1.4; } @media (prefers-color-scheme: dark) { .move-history { border-color: var(--border-dark); background-color: rgba(255, 255, 255, 0.02); } } @media (prefers-color-scheme: light) { .move-history { background-color: rgba(0, 0, 0, 0.01); } } .game-container { display: grid; grid-template-columns: 1fr auto; gap: 2rem; max-width: 1200px; margin: 0 auto; padding: 2rem; } @media (max-width: 768px) { .game-container { grid-template-columns: 1fr; padding: 1rem; } } .status-message { padding: 1rem; border-radius: 0.5rem; margin: 1rem 0; font-weight: 500; text-align: center; } .status-check { background-color: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.3); color: #ef4444; } .status-checkmate { background-color: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.3); color: #ef4444; } .status-stalemate { background-color: rgba(156, 163, 175, 0.1); border: 1px solid rgba(156, 163, 175, 0.3); color: #6b7280; } .difficulty-selector { display: flex; gap: 0.5rem; margin: 1rem 0; flex-wrap: wrap; } .difficulty-btn { padding: 0.5rem 1rem; border: 1px solid var(--border-light); border-radius: 1rem; background: transparent; color: inherit; cursor: pointer; font-family: 'Cabinet Grotesk', sans-serif; font-size: 0.8rem; transition: all 0.2s ease; } @media (prefers-color-scheme: dark) { .difficulty-btn { border-color: var(--border-dark); } } .difficulty-btn.active { background-color: var(--text-light); color: var(--bg-light); } @media (prefers-color-scheme: dark) { .difficulty-btn.active { background-color: var(--text-dark); color: var(--bg-dark); } } </style> </head> <body class="min-h-screen"> <header class="header-border py-6 sticky top-0 z-50 slide-up"> <div class="max-width-1200px mx-auto px-6"> <div class="flex justify-between items-center"> <h1 class="text-2xl font-light tracking-tight">Izhak</h1> <a href="index.php" class="text-sm font-light hover:opacity-70 transition-opacity">← Back to Home</a> </div> </div> </header> <div class="game-container slide-up delay-1"> <div> <div class="text-center mb-8"> <h2 class="text-4xl md:text-5xl font-light tracking-tight mb-4">Chess Game</h2> <p class="text-lg font-light opacity-70">Play against the AI bot</p> </div> <div class="chess-board" id="chessBoard"></div> <div class="text-center mt-6"> <button onclick="newGame()" class="button-custom"> <i class="fas fa-redo mr-2"></i> New Game </button> <button onclick="undoMove()" class="button-custom" id="undoBtn" disabled> <i class="fas fa-undo mr-2"></i> Undo Move </button> </div> </div> <div style="width: 300px;"> <div class="game-panel"> <h3 class="text-xl font-light mb-4">Game Status</h3> <div class="game-info"> <div class="player-info" id="whitePlayer"> <i class="fas fa-user"></i> <span>You (White)</span> </div> <div class="player-info" id="blackPlayer"> <i class="fas fa-robot"></i> <span>Bot (Black)</span> </div> </div> <div id="gameStatus" class="text-center font-medium mb-4"> White to move </div> <div class="difficulty-selector"> <span class="text-sm opacity-70 mb-2 block w-full">Bot Difficulty:</span> <button class="difficulty-btn active" onclick="setDifficulty(1)" data-level="1">Easy</button> <button class="difficulty-btn" onclick="setDifficulty(2)" data-level="2">Medium</button> <button class="difficulty-btn" onclick="setDifficulty(3)" data-level="3">Hard</button> </div> <h4 class="text-lg font-light mb-2">Move History</h4> <div class="move-history" id="moveHistory"> Game started. Good luck! </div> </div> </div> </div> <footer class="py-8 text-center text-sm font-light opacity-50"> <p>Designed with a smile.</p> </footer> <script> class ChessGame { constructor() { this.board = this.initBoard(); this.currentPlayer = 'white'; this.selectedSquare = null; this.gameOver = false; this.moveHistory = []; this.botDifficulty = 1; this.lastMove = null; this.setupBoard(); this.updateDisplay(); } initBoard() { return [ ['♜','♞','♝','♛','♚','♝','♞','♜'], ['♟','♟','♟','♟','♟','♟','♟','♟'], [null,null,null,null,null,null,null,null], [null,null,null,null,null,null,null,null], [null,null,null,null,null,null,null,null], [null,null,null,null,null,null,null,null], ['♙','♙','♙','♙','♙','♙','♙','♙'], ['♖','♘','♗','♕','♔','♗','♘','♖'] ]; } setupBoard() { const boardElement = document.getElementById('chessBoard'); boardElement.innerHTML = ''; for (let row = 0; row < 8; row++) { for (let col = 0; col < 8; col++) { const square = document.createElement('div'); square.className = `chess-square ${(row + col) % 2 === 0 ? 'square-white' : 'square-black'}`; square.dataset.row = row; square.dataset.col = col; square.textContent = this.board[row][col] || ''; square.addEventListener('click', () => this.handleSquareClick(row, col)); boardElement.appendChild(square); } } } handleSquareClick(row, col) { if (this.gameOver || this.currentPlayer === 'black') return; const piece = this.board[row][col]; const isWhitePiece = piece && this.isWhitePiece(piece); if (this.selectedSquare) { const [selectedRow, selectedCol] = this.selectedSquare; if (row === selectedRow && col === selectedCol) { this.selectedSquare = null; } else if (this.isValidMove(selectedRow, selectedCol, row, col)) { this.makeMove(selectedRow, selectedCol, row, col); this.selectedSquare = null; if (!this.gameOver) { setTimeout(() => this.makeBotMove(), 500); } } else if (isWhitePiece) { this.selectedSquare = [row, col]; } else { this.selectedSquare = null; } } else { if (isWhitePiece) { this.selectedSquare = [row, col]; } } this.updateDisplay(); } isWhitePiece(piece) { return '♔♕♖♗♘♙'.includes(piece); } isBlackPiece(piece) { return '♚♛♜♝♞♟'.includes(piece); } isValidMove(fromRow, fromCol, toRow, toCol) { if (toRow < 0 || toRow >= 8 || toCol < 0 || toCol >= 8) return false; const piece = this.board[fromRow][fromCol]; const targetPiece = this.board[toRow][toCol]; if (!piece) return false; if (targetPiece && this.isSameColor(piece, targetPiece)) return false; return this.isValidPieceMove(piece, fromRow, fromCol, toRow, toCol); } isSameColor(piece1, piece2) { return (this.isWhitePiece(piece1) && this.isWhitePiece(piece2)) || (this.isBlackPiece(piece1) && this.isBlackPiece(piece2)); } isValidPieceMove(piece, fromRow, fromCol, toRow, toCol) { const rowDiff = toRow - fromRow; const colDiff = toCol - fromCol; const absRowDiff = Math.abs(rowDiff); const absColDiff = Math.abs(colDiff); switch (piece) { case '♙': // White pawn if (colDiff === 0) { if (rowDiff === -1 && !this.board[toRow][toCol]) return true; if (fromRow === 6 && rowDiff === -2 && !this.board[toRow][toCol]) return true; } else if (absColDiff === 1 && rowDiff === -1 && this.board[toRow][toCol]) { return true; } break; case '♟': // Black pawn if (colDiff === 0) { if (rowDiff === 1 && !this.board[toRow][toCol]) return true; if (fromRow === 1 && rowDiff === 2 && !this.board[toRow][toCol]) return true; } else if (absColDiff === 1 && rowDiff === 1 && this.board[toRow][toCol]) { return true; } break; case '♖': case '♜': // Rook if (rowDiff === 0 || colDiff === 0) { return this.isPathClear(fromRow, fromCol, toRow, toCol); } break; case '♗': case '♝': // Bishop if (absRowDiff === absColDiff) { return this.isPathClear(fromRow, fromCol, toRow, toCol); } break; case '♕': case '♛': // Queen if (rowDiff === 0 || colDiff === 0 || absRowDiff === absColDiff) { return this.isPathClear(fromRow, fromCol, toRow, toCol); } break; case '♔': case '♚': // King if (absRowDiff <= 1 && absColDiff <= 1) return true; break; case '♘': case '♞': // Knight if ((absRowDiff === 2 && absColDiff === 1) || (absRowDiff === 1 && absColDiff === 2)) { return true; } break; } return false; } isPathClear(fromRow, fromCol, toRow, toCol) { const rowStep = toRow === fromRow ? 0 : (toRow > fromRow ? 1 : -1); const colStep = toCol === fromCol ? 0 : (toCol > fromCol ? 1 : -1); let currentRow = fromRow + rowStep; let currentCol = fromCol + colStep; while (currentRow !== toRow || currentCol !== toCol) { if (this.board[currentRow][currentCol]) return false; currentRow += rowStep; currentCol += colStep; } return true; } makeMove(fromRow, fromCol, toRow, toCol) { const piece = this.board[fromRow][fromCol]; const capturedPiece = this.board[toRow][toCol]; this.moveHistory.push({ from: [fromRow, fromCol], to: [toRow, toCol], piece: piece, captured: capturedPiece, player: this.currentPlayer }); this.board[toRow][toCol] = piece; this.board[fromRow][fromCol] = null; this.lastMove = [fromRow, fromCol, toRow, toCol]; this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white'; this.checkGameEnd(); this.updateMoveHistory(); } makeBotMove() { if (this.gameOver || this.currentPlayer !== 'black') return; const possibleMoves = this.getAllPossibleMoves('black'); if (possibleMoves.length === 0) { this.gameOver = true; return; } let bestMove; switch (this.botDifficulty) { case 1: // Easy - random move bestMove = possibleMoves[Math.floor(Math.random() * possibleMoves.length)]; break; case 2: // Medium - prefer captures const captures = possibleMoves.filter(move => this.board[move.to[0]][move.to[1]]); bestMove = captures.length > 0 ? captures[Math.floor(Math.random() * captures.length)] : possibleMoves[Math.floor(Math.random() * possibleMoves.length)]; break; case 3: // Hard - simple evaluation bestMove = this.getBestMove(possibleMoves); break; } if (bestMove) { this.makeMove(bestMove.from[0], bestMove.from[1], bestMove.to[0], bestMove.to[1]); this.updateDisplay(); } } getAllPossibleMoves(color) { const moves = []; for (let row = 0; row < 8; row++) { for (let col = 0; col < 8; col++) { const piece = this.board[row][col]; if (piece && ((color === 'white' && this.isWhitePiece(piece)) || (color === 'black' && this.isBlackPiece(piece)))) { for (let toRow = 0; toRow < 8; toRow++) { for (let toCol = 0; toCol < 8; toCol++) { if (this.isValidMove(row, col, toRow, toCol)) { moves.push({ from: [row, col], to: [toRow, toCol], piece: piece, capture: this.board[toRow][toCol] }); } } } } } } return moves; } getBestMove(moves) { const pieceValues = { '♙': 1, '♟': -1, '♘': 3, '♞': -3, '♗': 3, '♝': -3, '♖': 5, '♜': -5, '♕': 9, '♛': -9, '♔': 100, '♚': -100 }; let bestScore = -Infinity; let bestMove = moves[0]; for (const move of moves) { let score = 0; if (move.capture) { score += Math.abs(pieceValues[move.capture] || 0); } score += Math.random() * 0.5; if (score > bestScore) { bestScore = score; bestMove = move; } } return bestMove; } checkGameEnd() { const moves = this.getAllPossibleMoves(this.currentPlayer); if (moves.length === 0) { this.gameOver = true; const winner = this.currentPlayer === 'white' ? 'Black' : 'White'; document.getElementById('gameStatus').innerHTML = `<div class="status-checkmate">Checkmate! ${winner} wins!</div>`; } } updateDisplay() { this.setupBoard(); if (this.selectedSquare) { const [row, col] = this.selectedSquare; const square = document.querySelector(`[data-row="${row}"][data-col="${col}"]`); square.classList.add('selected'); for (let r = 0; r < 8; r++) { for (let c = 0; c < 8; c++) { if (this.isValidMove(row, col, r, c)) { const moveSquare = document.querySelector(`[data-row="${r}"][data-col="${c}"]`); moveSquare.classList.add('possible-move'); } } } } if (this.lastMove) { const [fromRow, fromCol, toRow, toCol] = this.lastMove; document.querySelector(`[data-row="${fromRow}"][data-col="${fromCol}"]`).classList.add('last-move'); document.querySelector(`[data-row="${toRow}"][data-col="${toCol}"]`).classList.add('last-move'); } document.getElementById('whitePlayer').classList.toggle('active', this.currentPlayer === 'white'); document.getElementById('blackPlayer').classList.toggle('active', this.currentPlayer === 'black'); if (!this.gameOver) { document.getElementById('gameStatus').textContent = this.currentPlayer === 'white' ? 'Your turn' : 'Bot is thinking...'; } document.getElementById('undoBtn').disabled = this.moveHistory.length === 0; } updateMoveHistory() { const historyElement = document.getElementById('moveHistory'); if (this.moveHistory.length === 0) { historyElement.textContent = 'Game started. Good luck!'; return; } let historyText = ''; for (let i = 0; i < this.moveHistory.length; i += 2) { const moveNumber = Math.floor(i / 2) + 1; const whiteMove = this.moveHistory[i]; const blackMove = this.moveHistory[i + 1]; let moveText = `${moveNumber}. ${this.formatMove(whiteMove)}`; if (blackMove) { moveText += ` ${this.formatMove(blackMove)}`; } historyText += moveText + '\n'; } historyElement.textContent = historyText; historyElement.scrollTop = historyElement.scrollHeight; } formatMove(move) { const files = 'abcdefgh'; const ranks = '87654321'; const fromSquare = files[move.from[1]] + ranks[move.from[0]]; const toSquare = files[move.to[1]] + ranks[move.to[0]]; const capture = move.captured ? 'x' : ''; return `${move.piece}${capture}${toSquare}`; } newGame() { this.board = this.initBoard(); this.currentPlayer = 'white'; this.selectedSquare = null; this.gameOver = false; this.moveHistory = []; this.lastMove = null; this.updateDisplay(); this.updateMoveHistory(); document.getElementById('gameStatus').textContent = 'White to move'; } undoMove() { if (this.moveHistory.length === 0) return; const lastMove = this.moveHistory.pop(); this.board[lastMove.from[0]][lastMove.from[1]] = lastMove.piece; this.board[lastMove.to[0]][lastMove.to[1]] = lastMove.captured; if (this.moveHistory.length > 0) { const prevMove = this.moveHistory[this.moveHistory.length - 1]; this.lastMove = [prevMove.from[0], prevMove.from[1], prevMove.to[0], prevMove.to[1]]; } else { this.lastMove = null; } this.currentPlayer = lastMove.player; this.gameOver = false; this.selectedSquare = null; this.updateDisplay(); this.updateMoveHistory(); document.getElementById('gameStatus').textContent = this.currentPlayer === 'white' ? 'Your turn' : 'Bot turn'; } setDifficulty(level) { this.botDifficulty = level; document.querySelectorAll('.difficulty-btn').forEach(btn => { btn.classList.remove('active'); }); document.querySelector(`[data-level="${level}"]`).classList.add('active'); } } let game; function newGame() { game = new ChessGame(); } function undoMove() { game.undoMove(); } function setDifficulty(level) { game.setDifficulty(level); } window.onload = function() { game = new ChessGame(); }; </script> </body> </html>
| ver. 1.6 |
Github
|
.
| PHP 8.1.33 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка