<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mobile Chess Game</title>
<style>
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #f0f0f0;
}
#board {
display: grid;
grid-template-columns: repeat(8, 12.5vw);
grid-template-rows: repeat(8, 12.5vw);
width: 100vw;
max-width: 100vh;
aspect-ratio: 1 / 1;
border: 2px solid #333;
}
.cell {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 6vw;
user-select: none;
}
.white { background: #eee; }
.black { background: #444; color: white; }
.selected { outline: 3px solid yellow; }
</style>
</head>
<body>
<div id="board"></div>
<script>
const board = document.getElementById("board");
const pieces = {
r: "♜", n: "♞", b: "♝", q: "♛", k: "♚", p: "♟",
R: "♖", N: "♘", B: "♗", Q: "♕", K: "♔", P: "♙"
};
let game = [
"rnbqkbnr",
"pppppppp",
"........",
"........",
"........",
"........",
"PPPPPPPP",
"RNBQKBNR"
].map(row => row.split(""));
let selected = null;
let turn = "white";
function draw() {
board.innerHTML = "";
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
const cell = document.createElement("div");
cell.className = `cell ${(r + c) % 2 === 0 ? "white" : "black"}`;
cell.dataset.row = r;
cell.dataset.col = c;
const piece = game[r][c];
if (pieces[piece]) cell.textContent = pieces[piece];
if (selected && selected[0] === r && selected[1] === c)
cell.classList.add("selected");
cell.onclick = () => handleClick(r, c);
board.appendChild(cell);
}
}
}
function handleClick(r, c) {
const piece = game[r][c];
if (!selected) {
if ((turn === "white" && piece === piece.toUpperCase() && piece !== ".") ||
(turn === "black" && piece === piece.toLowerCase() && piece !== ".")) {
selected = [r, c];
}
} else {
const [sr, sc] = selected;
if (sr === r && sc === c) {
selected = null; // Deselect if tapped again
} else if (isValidMove(sr, sc, r, c)) {
const target = game[r][c];
if (target === "k" || target === "K") {
alert(`${turn} wins!`);
location.reload();
}
game[r][c] = game[sr][sc];
game[sr][sc] = ".";
turn = turn === "white" ? "black" : "white";
selected = null;
} else {
selected = null;
}
}
draw();
}
function isValidMove(sr, sc, r, c) {
const piece = game[sr][sc];
const target = game[r][c];
if (piece === ".") return false;
if (piece === target) return false;
const isWhite = piece === piece.toUpperCase();
const dr = r - sr;
const dc = c - sc;
switch (piece.toLowerCase()) {
case "p":
let dir = isWhite ? -1 : 1;
if (dc === 0 && target === "." && dr === dir) return true;
if (dc === 0 && target === "." && dr === 2 * dir && (isWhite ? sr === 6 : sr === 1)) return true;
if (Math.abs(dc) === 1 && dr === dir && target !== "." && (isWhite !== (target === target.toUpperCase()))) return true;
break;
case "r":
if (sr === r || sc === c) return clearPath(sr, sc, r, c);
break;
case "n":
if ((Math.abs(dr) === 2 && Math.abs(dc) === 1) || (Math.abs(dr) === 1 && Math.abs(dc) === 2)) return true;
break;
case "b":
if (Math.abs(dr) === Math.abs(dc)) return clearPath(sr, sc, r, c);
break;
case "q":
if (sr === r || sc === c || Math.abs(dr) === Math.abs(dc)) return clearPath(sr, sc, r, c);
break;
case "k":
if (Math.abs(dr) <= 1 && Math.abs(dc) <= 1) return true;
break;
}
return false;
}
function clearPath(sr, sc, r, c) {
const dRow = Math.sign(r - sr);
const dCol = Math.sign(c - sc);
let i = sr + dRow, j = sc + dCol;
while (i !== r || j !== c) {
if (game[i][j] !== ".") return false;
i += dRow;
j += dCol;
}
return true;
}
draw();
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mobile Chess Game</title>
<style>
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #f0f0f0;
}
#board {
display: grid;
grid-template-columns: repeat(8, 12.5vw);
grid-template-rows: repeat(8, 12.5vw);
width: 100vw;
max-width: 100vh;
aspect-ratio: 1 / 1;
border: 2px solid #333;
}
.cell {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 6vw;
user-select: none;
}
.white { background: #eee; }
.black { background: #444; color: white; }
.selected { outline: 3px solid yellow; }
</style>
</head>
<body>
<div id="board"></div>
<script>
const board = document.getElementById("board");
const pieces = {
r: "♜", n: "♞", b: "♝", q: "♛", k: "♚", p: "♟",
R: "♖", N: "♘", B: "♗", Q: "♕", K: "♔", P: "♙"
};
let game = [
"rnbqkbnr",
"pppppppp",
"........",
"........",
"........",
"........",
"PPPPPPPP",
"RNBQKBNR"
].map(row => row.split(""));
let selected = null;
let turn = "white";
function draw() {
board.innerHTML = "";
for (let r = 0; r < 8; r++) {
for (let c = 0; c < 8; c++) {
const cell = document.createElement("div");
cell.className = `cell ${(r + c) % 2 === 0 ? "white" : "black"}`;
cell.dataset.row = r;
cell.dataset.col = c;
const piece = game[r][c];
if (pieces[piece]) cell.textContent = pieces[piece];
if (selected && selected[0] === r && selected[1] === c)
cell.classList.add("selected");
cell.onclick = () => handleClick(r, c);
board.appendChild(cell);
}
}
}
function handleClick(r, c) {
const piece = game[r][c];
if (!selected) {
if ((turn === "white" && piece === piece.toUpperCase() && piece !== ".") ||
(turn === "black" && piece === piece.toLowerCase() && piece !== ".")) {
selected = [r, c];
}
} else {
const [sr, sc] = selected;
if (sr === r && sc === c) {
selected = null; // Deselect if tapped again
} else if (isValidMove(sr, sc, r, c)) {
const target = game[r][c];
if (target === "k" || target === "K") {
alert(`${turn} wins!`);
location.reload();
}
game[r][c] = game[sr][sc];
game[sr][sc] = ".";
turn = turn === "white" ? "black" : "white";
selected = null;
} else {
selected = null;
}
}
draw();
}
function isValidMove(sr, sc, r, c) {
const piece = game[sr][sc];
const target = game[r][c];
if (piece === ".") return false;
if (piece === target) return false;
const isWhite = piece === piece.toUpperCase();
const dr = r - sr;
const dc = c - sc;
switch (piece.toLowerCase()) {
case "p":
let dir = isWhite ? -1 : 1;
if (dc === 0 && target === "." && dr === dir) return true;
if (dc === 0 && target === "." && dr === 2 * dir && (isWhite ? sr === 6 : sr === 1)) return true;
if (Math.abs(dc) === 1 && dr === dir && target !== "." && (isWhite !== (target === target.toUpperCase()))) return true;
break;
case "r":
if (sr === r || sc === c) return clearPath(sr, sc, r, c);
break;
case "n":
if ((Math.abs(dr) === 2 && Math.abs(dc) === 1) || (Math.abs(dr) === 1 && Math.abs(dc) === 2)) return true;
break;
case "b":
if (Math.abs(dr) === Math.abs(dc)) return clearPath(sr, sc, r, c);
break;
case "q":
if (sr === r || sc === c || Math.abs(dr) === Math.abs(dc)) return clearPath(sr, sc, r, c);
break;
case "k":
if (Math.abs(dr) <= 1 && Math.abs(dc) <= 1) return true;
break;
}
return false;
}
function clearPath(sr, sc, r, c) {
const dRow = Math.sign(r - sr);
const dCol = Math.sign(c - sc);
let i = sr + dRow, j = sc + dCol;
while (i !== r || j !== c) {
if (game[i][j] !== ".") return false;
i += dRow;
j += dCol;
}
return true;
}
draw();
</script>
</body>
</html>
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.