Play Chess Online
Gelişmiş Satranç Oyunu
Beyaz Başlar
// Bu satır style tag'inin üstüne taşındı
// Satranç tahtasının başlangıç durumu
const initialBoard = [
['bR', 'bN', 'bB', 'bQ', 'bK', 'bB', 'bN', 'bR'],
['bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP', 'bP'],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['', '', '', '', '', '', '', ''],
['wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP', 'wP'],
['wR', 'wN', 'wB', 'wQ', 'wK', 'wB', 'wN', 'wR']
];
// Taşların Unicode karakterleri
const pieceMap = {
'wR': '♖', 'wN': '♘', 'wB': '♗', 'wQ': '♕', 'wK': '♔', 'wP': '♙',
'bR': '♜', 'bN': '♞', 'bB': '♝', 'bQ': '♛', 'bK': '♚', 'bP': '♟'
};
let board = [];
let selectedSquare = null;
let currentPlayer = 'w'; // 'w' for white, 'b' for black
let gameStatus = document.getElementById('game-status');
// Tahtayı ve taşları çizen fonksiyon
function drawBoard() {
const chessboardElement = document.getElementById('chessboard');
chessboardElement.innerHTML = ''; // Tahtayı temizle
for (let row = 0; row < 8; row++) {
for (let col = 0; col < 8; col++) {
const squareElement = document.createElement('div');
const isLight = (row + col) % 2 === 0;
squareElement.classList.add('square', isLight ? 'light' : 'dark');
squareElement.dataset.row = row;
squareElement.dataset.col = col;
squareElement.id = `square-${row}-${col}`;
const piece = board[row][col];
if (piece) {
const pieceElement = document.createElement('span');
pieceElement.classList.add('piece', piece.startsWith('w') ? 'white-piece' : 'black-piece');
pieceElement.textContent = pieceMap[piece];
squareElement.appendChild(pieceElement);
}
squareElement.addEventListener('click', handleSquareClick);
chessboardElement.appendChild(squareElement);
}
}
}
// Kare tıklamasını işleyen fonksiyon
function handleSquareClick(event) {
const clickedSquare = event.currentTarget;
const row = parseInt(clickedSquare.dataset.row);
const col = parseInt(clickedSquare.dataset.col);
const piece = board[row][col];
if (selectedSquare === null) {
// Taş seçme
if (piece && piece.startsWith(currentPlayer)) {
selectedSquare = { row, col };
clickedSquare.classList.add('selected');
highlightPossibleMoves(row, col);
}
} else {
// Taş hareket ettirme veya başka taş seçme
const startRow = selectedSquare.row;
const startCol = selectedSquare.col;
if (startRow === row && startCol === col) {
// Aynı kareye tekrar tıklandı, seçimi kaldır
deselectSquare();
} else if (piece && piece.startsWith(currentPlayer)) {
// Başka kendi taşını seçme
deselectSquare();
selectedSquare = { row, col };
clickedSquare.classList.add('selected');
highlightPossibleMoves(row, col);
} else {
// Hareket etme denemesi
if (isValidMove(startRow, startCol, row, col)) {
movePiece(startRow, startCol, row, col);
switchPlayer();
deselectSquare();
checkGameStatus();
} else {
// Geçersiz hareket, seçimi kaldır
deselectSquare();
}
}
}
}
// Seçimi kaldıran fonksiyon
function deselectSquare() {
if (selectedSquare) {
const { row, col } = selectedSquare;
document.getElementById(`square-${row}-${col}`).classList.remove('selected');
removePossibleMoveHighlights();
selectedSquare = null;
}
}
// Olası hareketleri vurgulayan fonksiyon
function highlightPossibleMoves(row, col) {
const possibleMoves = getLegalMoves(row, col);
possibleMoves.forEach(move => {
document.getElementById(`square-${move.row}-${move.col}`).classList.add('possible-move');
});
}
// Olası hareket vurgularını kaldıran fonksiyon
function removePossibleMoveHighlights() {
document.querySelectorAll('.possible-move').forEach(square => {
square.classList.remove('possible-move');
});
}
// Taş hareketini gerçekleştiren fonksiyon
function movePiece(startRow, startCol, endRow, endCol) {
board[endRow][endCol] = board[startRow][startCol];
board[startRow][startCol] = '';
drawBoard(); // Tahtayı yeniden çiz
}
// Sıradaki oyuncuyu değiştiren fonksiyon
function switchPlayer() {
currentPlayer = currentPlayer === 'w' ? 'b' : 'w';
gameStatus.textContent = currentPlayer === 'w' ? 'Beyaz Sırası' : 'Siyah Sırası';
}
// Oyun durumunu kontrol eden fonksiyon (Şah, Mat vb.)
function checkGameStatus() {
const kingColor = currentPlayer;
if (isCheckmate(kingColor)) {
gameStatus.textContent = `${kingColor === 'w' ? 'Siyah' : 'Beyaz'} Kazandı! Mat!`;
// Oyunu durdurma veya yeniden başlatma seçenekleri eklenebilir
} else if (isCheck(kingColor)) {
gameStatus.textContent += ` - Şah!`;
}
}
// Belirtilen renkteki şahın şahta olup olmadığını kontrol eden fonksiyon
function isCheck(kingColor) {
// Şahın pozisyonunu bul
let kingRow, kingCol;
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
if (board[r][c] === kingColor + 'K') {
kingRow = r;
kingCol = c;
break;
}
}
if (kingRow !== undefined) break;
}
// Rakip taşların şahı tehdit edip etmediğini kontrol et
const opponentColor = kingColor === 'w' ? 'b' : 'w';
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
const piece = board[r][c];
if (piece && piece.startsWith(opponentColor)) {
// Geçici olarak isValidMove kullanıyoruz, ancak bu fonksiyonun
// şahın kendi rengi tarafından tehdit edilmediğini varsayması gerekir.
// Daha doğru bir kontrol için, her rakip taşın tüm olası hareketlerini
// kontrol edip şahın karesinde bitip bitmediğine bakmak gerekir.
// Basitlik adına, burada isValidMove'u kullanıyoruz, ancak bu tam doğru olmayabilir.
// Gelişmiş bir satranç motoru daha karmaşık bir şah kontrolü gerektirir.
// TODO: Daha doğru bir şah kontrolü implemente et.
if (isValidMove(r, c, kingRow, kingCol, true)) { // 'true' isValidMove'a tehdit kontrolü olduğunu belirtmek için eklenebilir
return true;
}
}
}
}
return false;
}
// Belirtilen renkteki şahın mat olup olmadığını kontrol eden fonksiyon
function isCheckmate(kingColor) {
if (!isCheck(kingColor)) {
return false; // Şahta değilse mat olamaz
}
// Oynayabilecek herhangi bir yasal hareket var mı kontrol et
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
const piece = board[r][c];
if (piece && piece.startsWith(kingColor)) {
const legalMoves = getLegalMoves(r, c);
if (legalMoves.length > 0) {
return false; // Yasal bir hareket bulundu, mat değil
}
}
}
}
return true; // Yasal hareket bulunamadı, mat
}
// Bir taşın yasal hareketlerini döndüren fonksiyon (Şah çekme durumunu dikkate alarak)
function getLegalMoves(startRow, startCol) {
const piece = board[startRow][startCol];
if (!piece) return [];
const possibleMoves = getPossibleMoves(startRow, startCol);
const legalMoves = [];
possibleMoves.forEach(move => {
// Hareketi geçici olarak yap
const originalEndPiece = board[move.row][move.col];
const originalStartPiece = board[startRow][startCol];
board[move.row][move.col] = originalStartPiece;
board[startRow][startCol] = '';
// Hareket sonrası kendi şahımızın şahta olup olmadığını kontrol et
const kingColor = originalStartPiece.startsWith('w') ? 'w' : 'b';
if (!isCheck(kingColor)) {
legalMoves.push(move);
}
// Tahtayı eski durumuna geri getir
board[startRow][startCol] = originalStartPiece;
board[move.row][move.col] = originalEndPiece;
});
return legalMoves;
}
// Bir taşın olası hareketlerini döndüren fonksiyon (Şah çekme durumunu dikkate almaz)
function getPossibleMoves(startRow, startCol) {
const piece = board[startRow][startCol];
const moves = [];
const color = piece.startsWith('w') ? 'w' : 'b';
const direction = color === 'w' ? -1 : 1; // Beyaz yukarı, siyah aşağı
switch (piece[1]) {
case 'P': // Piyon
// İleri hareket
if (board[startRow + direction] && board[startRow + direction][startCol] === '') {
moves.push({ row: startRow + direction, col: startCol });
// İlk hareket ve 2 kare ileri
if ((color === 'w' && startRow === 6) || (color === 'b' && startRow === 1)) {
if (board[startRow + 2 * direction] && board[startRow + 2 * direction][startCol] === '') {
moves.push({ row: startRow + 2 * direction, col: startCol });
}
}
}
// Çapraz yeme
if (board[startRow + direction]) {
if (startCol > 0 && board[startRow + direction][startCol - 1] && board[startRow + direction][startCol - 1].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow + direction, col: startCol - 1 });
}
if (startCol < 7 && board[startRow + direction][startCol + 1] && board[startRow + direction][startCol + 1].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow + direction, col: startCol + 1 });
}
}
// TODO: En passant ve terfi ekle
break;
case 'R': // Kale
// Dikey ve yatay hareket
for (let i = startRow + 1; i < 8; i++) { // Aşağı
if (board[i][startCol] === '') {
moves.push({ row: i, col: startCol });
} else {
if (board[i][startCol].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: i, col: startCol });
}
break;
}
}
for (let i = startRow - 1; i >= 0; i--) { // Yukarı
if (board[i][startCol] === '') {
moves.push({ row: i, col: startCol });
} else {
if (board[i][startCol].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: i, col: startCol });
}
break;
}
}
for (let i = startCol + 1; i < 8; i++) { // Sağ
if (board[startRow][i] === '') {
moves.push({ row: startRow, col: i });
} else {
if (board[startRow][i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow, col: i });
}
break;
}
}
for (let i = startCol - 1; i >= 0; i--) { // Sol
if (board[startRow][i] === '') {
moves.push({ row: startRow, col: i });
} else {
if (board[startRow][i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow, col: i });
}
break;
}
}
break;
case 'N': // At
const knightMoves = [
[-2, -1], [-2, 1], [-1, -2], [-1, 2],
[1, -2], [1, 2], [2, -1], [2, 1]
];
knightMoves.forEach(move => {
const newRow = startRow + move[0];
const newCol = startCol + move[1];
if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {
const targetPiece = board[newRow][newCol];
if (targetPiece === '' || targetPiece.startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: newRow, col: newCol });
}
}
});
break;
case 'B': // Fil
// Çapraz hareket
for (let i = 1; startRow + i < 8 && startCol + i < 8; i++) { // Sağ aşağı
if (board[startRow + i][startCol + i] === '') {
moves.push({ row: startRow + i, col: startCol + i });
} else {
if (board[startRow + i][startCol + i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow + i, col: startCol + i });
}
break;
}
}
for (let i = 1; startRow - i >= 0 && startCol + i < 8; i++) { // Sağ yukarı
if (board[startRow - i][startCol + i] === '') {
moves.push({ row: startRow - i, col: startCol + i });
} else {
if (board[startRow - i][startCol + i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow - i, col: startCol + i });
}
break;
}
}
for (let i = 1; startRow + i < 8 && startCol - i >= 0; i++) { // Sol aşağı
if (board[startRow + i][startCol - i] === '') {
moves.push({ row: startRow + i, col: startCol - i });
} else {
if (board[startRow + i][startCol - i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow + i, col: startCol - i });
}
break;
}
}
for (let i = 1; startRow - i >= 0 && startCol - i >= 0; i++) { // Sol yukarı
if (board[startRow - i][startCol - i] === '') {
moves.push({ row: startRow - i, col: startCol - i });
} else {
if (board[startRow - i][startCol - i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow - i, col: startCol - i });
}
break;
}
}
break;
case 'Q': // Vezir
// Kale ve Fil hareketlerinin birleşimi (Yukarıdaki Kale ve Fil mantığını buraya kopyalayabilirsiniz)
// Dikey ve yatay hareket (Kale gibi)
for (let i = startRow + 1; i < 8; i++) { // Aşağı
if (board[i][startCol] === '') {
moves.push({ row: i, col: startCol });
} else {
if (board[i][startCol].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: i, col: startCol });
}
break;
}
}
for (let i = startRow - 1; i >= 0; i--) { // Yukarı
if (board[i][startCol] === '') {
moves.push({ row: i, col: startCol });
} else {
if (board[i][startCol].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: i, col: startCol });
}
break;
}
}
for (let i = startCol + 1; i < 8; i++) { // Sağ
if (board[startRow][i] === '') {
moves.push({ row: startRow, col: i });
} else {
if (board[startRow][i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow, col: i });
}
break;
}
}
for (let i = startCol - 1; i >= 0; i--) { // Sol
if (board[startRow][i] === '') {
moves.push({ row: startRow, col: i });
} else {
if (board[startRow][i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow, col: i });
}
break;
}
}
// Çapraz hareket (Fil gibi)
for (let i = 1; startRow + i < 8 && startCol + i < 8; i++) { // Sağ aşağı
if (board[startRow + i][startCol + i] === '') {
moves.push({ row: startRow + i, col: startCol + i });
} else {
if (board[startRow + i][startCol + i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow + i, col: startCol + i });
}
break;
}
}
for (let i = 1; startRow - i >= 0 && startCol + i < 8; i++) { // Sağ yukarı
if (board[startRow - i][startCol + i] === '') {
moves.push({ row: startRow - i, col: startCol + i });
} else {
if (board[startRow - i][startCol + i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow - i, col: startCol + i });
}
break;
}
}
for (let i = 1; startRow + i < 8 && startCol - i >= 0; i++) { // Sol aşağı
if (board[startRow + i][startCol - i] === '') {
moves.push({ row: startRow + i, col: startCol - i });
} else {
if (board[startRow + i][startCol - i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow + i, col: startCol - i });
}
break;
}
}
for (let i = 1; startRow - i >= 0 && startCol - i >= 0; i++) { // Sol yukarı
if (board[startRow - i][startCol - i] === '') {
moves.push({ row: startRow - i, col: startCol - i });
} else {
if (board[startRow - i][startCol - i].startsWith(color === 'w' ? 'b' : 'w')) {
moves.push({ row: startRow - i, col: startCol - i });
}
break;
}
}
break;
case 'K': // Şah
const kingMoves = [
[-1, -1], [-1, 0], [-1, 1],
[0, -1], [0, 1],
[1, -1], [1, 0], [1, 1]
];
kingMoves.forEach(move => {
const newRow = startRow + move[0];
const newCol = startCol + move[1];
if (newRow >= 0 && newRow < 8 && newCol >= 0 && newCol < 8) {
const targetPiece = board[newRow][newCol];
if (targetPiece === '' || targetPiece.startsWith(color === 'w' ? 'b' : 'w')) {
// TODO: Şahın gideceği yerin şah tehdidi altında olup olmadığını kontrol et
moves.push({ row: newRow, col: newCol });
}
}
});
// TODO: Rok ekle
break;
}
return moves;
}
// Hareketin geçerli olup olmadığını kontrol eden fonksiyon
function isValidMove(startRow, startCol, endRow, endCol) {
const piece = board[startRow][startCol];
if (!piece) return false; // Başlangıç karesinde taş yok
const targetPiece = board[endRow][endCol];
const color = piece.startsWith('w') ? 'w' : 'b';
const opponentColor = color === 'w' ? 'b' : 'w';
// Kendi taşının üzerine gitme
if (targetPiece && targetPiece.startsWith(color)) {
return false;
}
const possibleMoves = getPossibleMoves(startRow, startCol);
// Olası hareketler arasında hedef kare var mı kontrol et
const isPossible = possibleMoves.some(move => move.row === endRow && move.col === endCol);
if (!isPossible) {
return false;
}
// Hareket sonrası kendi şahın şahta kalıp kalmadığını kontrol et (Bu kontrol getLegalMoves içinde yapılıyor)
// Bu fonksiyon sadece temel hareket kurallarını kontrol etmeliydi.
// getLegalMoves fonksiyonu zaten bu kontrolü yaptığı için bu kısım burada gereksiz olabilir.
// Ancak, getPossibleMoves sadece temel hareketleri verir, şah kontrolü yapmaz.
// Bu yüzden, hareketin yasal olup olmadığını kontrol etmek için getLegalMoves kullanılmalıdır.
// TODO: isValidMove yerine getLegalMoves kullanılarak hareketin yasal olup olmadığı kontrol edilmeli.
// Şimdilik basit bir isValidMove implementasyonu bırakıyorum, ancak bu tam doğru bir satranç motoru için yeterli değil.
// Geçici olarak hareketi yap
const originalEndPiece = board[endRow][endCol];
const originalStartPiece = board[startRow][startCol];
board[endRow][endCol] = originalStartPiece;
board[startRow][startCol] = '';
// Hareket sonrası kendi şahımızın şahta olup olmadığını kontrol et
const kingColor = originalStartPiece.startsWith('w') ? 'w' : 'b';
const isInCheckAfterMove = isCheck(kingColor);
// Tahtayı eski durumuna geri getir
board[startRow][startCol] = originalStartPiece;
board[endRow][endCol] = originalEndPiece;
// Eğer hareket sonrası şahta değilse ve hareket olası hareketlerden biriyse geçerli
return isPossible && !isInCheckAfterMove;
}
// Oyunu başlatan fonksiyon
function startGame() {
// Başlangıç tahtasını kopyala
board = initialBoard.map(row => [...row]);
currentPlayer = 'w';
gameStatus = document.getElementById('game-status'); // Elementi tekrar al
drawBoard();
}
// Sayfa yüklendiğinde oyunu başlat
document.addEventListener('DOMContentLoaded', startGame);