<!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;