chess / index.html
openfree's picture
Update index.html
a5aa9e1 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chess Game</title>
<style>
:root {
--light-square: #f0d9b5;
--dark-square: #b58863;
--highlight: rgba(255, 255, 0, 0.4);
--possible-move: rgba(0, 255, 0, 0.3);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #2c3e50;
font-family: Arial, sans-serif;
}
.game-container {
display: flex;
gap: 2rem;
padding: 1rem;
background: #34495e;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
}
.board {
width: 560px;
height: 560px;
display: grid;
grid-template-columns: repeat(8, 1fr);
border: 3px solid #111;
}
.square {
width: 70px;
height: 70px;
display: flex;
justify-content: center;
align-items: center;
font-size: 45px;
cursor: pointer;
position: relative;
}
.light {
background-color: var(--light-square);
}
.dark {
background-color: var(--dark-square);
}
.highlight {
background-color: var(--highlight);
}
.possible-move::after {
content: '';
position: absolute;
width: 25px;
height: 25px;
background: var(--possible-move);
border-radius: 50%;
}
.game-info {
color: white;
padding: 1rem;
width: 200px;
}
.status {
margin-bottom: 1rem;
padding: 1rem;
background: #2c3e50;
border-radius: 5px;
}
.captured {
margin-top: 1rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.piece {
user-select: none;
}
@media (max-width: 800px) {
.game-container {
flex-direction: column;
}
.board {
width: 400px;
height: 400px;
}
.square {
width: 50px;
height: 50px;
font-size: 35px;
}
}
</style>
</head>
<body>
<div class="game-container">
<div class="board" id="board"></div>
<div class="game-info">
<div class="status" id="status">White's turn</div>
<div>Captured pieces:</div>
<div class="captured" id="captured"></div>
</div>
</div>
<script>
class ChessGame {
constructor() {
this.board = document.getElementById('board');
this.status = document.getElementById('status');
this.captured = document.getElementById('captured');
this.selectedPiece = null;
this.currentPlayer = 'white';
this.possibleMoves = [];
this.gameBoard = this.initializeBoard();
this.createBoard();
this.capturedPieces = [];
}
initializeBoard() {
return [
['♜', '♞', '♝', '♛', '♚', '♝', '♞', '♜'],
['♟', '♟', '♟', '♟', '♟', '♟', '♟', '♟'],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['♙', '♙', '♙', '♙', '♙', '♙', '♙', '♙'],
['♖', '♘', '♗', '♕', '♔', '♗', '♘', '♖']
];
}
createBoard() {
this.board.innerHTML = '';
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const square = document.createElement('div');
square.classList.add('square');
square.classList.add((row + col) % 2 === 0 ? 'light' : 'dark');
const piece = this.gameBoard[row][col];
if (piece) {
square.innerHTML = `<span class="piece">${piece}</span>`;
}
square.dataset.row = row;
square.dataset.col = col;
square.addEventListener('click', (e) => this.handleSquareClick(e));
this.board.appendChild(square);
}
}
}
isPieceWhite(piece) {
return '♔♕♖♗♘♙'.includes(piece);
}
handleSquareClick(e) {
const square = e.target.closest('.square');
const row = parseInt(square.dataset.row);
const col = parseInt(square.dataset.col);
const piece = this.gameBoard[row][col];
if (this.currentPlayer === 'black') return; // Prevent moves during AI turn
if (this.selectedPiece) {
if (this.possibleMoves.some(move => move.row === row && move.col === col)) {
this.movePiece(row, col);
this.clearHighlights();
this.selectedPiece = null;
this.possibleMoves = [];
// AI move
setTimeout(() => this.makeAIMove(), 500);
} else {
this.clearHighlights();
this.selectedPiece = null;
this.possibleMoves = [];
}
} else if (piece && this.isPieceWhite(piece) === (this.currentPlayer === 'white')) {
this.selectedPiece = { row, col, piece };
this.highlightSquare(row, col);
this.possibleMoves = this.calculatePossibleMoves(row, col, piece);
this.showPossibleMoves();
}
}
clearHighlights() {
document.querySelectorAll('.square').forEach(square => {
square.classList.remove('highlight', 'possible-move');
});
}
highlightSquare(row, col) {
const square = this.getSquare(row, col);
square.classList.add('highlight');
}
showPossibleMoves() {
this.possibleMoves.forEach(move => {
const square = this.getSquare(move.row, move.col);
square.classList.add('possible-move');
});
}
getSquare(row, col) {
return this.board.children[row * 8 + col];
}
calculatePossibleMoves(row, col, piece) {
const moves = [];
// Pawn moves
if (piece === '♙') {
// Forward move
if (row > 0 && !this.gameBoard[row-1][col]) {
moves.push({row: row-1, col: col});
// Initial two-square move
if (row === 6 && !this.gameBoard[row-2][col]) {
moves.push({row: row-2, col: col});
}
}
// Diagonal captures
if (row > 0 && col > 0 && this.gameBoard[row-1][col-1] && !this.isPieceWhite(this.gameBoard[row-1][col-1])) {
moves.push({row: row-1, col: col-1});
}
if (row > 0 && col < 7 && this.gameBoard[row-1][col+1] && !this.isPieceWhite(this.gameBoard[row-1][col+1])) {
moves.push({row: row-1, col: col+1});
}
}
// Basic moves for other pieces (simplified)
if ('♖♜'.includes(piece)) { // Rook
moves.push(...this.getRookMoves(row, col));
}
if ('♗♝'.includes(piece)) { // Bishop
moves.push(...this.getBishopMoves(row, col));
}
if ('♕♛'.includes(piece)) { // Queen
moves.push(...this.getRookMoves(row, col));
moves.push(...this.getBishopMoves(row, col));
}
if ('♘♞'.includes(piece)) { // Knight
const knightMoves = [
{row: row-2, col: col-1}, {row: row-2, col: col+1},
{row: row-1, col: col-2}, {row: row-1, col: col+2},
{row: row+1, col: col-2}, {row: row+1, col: col+2},
{row: row+2, col: col-1}, {row: row+2, col: col+1}
];
moves.push(...knightMoves.filter(move =>
move.row >= 0 && move.row < 8 && move.col >= 0 && move.col < 8 &&
(!this.gameBoard[move.row][move.col] ||
this.isPieceWhite(this.gameBoard[move.row][move.col]) !== this.isPieceWhite(piece))
));
}
if ('♔♚'.includes(piece)) { // King
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
if (i === 0 && j === 0) continue;
const newRow = row + i;
const newCol = col + j;
if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8 &&
(!this.gameBoard[newRow][newCol] ||
this.isPieceWhite(this.gameBoard[newRow][newCol]) !== this.isPieceWhite(piece))) {
moves.push({row: newRow, col: newCol});
}
}
}
}
return moves;
}
getRookMoves(row, col) {
const moves = [];
const directions = [[0,1], [0,-1], [1,0], [-1,0]];
for (let [dx, dy] of directions) {
let x = row + dx;
let y = col + dy;
while (x >= 0 && x < 8 && y >= 0 && y < 8) {
if (!this.gameBoard[x][y]) {
moves.push({row: x, col: y});
} else {
if (this.isPieceWhite(this.gameBoard[x][y]) !== this.isPieceWhite(this.gameBoard[row][col])) {
moves.push({row: x, col: y});
}
break;
}
x += dx;
y += dy;
}
}
return moves;
}
getBishopMoves(row, col) {
const moves = [];
const directions = [[1,1], [1,-1], [-1,1], [-1,-1]];
for (let [dx, dy] of directions) {
let x = row + dx;
let y = col + dy;
while (x >= 0 && x < 8 && y >= 0 && y < 8) {
if (!this.gameBoard[x][y]) {
moves.push({row: x, col: y});
} else {
if (this.isPieceWhite(this.gameBoard[x][y]) !== this.isPieceWhite(this.gameBoard[row][col])) {
moves.push({row: x, col: y});
}
break;
}
x += dx;
y += dy;
}
}
return moves;
}
movePiece(toRow, toCol) {
const fromRow = this.selectedPiece.row;
const fromCol = this.selectedPiece.col;
// Capture logic
if (this.gameBoard[toRow][toCol]) {
this.capturedPieces.push(this.gameBoard[toRow][toCol]);
this.updateCapturedPieces();
}
this.gameBoard[toRow][toCol] = this.gameBoard[fromRow][fromCol];
this.gameBoard[fromRow][fromCol] = '';
this.currentPlayer = this.currentPlayer === 'white' ? 'black' : 'white';
this.status.textContent = `${this.currentPlayer.charAt(0).toUpperCase() + this.currentPlayer.slice(1)}'s turn`;
this.createBoard();
}
updateCapturedPieces() {
this.captured.innerHTML = this.capturedPieces.map(piece =>
`<span class="piece">${piece}</span>`
).join('');
}
makeAIMove() {
// Simple AI: randomly select a valid move
let possibleAIMoves = [];
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const piece = this.gameBoard[row][col];
if (piece && !this.isPieceWhite(piece)) {
const moves = this.calculatePossibleMoves(row, col, piece);
moves.forEach(move => {
possibleAIMoves.push({
from: {row, col},
to: move
});
});
}
}
}
if (possibleAIMoves.length > 0) {
const move = possibleAIMoves[Math.floor(Math.random() * possibleAIMoves.length)];
this.selectedPiece = {
row: move.from.row,
col: move.from.col,
piece: this.gameBoard[move.from.row][move.from.col]
};
this.movePiece(move.to.row, move.to.col);
}
}
}
// Start the game
const game = new ChessGame();
</script>
</body>
</html>