<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Pente HTML5 Game</title>
<style>
body { font-family: sans-serif; margin: 20px; }
canvas { border: 1px solid #333; }
#status { margin-top: 10px; }
</style>
</head>
<body>
<h2>Pente Board Game</h2>
<canvas id="gameBoard" width="600" height="600"></canvas>
<div id="status"></div>
<script>
const canvas = document.getElementById('gameBoard');
const ctx = canvas.getContext('2d');
const size = 15; // 15x15 grid
const cellSize = 40;
const board = Array.from({ length: size }, () => Array(size).fill(0));
let currentPlayer = 1; // 1 or 2
let captureCount = {1: 0, 2: 0};
const maxCaptures = 5;
const gameState = { ended: false };
const statusDiv = document.getElementById('status');
function drawBoard() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = '#444';
for (let i=0; i<=size; i++) {
ctx.beginPath();
ctx.moveTo(i*cellSize+0.5, 0);
ctx.lineTo(i*cellSize+0.5, size*cellSize);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, i*cellSize+0.5);
ctx.lineTo(size*cellSize, i*cellSize+0.5);
ctx.stroke();
}
for (let r=0; r<size; r++) {
for (let c=0; c<size; c++) {
if (board[r][c] !== 0) {
ctx.beginPath();
ctx.arc(c*cellSize + cellSize/2, r*cellSize + cellSize/2, cellSize/2 - 2, 0, 2*Math.PI);
ctx.fillStyle = board[r][c] === 1 ? 'black' : 'white';
ctx.fill();
}
}
}
}
function getCell(x, y) {
const c = Math.floor(x / cellSize);
const r = Math.floor(y / cellSize);
if (r>=0 && r<size && c>=0 && c<size) return {r, c};
return null;
}
canvas.addEventListener('click', e => {
if (gameState.ended) return;
const rect = canvas.getBoundingClientRect();
const pos = getCell(e.clientX - rect.left, e.clientY - rect.top);
if (!pos) return;
if (board[pos.r][pos.c] !== 0) return;
// Place stone
board[pos.r][pos.c] = currentPlayer;
// Check captures
handleCaptures(pos.r, pos.c);
// Check victory
if (checkWin(pos.r, pos.c)) {
statusDiv.textContent = `Player ${currentPlayer} wins!`;
gameState.ended = true;
} else if (captureCount[currentPlayer] >= 5 || checkFiveInRow(pos.r, pos.c)) {
// Win by capture or five in a row
statusDiv.textContent = `Player ${currentPlayer} wins!`;
gameState.ended = true;
} else {
// Switch turn
currentPlayer = 3 - currentPlayer;
statusDiv.textContent = `Player ${currentPlayer}'s turn`;
}
drawBoard();
});
function handleCaptures(r, c) {
const directions = [
{dr:1, dc:0}, {dr:0, dc:1}, {dr:1, dc:1}, {dr:1, dc:-1}
];
const opponent = 3 - currentPlayer;
for (const d of directions) {
const r1 = r + d.dr;
const c1 = c + d.dc;
const r2 = r + 2*d.dr;
const c2 = c + 2*d.dc;
const r3 = r + 3*d.dr;
const c3 = c + 3*d.dc;
if (inBounds(r1,c1) && inBounds(r2,c2) && inBounds(r3,c3)) {
if (board[r1][c1] === opponent && board[r2][c2] === opponent && board[r3][c3] === currentPlayer) {
// Remove opponent stones
board[r1][c1] = 0;
board[r2][c2] = 0;
captureCount[currentPlayer]++;
}
}
}
}
function inBounds(r, c) {
return r >=0 && r<size && c>=0 && c<size;
}
function checkWin(r, c) {
return checkFiveInRow(r, c);
}
function checkFiveInRow(r, c) {
const directions = [
{dr:1, dc:0}, {dr:0, dc:1}, {dr:1, dc:1}, {dr:1, dc:-1}
];
for (const d of directions) {
let count = 1;
count += countLine(r, c, d.dr, d.dc);
count += countLine(r, c, -d.dr, -d.dc);
if (count >= 5) return true;
}
return false;
}
function countLine(r, c, dr, dc) {
let count = 0;
let r1 = r + dr;
let c1 = c + dc;
while (inBounds(r1, c1) && board[r1][c1] === currentPlayer) {
count++;
r1 += dr;
c1 += dc;
}
return count;
}
// initial draw
drawBoard();
statusDiv.textContent = `Player ${currentPlayer}'s turn`;
</script>
</body>
</html>