<!DOCTYPE html>
<html lang="tr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Satranç - Düzeltilmiş Sürüm</title>
    <style>
        :root {
            --bg-color: #302e2b; /* Arka plan koyu gri */
            --board-border: #444;
            --light-sq: #eeeed2; /* Açık kare rengi */
            --dark-sq: #769656;  /* Koyu kare rengi (Chess.com yeşili) */
            --highlight: rgba(255, 255, 50, 0.6);
            --valid-move: rgba(0, 0, 0, 0.2);
        }

        body {
            font-family: 'Segoe UI', sans-serif;
            background-color: var(--bg-color);
            color: #fff;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            min-height: 100vh;
            margin: 0;
        }

        h1 { margin: 10px 0; font-size: 1.8rem; }

        /* Kontrol Paneli */
        .controls {
            margin-bottom: 15px;
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
            justify-content: center;
        }

        select, button {
            padding: 8px 15px;
            border-radius: 4px;
            border: none;
            font-size: 14px;
            cursor: pointer;
        }

        button { background-color: #81b64c; color: white; font-weight: bold; }
        button:hover { background-color: #6f9e41; }
        
        #status {
            margin-bottom: 10px;
            font-weight: bold;
            font-size: 1.2rem;
            min-height: 1.5em;
        }

        /* --- TAHTA DÜZENİ (DÜZELTİLEN KISIM) --- */
        .board-container {
            width: 100%;
            max-width: 500px; /* Tahta maksimum genişliği */
            padding: 10px;
            box-sizing: border-box;
        }

        #board {
            display: grid;
            grid-template-columns: repeat(8, 1fr); /* 8 Eşit sütun */
            grid-template-rows: repeat(8, 1fr);    /* 8 Eşit satır */
            width: 100%;
            aspect-ratio: 1 / 1; /* EN ÖNEMLİ AYAR: Kareyi zorlar */
            border: 5px solid var(--board-border);
            border-radius: 4px;
            box-shadow: 0 5px 15px rgba(0,0,0,0.5);
            background-color: var(--board-border);
        }

        .square {
            width: 100%;
            height: 100%;
            display: flex;            /* İçindeki taşı ortalamak için */
            justify-content: center;  /* Yatay ortalama */
            align-items: center;      /* Dikey ortalama */
            font-size: clamp(1.5rem, 8vw, 3.5rem); /* Taş boyutu ekrana göre değişir */
            cursor: pointer;
            position: relative;
            user-select: none;
        }

        /* Renkler */
        .light { background-color: var(--light-sq); color: black; }
        .dark { background-color: var(--dark-sq); color: black; }

        /* Taş Renkleri */
        .piece {
            cursor: grab;
            z-index: 2;
            line-height: 1; /* Satır yüksekliği taşın kaymasını engeller */
        }
        .piece:active { cursor: grabbing; }
        .piece.white { color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.8); }
        .piece.black { color: #000; text-shadow: 0 1px 2px rgba(255,255,255,0.5); }

        /* Efektler */
        .highlight { background-color: var(--highlight) !important; }
        
        .valid-move::after {
            content: '';
            position: absolute;
            width: 25%;
            height: 25%;
            background-color: var(--valid-move);
            border-radius: 50%;
        }
    </style>
</head>
<body>

    <h1>Satranç (AI)</h1>

    <div class="controls">
        <select id="difficulty">
            <option value="1">Kolay</option>
            <option value="2" selected>Orta</option>
            <option value="3">Zor (Düşünür)</option>
        </select>
        <button onclick="resetGame()">Yeni Oyun</button>
        <button onclick="downloadGameHistory()" style="background-color:#444;">Hamleleri İndir</button>
    </div>

    <div id="status">Beyazın Sırası</div>
    
    <div class="board-container">
        <div id="board"></div>
    </div>

<script>
/* --- JAVASCRIPT MANTIĞI (Değişmedi, aynı motor kullanılıyor) --- */

const PIECES = {
    r: '♜', n: '♞', b: '♝', q: '♛', k: '♚', p: '♟',
    R: '♜', N: '♞', B: '♝', Q: '♛', K: '♚', P: '♟'
};

let board = []; 
const files = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];
let turn = 'w';
let gameActive = true;
let selectedSquare = -1;
let possibleMoves = [];
let moveHistory = [];

// AI Puanları
const weights = { p: 100, n: 320, b: 330, r: 500, q: 900, k: 20000 };

// Oyunu Başlat
function initGame() {
    const setup = [
        'r','n','b','q','k','b','n','r',
        'p','p','p','p','p','p','p','p',
        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,
        'P','P','P','P','P','P','P','P',
        'R','N','B','Q','K','B','N','R'
    ];
    board = [...setup];
    turn = 'w';
    moveHistory = [];
    gameActive = true;
    document.getElementById('status').innerText = "Beyazın Sırası";
    renderBoard();
}

// Renk Kontrolü
function getPieceColor(piece) {
    if (!piece) return null;
    return piece === piece.toUpperCase() ? 'w' : 'b';
}

// Hamle Hesaplama
function getLegalMoves(boardState, color) {
    let moves = [];
    for (let i = 0; i < 64; i++) {
        if (boardState[i] && getPieceColor(boardState[i]) === color) {
            let pieceMoves = generatePseudoMoves(boardState, i, boardState[i]);
            pieceMoves.forEach(to => {
                let tempBoard = [...boardState];
                tempBoard[to] = tempBoard[i];
                tempBoard[i] = null;
                if (!isKingInCheck(tempBoard, color)) {
                    moves.push({from: i, to: to});
                }
            });
        }
    }
    return moves;
}

function generatePseudoMoves(boardState, idx, piece) {
    let moves = [];
    let row = Math.floor(idx / 8);
    let col = idx % 8;
    let type = piece.toLowerCase();
    let color = getPieceColor(piece);

    const addIfValid = (r, c) => {
        if (r >= 0 && r < 8 && c >= 0 && c < 8) {
            let targetIdx = r * 8 + c;
            let targetPiece = boardState[targetIdx];
            if (!targetPiece || getPieceColor(targetPiece) !== color) {
                moves.push(targetIdx);
                return !!targetPiece;
            }
            return true;
        }
        return true;
    };

    if (type === 'p') {
        let dir = color === 'w' ? -1 : 1;
        let startRow = color === 'w' ? 6 : 1;
        if (!boardState[idx + dir * 8]) {
            moves.push(idx + dir * 8);
            if (row === startRow && !boardState[idx + dir * 16]) moves.push(idx + dir * 16);
        }
        [[dir, -1], [dir, 1]].forEach(([rOff, cOff]) => {
            let r = row + rOff, c = col + cOff;
            if (r >= 0 && r < 8 && c >= 0 && c < 8) {
                let target = boardState[r * 8 + c];
                if (target && getPieceColor(target) !== color) moves.push(r * 8 + c);
            }
        });
    } else if (type === 'n') {
        [[-2,-1],[-2,1],[-1,-2],[-1,2],[1,-2],[1,2],[2,-1],[2,1]].forEach(([r, c]) => addIfValid(row + r, col + c));
    } else if (type === 'k') {
        [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]].forEach(([r, c]) => addIfValid(row + r, col + c));
    } else {
        let dirs = (type === 'b' || type === 'q') ? [[-1,-1],[-1,1],[1,-1],[1,1]] : [];
        if (type === 'r' || type === 'q') dirs = dirs.concat([[-1,0],[1,0],[0,-1],[0,1]]);
        dirs.forEach(([dr, dc]) => {
            let r = row + dr, c = col + dc;
            while (r >= 0 && r < 8 && c >= 0 && c < 8) {
                let targetIdx = r * 8 + c;
                let targetPiece = boardState[targetIdx];
                if (!targetPiece) moves.push(targetIdx);
                else {
                    if (getPieceColor(targetPiece) !== color) moves.push(targetIdx);
                    break;
                }
                r += dr; c += dc;
            }
        });
    }
    return moves;
}

function isKingInCheck(boardState, color) {
    let kingIdx = boardState.indexOf(color === 'w' ? 'K' : 'k');
    if (kingIdx === -1) return true;
    let enemyColor = color === 'w' ? 'b' : 'w';
    for (let i = 0; i < 64; i++) {
        if (boardState[i] && getPieceColor(boardState[i]) === enemyColor) {
            let moves = generatePseudoMoves(boardState, i, boardState[i]);
            if (moves.includes(kingIdx)) return true;
        }
    }
    return false;
}

function makeMove(move) {
    let piece = board[move.from];
    let captured = board[move.to];
    
    // Piyon Terfi (Otomatik Vezir)
    if (piece.toLowerCase() === 'p') {
        if ((getPieceColor(piece) === 'w' && Math.floor(move.to/8) === 0) ||
            (getPieceColor(piece) === 'b' && Math.floor(move.to/8) === 7)) {
            piece = getPieceColor(piece) === 'w' ? 'Q' : 'q';
        }
    }

    board[move.to] = piece;
    board[move.from] = null;
    
    let fromAlg = files[move.from % 8] + (8 - Math.floor(move.from / 8));
    let toAlg = files[move.to % 8] + (8 - Math.floor(move.to / 8));
    moveHistory.push(`${turn === 'w' ? "Beyaz" : "Siyah"}: ${fromAlg} -> ${toAlg}`);

    turn = turn === 'w' ? 'b' : 'w';
    checkGameState();
    renderBoard();
    
    if (gameActive && turn === 'b') {
        setTimeout(aiMove, 100);
    }
}

function checkGameState() {
    let moves = getLegalMoves(board, turn);
    let statusEl = document.getElementById('status');
    if (moves.length === 0) {
        gameActive = false;
        if (isKingInCheck(board, turn)) {
            statusEl.innerText = `Mat! ${turn === 'w' ? "Siyah" : "Beyaz"} Kazandı!`;
            moveHistory.push(`Sonuç: ${turn === 'w' ? "Siyah" : "Beyaz"} Mat Etti`);
        } else {
            statusEl.innerText = "Pat! Oyun Berabere.";
            moveHistory.push(`Sonuç: Pat (Berabere)`);
        }
        downloadGameHistory();
    } else {
        statusEl.innerText = isKingInCheck(board, turn) ? "ŞAH!" : `${turn === 'w' ? "Beyaz" : "Siyah"}ın Sırası`;
    }
}

// AI (Yapay Zeka)
function evaluateBoard(boardState) {
    let score = 0;
    for (let i = 0; i < 64; i++) {
        if (!boardState[i]) continue;
        let val = weights[boardState[i].toLowerCase()];
        score += boardState[i] === boardState[i].toUpperCase() ? val : -val;
    }
    return score;
}

function aiMove() {
    if (!gameActive) return;
    let depth = parseInt(document.getElementById('difficulty').value);
    let bestMove = minimaxRoot(depth === 1 ? 1 : (depth === 2 ? 2 : 3), 'b');
    if (bestMove) makeMove(bestMove);
    else { /* Yapılacak hamle yoksa oyun biter (checkGameState halleder) */ }
}

function minimaxRoot(depth, playerColor) {
    let moves = getLegalMoves(board, playerColor);
    let bestMove = null;
    let bestValue = -Infinity;
    moves.sort(() => Math.random() - 0.5);

    for (let move of moves) {
        let saved = board[move.to];
        board[move.to] = board[move.from];
        board[move.from] = null;
        let value = minimax(depth - 1, -Infinity, Infinity, false);
        board[move.from] = board[move.to];
        board[move.to] = saved;
        if (value >= bestValue) { bestValue = value; bestMove = move; }
    }
    return bestMove;
}

function minimax(depth, alpha, beta, isMaximizing) {
    if (depth === 0) return -evaluateBoard(board);
    let moves = getLegalMoves(board, isMaximizing ? 'b' : 'w');
    if (moves.length === 0) return isMaximizing ? -10000 : 10000;

    let best = isMaximizing ? -Infinity : Infinity;
    for (let move of moves) {
        let saved = board[move.to];
        board[move.to] = board[move.from];
        board[move.from] = null;
        let val = minimax(depth - 1, alpha, beta, !isMaximizing);
        board[move.from] = board[move.to];
        board[move.to] = saved;
        
        if (isMaximizing) {
            best = Math.max(best, val);
            alpha = Math.max(alpha, best);
        } else {
            best = Math.min(best, val);
            beta = Math.min(beta, best);
        }
        if (beta <= alpha) break;
    }
    return best;
}

// Render ve Etkileşim
const boardEl = document.getElementById('board');
function renderBoard() {
    boardEl.innerHTML = '';
    possibleMoves = selectedSquare !== -1 ? getLegalMoves(board, turn).filter(m => m.from === selectedSquare) : [];
    let dests = possibleMoves.map(m => m.to);

    for (let i = 0; i < 64; i++) {
        let sq = document.createElement('div');
        let r = Math.floor(i/8), c = i%8;
        sq.className = `square ${(r+c)%2===0 ? 'light' : 'dark'}`;
        if (i === selectedSquare) sq.classList.add('highlight');
        if (dests.includes(i)) sq.classList.add('valid-move');
        
        if (board[i]) {
            let p = document.createElement('span');
            p.className = `piece ${getPieceColor(board[i])==='w'?'white':'black'}`;
            p.innerText = PIECES[board[i]];
            p.draggable = true;
            p.addEventListener('dragstart', (e) => dragStart(e, i));
            sq.appendChild(p);
        }
        sq.addEventListener('click', () => handleClick(i));
        sq.addEventListener('dragover', (e) => e.preventDefault());
        sq.addEventListener('drop', (e) => drop(e, i));
        boardEl.appendChild(sq);
    }
}

function handleClick(i) {
    if (!gameActive || turn === 'b') return;
    if (selectedSquare === i) { selectedSquare = -1; renderBoard(); return; }
    let move = possibleMoves.find(m => m.to === i);
    if (move) { makeMove(move); selectedSquare = -1; return; }
    if (board[i] && getPieceColor(board[i]) === turn) { selectedSquare = i; renderBoard(); }
    else { selectedSquare = -1; renderBoard(); }
}

let draggedIdx = -1;
function dragStart(e, i) {
    if (!gameActive || turn === 'b' || getPieceColor(board[i]) !== turn) { e.preventDefault(); return; }
    draggedIdx = i;
    selectedSquare = i; // Sürüklerken de seçili göster
}
function drop(e, i) {
    e.preventDefault();
    if (draggedIdx === -1) return;
    let moves = getLegalMoves(board, turn);
    let move = moves.find(m => m.from === draggedIdx && m.to === i);
    if (move) makeMove(move);
    draggedIdx = -1;
    selectedSquare = -1;
    renderBoard(); // Hata durumunda tahtayı tazelemek için
}

function resetGame() { initGame(); }
function downloadGameHistory() {
    const blob = new Blob([moveHistory.join('\n')], {type: 'text/plain'});
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = 'Satranc_Kayit.txt';
    a.click();
}

initGame();
</script>
</body>
</html>

zorluk dereceleri ve oyun bitimi oyun raporu otomatik iner


örnek rapor


oyunda geçekleşen bilgiler örnek şah oldu bilgisi ekranda



Selamlar gemini 3 ile satranç oyunu yaptık geliştirmek size kalmış iyi forumlar

@Vulcanist;