Dame-Spiel / damelogic.js
Sebastiankay's picture
Create damelogic.js
de7d29f verified
const boardSize = 8;
let board = [],
currentPlayer = 1
selectedPiece = null,
validMoves = [],
gameRunning = false,
vsCPU = false;
const playerColors = {
1: "168, 208, 230",
2: "246, 171, 182",
};
let players = {
1: { name: "Spieler 1", color: "168, 208, 230" },
2: { name: "Spieler 2", color: "246, 171, 182" },
};
const captureHighlightColors = {
1: "128, 168, 190",
2: "206, 131, 142",
};
const pieceColors = {
1: "77, 129, 199",
2: "214, 106, 139",
};
const body = document.body;
body.style.setProperty("--player1-color", players[1].color);
body.style.setProperty("--player2-color", players[2].color);
const inputPlayerName1 = document.getElementById("inputPlayerName1");
inputPlayerName1.value = players[1].name;
const inputPlayerName2 = document.getElementById("inputPlayerName2");
inputPlayerName2.value = players[2].name;
const savePlayerNamesButton = document.getElementById("savePlayerNames");
const boardElement = document.getElementById("board");
const statusElement = document.getElementById("status");
const newGameButton = document.getElementById("new-game");
const winMessageElement = document.getElementById("winMessage");
const cpuToggle = document.getElementById("cpuToggle");
function inBounds(row, col) {
return row >= 0 && row < boardSize && col >= 0 && col < boardSize;
}
function isEmpty(row, col) {
return board[row][col] === 0;
}
function isOpponent(piece, player) {
return piece !== 0 && (player === 1 ? piece === 2 || piece === 4 : piece === 1 || piece === 3);
}
function isPlayerPiece(piece, player) {
return player === 1 ? piece === 1 || piece === 3 : player === 2 && (piece === 2 || piece === 4);
}
function isKing(piece) {
return piece === 3 || piece === 4;
}
function initGame() {
board = Array.from({ length: boardSize }, () => Array(boardSize).fill(0));
for (let row = 0; row < 3; row++) {
for (let col = 0; col < boardSize; col++) {
if ((row + col) % 2 === 1) board[row][col] = 1;
}
}
for (let row = boardSize - 3; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
if ((row + col) % 2 === 1) board[row][col] = 2;
}
}
currentPlayer = 1;
selectedPiece = null;
validMoves = [];
gameRunning = true;
winMessageElement.style.display = "none";
newGameButton.style.display = "inline-block";
vsCPU = cpuToggle.checked;
cpuToggle.disabled = false;
updateStatus();
updateBackground();
renderBoard();
if (vsCPU && currentPlayer === 2) {
setTimeout(cpuMove, 500);
}
}
function updateStatus() {
statusElement.textContent = `${players[currentPlayer].name} ist am Zug`;
}
function updateBackground() {
body.style.setProperty("--active-background-color", players[currentPlayer].color);
}
function getValidMoves(row, col) {
const moves = [];
const piece = board[row][col];
if (!isPlayerPiece(piece, currentPlayer)) return moves;
const directions = isKing(piece)
? [[1, 1], [1, -1], [-1, 1], [-1, -1]]
: currentPlayer === 1
? [[1, -1], [1, 1]]
: [[-1, -1], [-1, 1]];
directions.forEach(([dr, dc]) => {
const newRow = row + dr, newCol = col + dc;
if (inBounds(newRow, newCol) && isEmpty(newRow, newCol)) {
moves.push({ row: newRow, col: newCol, capture: false });
}
const captureRow = row + 2 * dr, captureCol = col + 2 * dc;
if (inBounds(newRow, newCol) && inBounds(captureRow, captureCol) && isOpponent(board[newRow][newCol], currentPlayer) && isEmpty(captureRow, captureCol)) {
moves.push({ row: captureRow, col: captureCol, capture: true, captured: { row: newRow, col: newCol } });
}
});
return moves;
}
function getValidMovesForPlayer(row, col, player) {
const moves = [];
const piece = board[row][col];
if (!isPlayerPiece(piece, player)) return moves;
const directions = isKing(piece)
? [[1, 1], [1, -1], [-1, 1], [-1, -1]]
: player === 1
? [[1, -1], [1, 1]]
: [[-1, -1], [-1, 1]];
directions.forEach(([dr, dc]) => {
const newRow = row + dr, newCol = col + dc;
if (inBounds(newRow, newCol) && isEmpty(newRow, newCol)) {
moves.push({ row: newRow, col: newCol, capture: false });
}
const captureRow = row + 2 * dr, captureCol = col + 2 * dc;
if (inBounds(newRow, newCol) && inBounds(captureRow, captureCol) && isOpponent(board[newRow][newCol], player) && isEmpty(captureRow, captureCol)) {
moves.push({ row: captureRow, col: captureCol, capture: true, captured: { row: newRow, col: newCol } });
}
});
return moves;
}
function hasAnyMoves(player) {
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
if (isPlayerPiece(board[row][col], player) && getValidMovesForPlayer(row, col, player).length > 0) {
return true;
}
}
}
return false;
}
function hasAnyCapture() {
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
if (isPlayerPiece(board[row][col], currentPlayer) && getValidMoves(row, col).some(move => move.capture)) {
return true;
}
}
}
return false;
}
function makeMove(fromRow, fromCol, move) {
board[move.row][move.col] = board[fromRow][fromCol];
board[fromRow][fromCol] = 0;
if (move.capture) {
const captured = move.captured;
board[captured.row][captured.col] = 0;
}
if (currentPlayer === 1 && move.row === boardSize - 1 && board[move.row][move.col] === 1) {
board[move.row][move.col] = 3;
} else if (currentPlayer === 2 && move.row === 0 && board[move.row][move.col] === 2) {
board[move.row][move.col] = 4;
}
}
function switchPlayer() {
currentPlayer = currentPlayer === 1 ? 2 : 1;
selectedPiece = null;
renderBoard();
validMoves = [];
updateStatus();
updateBackground();
if (hasAnyMoves(currentPlayer)) {
if (vsCPU && currentPlayer === 2) {
setTimeout(cpuMove, 500);
}
} else {
endGame(currentPlayer === 1 ? 2 : 1);
}
}
function cpuMove() {
let possibleMoves = [];
const mustCapture = hasAnyCapture();
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
if (isPlayerPiece(board[row][col], currentPlayer)) {
let moves = getValidMoves(row, col);
if (mustCapture) {
moves = moves.filter(move => move.capture);
}
if (moves.length > 0) {
possibleMoves.push({ row, col, moves });
}
}
}
}
if (possibleMoves.length === 0) {
endGame(currentPlayer === 1 ? 2 : 1);
return;
}
const { row, col, moves } = possibleMoves[Math.floor(Math.random() * possibleMoves.length)];
const move = moves[Math.floor(Math.random() * moves.length)];
setTimeout(() => {
makeMove(row, col, move);
renderBoard();
if (move.capture) {
cpuCaptureChain(move.row, move.col);
} else {
checkWin() || switchPlayer();
}
}, 500);
}
function cpuCaptureChain(row, col) {
let captureMoves = getValidMoves(row, col).filter(move => move.capture);
if (captureMoves.length > 0) {
const move = captureMoves[Math.floor(Math.random() * captureMoves.length)];
setTimeout(() => {
makeMove(row, col, move);
renderBoard();
cpuCaptureChain(move.row, move.col);
}, 500);
} else {
checkWin() || switchPlayer();
}
}
function checkWin() {
let player1Pieces = 0, player2Pieces = 0;
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
if (board[row][col] === 1 || board[row][col] === 3) {
player1Pieces++;
} else if (board[row][col] === 2 || board[row][col] === 4) {
player2Pieces++;
}
}
}
if (player1Pieces === 0) {
endGame(2);
return true;
} else if (player2Pieces === 0) {
endGame(1);
return true;
} else if (!hasAnyMoves(currentPlayer === 1 ? 2 : 1)) {
endGame(currentPlayer);
return true;
}
return false;
}
function endGame(winner) {
gameRunning = false;
newGameButton.style.display = "none";
winMessageElement.textContent = `Spieler ${winner} hat gewonnen! (Zum Neustart klicken)`;
winMessageElement.style.display = "block";
winMessageElement.style.backgroundColor = `rgba(${players[winner].color}, 1.0)`;
cpuToggle.disabled = false;
winMessageElement.addEventListener("click", initGame, { once: true });
}
function renderBoard() {
boardElement.innerHTML = "";
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
const cell = document.createElement("div");
cell.classList.add("cell");
cell.classList.add((row + col) % 2 === 0 ? "light" : "dark");
cell.dataset.row = row;
cell.dataset.col = col;
if (validMoves.some(move => move.row === row && move.col === col)) {
cell.classList.add("highlight");
}
if (selectedPiece && selectedPiece.row === row && selectedPiece.col === col) {
cell.classList.add("selected");
}
const piece = board[row][col];
if (piece !== 0) {
const pieceElement = document.createElement("div");
pieceElement.classList.add("piece");
pieceElement.style.setProperty("--player-color", players[piece % 2 === 0 ? 2 : 1].color);
if (isKing(piece)) {
pieceElement.classList.add("king");
}
if (getValidMoves(row, col).some(move => move.capture)) {
pieceElement.classList.add("must-capture");
} else {
pieceElement.classList.remove("must-capture");
}
cell.appendChild(pieceElement);
}
cell.addEventListener("click", handleCellClick);
boardElement.appendChild(cell);
}
}
}
function handleCellClick(event) {
if (!gameRunning || (vsCPU && currentPlayer === 2)) return;
const row = parseInt(event.currentTarget.dataset.row);
const col = parseInt(event.currentTarget.dataset.col);
if (selectedPiece) {
const move = validMoves.find(move => move.row === row && move.col === col);
if (move) {
makeMove(selectedPiece.row, selectedPiece.col, move);
renderBoard();
if (move.capture) {
const captureMoves = getValidMoves(move.row, move.col).filter(move => move.capture);
if (captureMoves.length > 0) {
selectedPiece = { row: move.row, col: move.col };
validMoves = captureMoves;
return;
}
}
selectedPiece = null;
validMoves = [];
checkWin() || switchPlayer();
return;
}
}
if (isPlayerPiece(board[row][col], currentPlayer)) {
if (hasAnyCapture()) {
const captureMoves = getValidMoves(row, col).filter(move => move.capture);
if (captureMoves.length === 0) return;
selectedPiece = { row, col };
validMoves = captureMoves;
} else {
selectedPiece = { row, col };
validMoves = getValidMoves(row, col);
}
renderBoard();
}
}
function openSavePlayerNamesDialog() {
if (!cpuToggle.checked) {
inputPlayerName2.value = inputPlayerName2.value === "CPU" ? "Spieler 2" : inputPlayerName2.value;
} else {
inputPlayerName2.value = "CPU";
}
inputPlayerName2.disabled = cpuToggle.checked;
document.getElementById("setPlayerNamesWrapperBackdrop").style.display = "block";
}
savePlayerNamesButton.addEventListener("click", () => {
players[1].name = inputPlayerName1.value.length > 0 ? inputPlayerName1.value : "Spieler 1";
players[2].name = inputPlayerName2.value.length > 0 ? inputPlayerName2.value : "Spieler 2";
document.getElementById("setPlayerNamesWrapperBackdrop").style.display = "none";
cpuToggle.disabled = false;
initGame();
});
newGameButton.addEventListener("click", openSavePlayerNamesDialog);
cpuToggle.addEventListener("click", openSavePlayerNamesDialog);
initGame();