Kodda ki eksiklikler
1-) Oyuncu, kendi taşınıda yiyebilmektedir, bu ileriki versiyonda düzeltilecektir.
2-) Rok hamlesinde kale yok oluyor, bu ileriki versiyonda düzeltilecektir.
Eklenmesi Planlanan özellikler
1-) Şah çekme tehdit ve Şah-Mat kontrolü eklenecektir.
2-) Piyonun rakip ana bölgesine girdiğinde (KALE, FİL, AT, VEZİR) değerli taşlara dönüşümü eklenecektir.
3-) Puanlama sistemi, şu anlık yenilen taşların puan değerlerine göre puanlama yapılacaktır.
4-) Süre takibi eklenecektir, süre bitiminde puan fazlası olan rakip kazanacaktır.
Eklenen Özellikler Nelerdir?
1-)Önceki versiyonda sadece harf olarak oynanıyordu ve taş yeme hamle yanlışlıkları vardı. Harf yerine "*.png" formatlı taşlar oluşturuldu.
2-) Hamle takibi yapılarak, her oyuncunun 1 kez oynanmasını ve taş yeme esnasında donma kasma gibi hataların giderilmesi sağlandı.
3-) Rakiplerin resimleri manuel, isimleri dinamik olarak alınması sağlandı.
4-) Yenen taşlar rakiplerin isimlerinin altında çerçeveye sıralı ve düzgün bir şekilde eklenmesi sağlandı.
Kullanılan resimler:














HTML KODU:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Satranç Tahtası</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="player-info player-black">
<img src="images/black-player.png" alt="Black Player Avatar" class="player-avatar">
<span class="player-name" id="black-player-name"></span>
</div>
<div class="captured-pieces captured-black"></div>
<div class="chessboard-container">
<div class="labels-top">
<span></span><span>a</span><span>b</span><span>c</span><span>d</span><span>e</span><span>f</span><span>g</span><span>h</span><span></span>
</div>
<div class="labels-left">
<span>8</span><span>7</span><span>6</span><span>5</span><span>4</span><span>3</span><span>2</span><span>1</span>
</div>
<div class="chessboard"></div>
<div class="labels-right">
<span>8</span><span>7</span><span>6</span><span>5</span><span>4</span><span>3</span><span>2</span><span>1</span>
</div>
<div class="labels-bottom">
<span></span><span>a</span><span>b</span><span>c</span><span>d</span><span>e</span><span>f</span><span>g</span><span>h</span><span></span>
</div>
</div>
<div class="captured-pieces captured-white"></div>
<div class="player-info player-white">
<img src="images/white-player.png" alt="White Player Avatar" class="player-avatar">
<span class="player-name" id="white-player-name"></span>
</div>
<script src="script.js"></script>
</body>
</html>
CSS KODU:
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
margin: 0;
}
.player-info {
display: flex;
align-items: center;
margin: 10px;
}
.player-info img {
width: 40px;
height: 40px;
margin-right: 10px;
}
.player-info .player-name {
font-size: 20px;
font-weight: bold;
}
.captured-pieces {
display: flex;
flex-wrap: wrap;
width: 480px;
margin: 10px;
border: 2px solid #333;
min-height: 60px;
justify-content: flex-start;
align-items: center;
background-color: #fff;
}
.captured-pieces img {
width: 30px;
height: 30px;
margin: 5px;
}
.chessboard-container {
display: grid;
grid-template-areas:
"top top top"
"left board right"
"bottom bottom bottom";
gap: 10px;
}
.labels-top, .labels-bottom {
display: grid;
grid-template-columns: repeat(10, 1fr);
grid-area: top;
}
.labels-top {
grid-area: top;
}
.labels-bottom {
grid-area: bottom;
}
.labels-left, .labels-right {
display: grid;
grid-template-rows: repeat(8, 1fr);
grid-area: left;
justify-items: center;
}
.labels-right {
grid-area: right;
}
.chessboard {
display: grid;
grid-template-columns: repeat(8, 60px);
grid-template-rows: repeat(8, 60px);
gap: 0;
border: 2px solid #000;
grid-area: board;
}
.labels-top span, .labels-bottom span {
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
}
.labels-left span, .labels-right span {
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: bold;
}
.square {
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-weight: bold;
font-family: Arial, sans-serif;
position: relative;
}
.square.white {
background-color: #eeeed2;
}
.square.black {
background-color: #769656;
}
.square.selected {
outline: 2px solid red;
}
[data-piece]:before {
content: "";
background-size: cover;
background-position: center;
width: 100%;
height: 100%;
position: absolute;
}
[data-piece="p"]::before { background-image: url('images/bP.png'); }
[data-piece="r"]::before { background-image: url('images/bR.png'); }
[data-piece="n"]::before { background-image: url('images/bN.png'); }
[data-piece="b"]::before { background-image: url('images/bB.png'); }
[data-piece="q"]::before { background-image: url('images/bQ.png'); }
[data-piece="k"]::before { background-image: url('images/bK.png'); }
[data-piece="P"]::before { background-image: url('images/wP.png'); }
[data-piece="R"]::before { background-image: url('images/wR.png'); }
[data-piece="N"]::before { background-image: url('images/wN.png'); }
[data-piece="B"]::before { background-image: url('images/wB.png'); }
[data-piece="Q"]::before { background-image: url('images/wQ.png'); }
[data-piece="K"]::before { background-image: url('images/wK.png'); }
.captured-pieces img {
width: 30px;
height: 30px;
margin: 5px;
}
Son Olarak Hakeret ve Yeme İşlemlerini Kontrol Eden JS KODU
document.addEventListener('DOMContentLoaded', () => {
const initialBoard = {
a8: 'r', b8: 'n', c8: 'b', d8: 'q', e8: 'k', f8: 'b', g8: 'n', h8: 'r',
a7: 'p', b7: 'p', c7: 'p', d7: 'p', e7: 'p', f7: 'p', g7: 'p', h7: 'p',
a2: 'P', b2: 'P', c2: 'P', d2: 'P', e2: 'P', f2: 'P', g2: 'P', h2: 'P',
a1: 'R', b1: 'N', c1: 'B', d1: 'Q', e1: 'K', f1: 'B', g1: 'N', h1: 'R'
};
const pieceMoves = {
p: (from, to, board) => {
const direction = from[1] === '2' ? 1 : -1;
const startRow = from[1] === '2' || from[1] === '7';
const diff = parseInt(to[1]) - parseInt(from[1]);
if (from[0] === to[0] && board[to] === undefined && (diff === direction || (startRow && diff === 2 * direction && board[from[0] + (parseInt(from[1]) + direction)] === undefined))) {
return true;
}
if (Math.abs(from.charCodeAt(0) - to.charCodeAt(0)) === 1 && diff === direction && board[to] !== undefined) {
return true;
}
return false;
},
r: (from, to, board) => {
if (from[0] === to[0]) {
for (let i = Math.min(parseInt(from[1]), parseInt(to[1])) + 1; i < Math.max(parseInt(from[1]), parseInt(to[1])); i++) {
if (board[from[0] + i]) return false;
}
return true;
}
if (from[1] === to[1]) {
for (let i = Math.min(from.charCodeAt(0), to.charCodeAt(0)) + 1; i < Math.max(from.charCodeAt(0), to.charCodeAt(0)); i++) {
if (board[String.fromCharCode(i) + from[1]]) return false;
}
return true;
}
return false;
},
n: (from, to) => {
const dx = Math.abs(from.charCodeAt(0) - to.charCodeAt(0));
const dy = Math.abs(from[1] - to[1]);
return (dx === 2 && dy === 1) || (dx === 1 && dy === 2);
},
b: (from, to, board) => {
if (Math.abs(from.charCodeAt(0) - to.charCodeAt(0)) !== Math.abs(from[1] - to[1])) return false;
const xDirection = from.charCodeAt(0) < to.charCodeAt(0) ? 1 : -1;
const yDirection = from[1] < to[1] ? 1 : -1;
for (let i = 1; i < Math.abs(from.charCodeAt(0) - to.charCodeAt(0)); i++) {
if (board[String.fromCharCode(from.charCodeAt(0) + i * xDirection) + (parseInt(from[1]) + i * yDirection)]) return false;
}
return true;
},
q: (from, to, board) => {
return pieceMoves.r(from, to, board) || pieceMoves.b(from, to, board);
},
k: (from, to, board) => {
const dx = Math.abs(from.charCodeAt(0) - to.charCodeAt(0));
const dy = Math.abs(from[1] - to[1]);
return dx <= 1 && dy <= 1;
}
};
let hasMoved = {
K: false, // Beyaz şah
k: false, // Siyah şah
R: {
a1: false, h1: false // Beyaz kaleler
},
r: {
a8: false, h8: false // Siyah kaleler
}
};
const canCastle = (king, from, to, board) => {
if (king.toLowerCase() !== 'k') return false;
const isWhite = king === 'K';
const rookPosition = isWhite ? (to === 'g1' ? 'h1' : 'a1') : (to === 'g8' ? 'h8' : 'a8');
const rook = board[rookPosition];
if (!rook || rook.toLowerCase() !== 'r') return false;
if (hasMoved[king] || hasMoved[rook.toLowerCase()][rookPosition]) return false;
const direction = to.charCodeAt(0) > from.charCodeAt(0) ? 1 : -1;
const kingPath = [];
for (let i = 1; i <= 2; i++) {
kingPath.push(String.fromCharCode(from.charCodeAt(0) + i * direction) + from[1]);
}
for (let square of kingPath) {
if (board[square]) return false;
// Ayrıca tehdit altındaki kareleri kontrol etmeliyiz (bu kısım ihmal edildi, daha kapsamlı bir tehdit kontrolü eklenebilir)
}
return true;
};
const isValidMove = (piece, from, to, board) => {
if (piece.toLowerCase() in pieceMoves) {
if (board[to] && piece[0] === board[to][0]) {
return false;
}
if (piece.toLowerCase() === 'k' && Math.abs(from.charCodeAt(0) - to.charCodeAt(0)) === 2) {
if (canCastle(piece, from, to, board)) {
// Rok hareketi geçerli, kaleyi taşı
const rookOldPosition = to === 'g1' || to === 'g8' ? String.fromCharCode(to.charCodeAt(0) + 1) + from[1] : String.fromCharCode(to.charCodeAt(0) - 2) + from[1];
const rookNewPosition = to === 'g1' || to === 'g8' ? String.fromCharCode(to.charCodeAt(0) - 1) + from[1] : String.fromCharCode(to.charCodeAt(0) + 1) + from[1];
board[rookNewPosition] = board[rookOldPosition];
delete board[rookOldPosition];
return true;
}
return false;
}
return pieceMoves[piece.toLowerCase()](from, to, board);
}
return false;
};
const chessboard = document.querySelector('.chessboard');
const capturedBlack = document.querySelector('.captured-black');
const capturedWhite = document.querySelector('.captured-white');
const blackPlayerNameElement = document.getElementById('black-player-name');
const whitePlayerNameElement = document.getElementById('white-player-name');
const boardState = { ...initialBoard };
let selectedSquare = null;
let currentPlayer = 'white'; // Başlangıçta beyaz başlar
const renderBoard = () => {
chessboard.innerHTML = '';
for (let i = 8; i >= 1; i--) {
for (let j = 0; j < 8; j++) {
const square = document.createElement('div');
const id = String.fromCharCode(97 + j) + i;
square.id = id;
square.className = 'square ' + ((i + j) % 2 === 0 ? 'white' : 'black');
if (boardState[id]) {
square.setAttribute('data-piece', boardState[id]);
}
square.addEventListener('click', () => onSquareClick(square));
chessboard.appendChild(square);
}
}
};
const onSquareClick = (square) => {
if (selectedSquare) {
selectedSquare.classList.remove('selected');
const piece = selectedSquare.getAttribute('data-piece');
const targetPiece = square.getAttribute('data-piece');
if (selectedSquare !== square && isValidMove(piece, selectedSquare.id, square.id, boardState) && (!targetPiece || piece[0] !== targetPiece[0])) {
if (targetPiece) {
if (targetPiece === targetPiece.toUpperCase()) {
addCapturedPiece(targetPiece, 'black');
} else {
addCapturedPiece(targetPiece, 'white');
}
}
// Rok hareketi için özel kontrol
if (piece.toLowerCase() === 'k' && Math.abs(selectedSquare.id.charCodeAt(0) - square.id.charCodeAt(0)) === 2) {
const direction = square.id.charCodeAt(0) > selectedSquare.id.charCodeAt(0) ? 1 : -1;
const rookOldPosition = direction === 1 ? 'h' + selectedSquare.id[1] : 'a' + selectedSquare.id[1];
const rookNewPosition = String.fromCharCode(square.id.charCodeAt(0) - direction) + selectedSquare.id[1];
boardState[rookNewPosition] = boardState[rookOldPosition];
delete boardState[rookOldPosition];
}
boardState[square.id] = piece;
delete boardState[selectedSquare.id];
// Şah ve kale hareketlerini kaydet
if (piece.toLowerCase() === 'k') {
hasMoved[piece] = true;
}
if (piece.toLowerCase() === 'r') {
hasMoved[piece.toLowerCase()][selectedSquare.id] = true;
}
currentPlayer = currentPlayer === 'white' ? 'black' : 'white'; // Sırayı değiştir
renderBoard(); // Tahtayı yeniden çiz
}
selectedSquare = null;
} else if (square.getAttribute('data-piece')) {
selectedSquare = square;
selectedSquare.classList.add('selected');
}
};
const addCapturedPiece = (piece, color) => {
const img = document.createElement('img');
img.src = `images/${color === 'black' ? 'w' : 'b'}${piece.toUpperCase()}.png`;
if (color === 'black') {
capturedBlack.appendChild(img);
} else {
capturedWhite.appendChild(img);
}
};
const blackPlayerName = prompt("Siyah oyuncunun adını girin:");
const whitePlayerName = prompt("Beyaz oyuncunun adını girin:");
if (blackPlayerName) {
blackPlayerNameElement.textContent = blackPlayerName;
}
if (whitePlayerName) {
whitePlayerNameElement.textContent = whitePlayerName;
}
renderBoard();
});