Back to Game

Checkers - Source Code

Play Game
JavaScript
const BOARD_SIZE = 8;
let board = initializeBoard();
let currentPlayer = 1;
let selectedSquare = null;

function initializeBoard() {
  const board = Array(BOARD_SIZE).fill().map(() => Array(BOARD_SIZE).fill(null));
  
  for (let row = 0; row < 3; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if ((row + col) % 2 === 1) {
        board[row][col] = { player: 1, isKing: false };
      }
    }
  }
  
  for (let row = 5; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      if ((row + col) % 2 === 1) {
        board[row][col] = { player: 2, isKing: false };
      }
    }
  }
  
  return board;
}

function minimax(board, depth, isMaximizing, alpha, beta) {
  if (depth === 0) {
    return evaluateBoard(board);
  }
  
  const moves = getAllPossibleMoves(board, isMaximizing ? 2 : 1);
  
  if (moves.length === 0) {
    return isMaximizing ? -1000 : 1000;
  }
  
  if (isMaximizing) {
    let maxEval = -Infinity;
    for (const move of moves) {
      const newBoard = makeMove(board, move);
      const eval = minimax(newBoard, depth - 1, false, alpha, beta);
      maxEval = Math.max(maxEval, eval);
      alpha = Math.max(alpha, eval);
      if (beta <= alpha) break;
    }
    return maxEval;
  } else {
    let minEval = Infinity;
    for (const move of moves) {
      const newBoard = makeMove(board, move);
      const eval = minimax(newBoard, depth - 1, true, alpha, beta);
      minEval = Math.min(minEval, eval);
      beta = Math.min(beta, eval);
      if (beta <= alpha) break;
    }
    return minEval;
  }
}

function evaluateBoard(board) {
  let score = 0;
  
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      const piece = board[row][col];
      if (piece) {
        let pieceValue = piece.isKing ? 5 : 1;
        
        if (piece.player === 1) {
          pieceValue += (BOARD_SIZE - 1 - row) * 0.1;
        } else {
          pieceValue += row * 0.1;
        }
        
        if (row === 0 || row === BOARD_SIZE - 1 || col === 0 || col === BOARD_SIZE - 1) {
          pieceValue += 0.5;
        }
        
        score += piece.player === 2 ? pieceValue : -pieceValue;
      }
    }
  }
  
  return score;
}

function getAllPossibleMoves(board, player) {
  const moves = [];
  
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      const piece = board[row][col];
      if (piece && piece.player === player) {
        const pieceMoves = getPossibleMoves(board, row, col, piece);
        pieceMoves.forEach(move => {
          moves.push({
            from: { row, col },
            to: move,
            piece: piece
          });
        });
      }
    }
  }
  
  return moves;
}

function getPossibleMoves(board, row, col, piece) {
  const moves = [];
  const directions = piece.isKing ? 
    [[-1, -1], [-1, 1], [1, -1], [1, 1]] :
    piece.player === 1 ? [[1, -1], [1, 1]] : [[-1, -1], [-1, 1]];
  
  for (const [dRow, dCol] of directions) {
    const newRow = row + dRow;
    const newCol = col + dCol;
    
    if (newRow >= 0 && newRow < BOARD_SIZE && newCol >= 0 && newCol < BOARD_SIZE) {
      if (!board[newRow][newCol]) {
        moves.push({ row: newRow, col: newCol });
      } else if (board[newRow][newCol].player !== piece.player) {
        const jumpRow = newRow + dRow;
        const jumpCol = newCol + dCol;
        if (jumpRow >= 0 && jumpRow < BOARD_SIZE && jumpCol >= 0 && jumpCol < BOARD_SIZE && !board[jumpRow][jumpCol]) {
          moves.push({ row: jumpRow, col: jumpCol });
        }
      }
    }
  }
  
  return moves;
}

function makeMove(board, move) {
  const newBoard = board.map(row => [...row]);
  const piece = newBoard[move.from.row][move.from.col];
  
  newBoard[move.to.row][move.to.col] = piece;
  newBoard[move.from.row][move.from.col] = null;
  
  const rowDiff = Math.abs(move.to.row - move.from.row);
  if (rowDiff === 2) {
    const jumpedRow = (move.to.row + move.from.row) / 2;
    const jumpedCol = (move.to.col + move.from.col) / 2;
    newBoard[jumpedRow][jumpedCol] = null;
  }
  
  if ((piece.player === 1 && move.to.row === BOARD_SIZE - 1) || 
      (piece.player === 2 && move.to.row === 0)) {
    newBoard[move.to.row][move.to.col].isKing = true;
  }
  
  return newBoard;
}

function getBestMove() {
  const moves = getAllPossibleMoves(board, 2);
  let bestScore = -Infinity;
  let bestMove = moves[0];
  
  for (const move of moves) {
    const newBoard = makeMove(board, move);
    const score = minimax(newBoard, 4, false, -Infinity, Infinity);
    
    if (score > bestScore) {
      bestScore = score;
      bestMove = move;
    }
  }
  
  return bestMove;
}

function handleSquareClick(row, col) {
  const piece = board[row][col];
  
  if (selectedSquare) {
    const moves = getPossibleMoves(board, selectedSquare.row, selectedSquare.col, 
      board[selectedSquare.row][selectedSquare.col]);
    const isValidMove = moves.some(move => move.row === row && move.col === col);
    
    if (isValidMove) {
      const move = {
        from: selectedSquare,
        to: { row, col },
        piece: board[selectedSquare.row][selectedSquare.col]
      };
      
      board = makeMove(board, move);
      selectedSquare = null;
      currentPlayer = 2;
      
      setTimeout(() => {
        const aiMove = getBestMove();
        if (aiMove) {
          board = makeMove(board, aiMove);
          currentPlayer = 1;
        }
      }, 500);
    } else {
      selectedSquare = null;
    }
  } else if (piece && piece.player === currentPlayer && currentPlayer === 1) {
    selectedSquare = { row, col };
  }
  
  updateDisplay();
}

function updateDisplay() {
  const boardElement = document.getElementById('checkers-board');
  boardElement.innerHTML = '';
  
  for (let row = 0; row < BOARD_SIZE; row++) {
    for (let col = 0; col < BOARD_SIZE; col++) {
      const square = document.createElement('div');
      square.className = `square ${(row + col) % 2 === 0 ? 'light' : 'dark'}`;
      square.onclick = () => handleSquareClick(row, col);
      
      const piece = board[row][col];
      if (piece) {
        const pieceElement = document.createElement('div');
        pieceElement.className = `piece player${piece.player} ${piece.isKing ? 'king' : ''}`;
        square.appendChild(pieceElement);
      }
      
      boardElement.appendChild(square);
    }
  }
}

updateDisplay();

This code demonstrates the core game logic. The actual implementation may include additional features and optimizations.