<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Native Gomoku Game</title>
<style>
:root {
--num: 15; /* Board size (8-15) */
--cell-size: calc(80vh / var(--num));
--board-bg: #f5f5dc; /* Classical board color */
--grid-color: #000;
--dot-color: #000;
--black-piece: #000;
--white-piece: #fff;
--highlight: #ffcc00;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
background-color: #f0f0f0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
.game-container {
position: relative;
width: fit-content;
}
.board {
display: grid;
grid-template-columns: repeat(var(--num), var(--cell-size));
grid-template-rows: repeat(var(--num), var(--cell-size));
background-color: var(--board-bg);
border: 2px solid var(--grid-color);
box-shadow: 0 0 10px rgba(0,0,0,0.2);
}
.cell {
width: var(--cell-size);
height: var(--cell-size);
border-right: 1px solid var(--grid-color);
border-bottom: 1px solid var(--grid-color);
position: relative;
}
.cell:first-child {
border-left: 1px solid var(--grid-color);
}
.cell:nth-child(var(--num)) {
border-right: 1px solid var(--grid-color);
}
.cell:nth-child(var(--num) * n + 1) {
border-left: 1px solid var(--grid-color);
}
.cell:nth-last-child(-n + var(--num)) {
border-bottom: 1px solid var(--grid-color);
}
.trigger {
position: absolute;
width: var(--cell-size);
height: var(--cell-size);
top: 0;
left: 0;
cursor: pointer;
z-index: 10;
}
.piece {
position: absolute;
width: calc(var(--cell-size) * 0.8);
height: calc(var(--cell-size) * 0.8);
border-radius: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 0 5px rgba(0,0,0,0.5);
z-index: 5;
}
.black {
background-color: var(--black-piece);
}
.white {
background-color: var(--white-piece);
border: 1px solid #000;
}
.highlight {
border: 3px solid var(--highlight) !important;
box-shadow: 0 0 10px var(--highlight);
}
.star-point {
position: absolute;
width: 8px;
height: 8px;
background-color: var(--dot-color);
border-radius: 50%;
z-index: 2;
}
.status {
margin-top: 20px;
padding: 10px;
text-align: center;
font-size: 1.2em;
font-weight: bold;
color: #333;
}
.controls {
margin-top: 10px;
text-align: center;
}
.controls label {
margin-right: 10px;
}
.controls input {
width: 60px;
}
.winner {
color: #d32f2f;
animation: pulse 1s infinite;
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
</style>
</head>
<body>
<div class="game-container">
<div class="board" id="board"></div>
<div class="status" id="status">Black's turn</div>
<div class="controls">
<label for="boardSize">Board Size (8-15):</label>
<input type="number" id="boardSize" min="8" max="15" value="15">
<button onclick="resetGame()">New Game</button>
</div>
</div>
<script>
// Game state management
let boardSize = 15;
let board = [];
let current = 'black'; // Current player
let gameOver = false;
// DOM elements
const boardEl = document.getElementById('board');
const statusEl = document.getElementById('status');
const sizeInput = document.getElementById('boardSize');
// Initialize the game
function initGame() {
boardSize = parseInt(sizeInput.value) || 15;
// Update CSS variable for board size
document.documentElement.style.setProperty('--num', boardSize);
// Reset game state
board = Array(boardSize).fill().map(() => Array(boardSize).fill(null));
current = 'black';
gameOver = false;
// Clear the board
boardEl.innerHTML = '';
// Create star points (fixed points on board)
createStarPoints();
// Create cells and triggers
createBoard();
// Update status
updateStatus();
}
// Create star points (traditional Go board points)
function createStarPoints() {
const starPoints = getStarPoints(boardSize);
starPoints.forEach(([row, col]) => {
const star = document.createElement('div');
star.className = 'star-point';
star.style.top = ` $ {(row + 0.5) * 100 / boardSize}%`;
star.style.left = ` $ {(col + 0.5) * 100 / boardSize}%`;
boardEl.appendChild(star);
});
}
// Get star point positions based on board size
function getStarPoints(size) {
const points = [];
const center = Math.floor(size / 2);
const nearCenter = Math.floor(size / 4);
const nearEdge = Math.floor(size * 3 / 4);
// Add standard star points
if (size >= 9) {
// Center point
points.push([center, center]);
// Four corners
points.push([nearCenter, nearCenter]);
points.push([nearCenter, nearEdge]);
points.push([nearEdge, nearCenter]);
points.push([nearEdge, nearEdge]);
}
return points;
}
// Create the board grid
function createBoard() {
for (let row = 0; row < boardSize; row++) {
for (let col = 0; col < boardSize; col++) {
// Create trigger for each intersection
createTrigger(row, col);
}
}
}
// Create a clickable trigger at each intersection
function createTrigger(row, col) {
const trigger = document.createElement('div');
trigger.className = 'trigger';
trigger.style.top = ` $ {row * 100 / (boardSize - 1)}%`;
trigger.style.left = ` $ {col * 100 / (boardSize - 1)}%`;
trigger.dataset.row = row;
trigger.dataset.col = col;
trigger.addEventListener('click', handleMove);
boardEl.appendChild(trigger);
}
// Handle player move
function handleMove(e) {
if (gameOver) return;
const row = parseInt(e.target.dataset.row);
const col = parseInt(e.target.dataset.col);
// Check if the position is already occupied
if (board[row][col] !== null) return;
// Place the piece
board[row][col] = current;
// Create and place the piece visually
placePiece(row, col, current);
// Check for win
if (checkWin(row, col, current)) {
endGame(current);
return;
}
// Switch player
current = current === 'black' ? 'white' : 'black';
updateStatus();
}
// Place a piece on the board visually
function placePiece(row, col, player) {
const piece = document.createElement('div');
piece.className = `piece $ {player}`;
piece.dataset.row = row;
piece.dataset.col = col;
// Position the piece at the intersection
const boardRect = boardEl.getBoundingClientRect();
const x = col * boardRect.width / (boardSize - 1);
const y = row * boardRect.height / (boardSize - 1);
piece.style.left = ` $ {x}px`;
piece.style.top = ` $ {y}px`;
boardEl.appendChild(piece);
}
// Check if the current move results in a win
function checkWin(row, col, player) {
// Check in 8 directions: horizontal, vertical, and two diagonals
const directions = [
[0, 1], // horizontal right
[1, 0], // vertical down
[1, 1], // diagonal down-right
[1, -1] // diagonal down-left
];
for (const [dx, dy] of directions) {
let count = 1; // Count the current piece
// Check in positive direction
count += countInDirection(row, col, dx, dy, player);
// Check in negative direction
count += countInDirection(row, col, -dx, -dy, player);
if (count >= 5) {
highlightWin(row, col, dx, dy, player);
return true;
}
}
return false;
}
// Count consecutive pieces in a given direction
function countInDirection(row, col, dx, dy, player) {
let count = 0;
let r = row + dx;
let c = col + dy;
while (
r >= 0 && r < boardSize &&
c >= 0 && c < boardSize &&
board[r][c] === player
) {
count++;
r += dx;
c += dy;
}
return count;
}
// Highlight the winning pieces
function highlightWin(row, col, dx, dy, player) {
// Find all pieces in the winning line
const pieces = [];
// Add pieces in positive direction
let r = row, c = col;
while (
r >= 0 && r < boardSize &&
c >= 0 && c < boardSize &&
board[r][c] === player
) {
pieces.push([r, c]);
r += dx;
c += dy;
}
// Add pieces in negative direction
r = row - dx;
c = col - dy;
while (
r >= 0 && r < boardSize &&
c >= 0 && c < boardSize &&
board[r][c] === player
) {
pieces.unshift([r, c]);
r -= dx;
c -= dy;
}
// Keep only 5 pieces (in case of more than 5 in a row)
if (pieces.length > 5) {
// Find the center and take 5 around it
const center = Math.floor(pieces.length / 2);
const start = Math.max(0, center - 2);
pieces.splice(5, pieces.length - 5);
}
// Highlight the pieces
pieces.forEach(([r, c]) => {
const pieceEl = document.querySelector(`.piece[data-row=" $ {r}"][data-col=" $ {c}"]`);
if (pieceEl) {
pieceEl.classList.add('highlight');
}
});
}
// Update the game status display
function updateStatus() {
statusEl.textContent = ` $ {current.charAt(0).toUpperCase() + current.slice(1)}'s turn`;
statusEl.className = 'status';
}
// End the game and display winner
function endGame(winner) {
gameOver = true;
statusEl.textContent = `Winner: $ {winner.charAt(0).toUpperCase() + winner.slice(1)}!`;
statusEl.classList.add('winner');
}
// Reset the game
function resetGame() {
initGame();
}
// Initialize game on load
window.addEventListener('load', initGame);
// Update board when size changes
sizeInput.addEventListener('change', function() {
const value = parseInt(this.value);
if (value >= 8 && value <= 15) {
initGame();
} else {
this.value = boardSize;
}
});
</script>
</body>
</html>Native Strategy Board Game
Create a standalone HTML file containing CSS and JavaScript to generate a native Gomoku game with a customizable board size.
Services with a clipboard icon will copy the prompt to your clipboard first.
Version History
Prompt documentation
Related Prompts
A concise English prompt to generate doodle-style illustrations with naive lines and humorous exaggeration for any subje...
A structured JSON prompt for Gemini Nano Banana Pro, aiming to generate a hyper-realistic portrait with a Canon IXUS poi...
A highly structured JSON prompt for Nano Banana Pro designed to generate a hyper-realistic portrait in the style of Cano...
Comments (0)
Be the first to comment
to start the conversation.