WEB APP GENERATOR
Feed
Active: none
Key ready
Login
Guest
Gomoku Web App
aaa • Feb 18, 2026 3:09 PM
A single-page Gomoku game with a 15x15 board. The player plays as Black, and the computer as White, with a basic AI opponent.
Prompt
"Develop a fully functional Gomoku (Five in a Row) web application using a single-file HTML5, CSS, and JavaScript solution. Game Rules & Mechanics: Board: A 15x15 grid on a stylized wood-colored canvas. Players: The User plays as Black (goes first), and the Computer (PC) plays as White. Win Condition: The first to get exactly five stones in a row (horizontally, vertically, or diagonally) wins. Technical Requirements: Implement a Minimax algorithm or a heuristic-based AI that can block the player’s 3-in-a-row or 4-in-a-row threats and prioritize its own winning lines. Include a clear Status Indicator showing whose turn it is or who won. Add a 'Restart Game' button to clear the board and reset the state. Ensure the UI is clean, centered, and responsive."
HTML
<div id="gameContainer">
    <canvas id="gameCanvas" width="600" height="600"></canvas>
    <div id="statusIndicator">Turn: Player (Black)</div>
    <button id="restartButton">Restart Game</button>
</div>
CSS
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    margin: 0;
    font-family: Arial, sans-serif;
}

#gameContainer {
    text-align: center;
}

#gameCanvas {
    background-color: #DEB887;
    border: 1px solid #333;
    display: block;
    margin: 0 auto;
}

#statusIndicator {
    margin-top: 10px;
    font-size: 18px;
}

#restartButton {
    margin-top: 10px;
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
}
JS
(function() {
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');
    const statusIndicator = document.getElementById('statusIndicator');
    const restartButton = document.getElementById('restartButton');
    const boardSize = 15;
    const cellSize = canvas.width / boardSize;
    const board = Array.from({ length: boardSize }, () => Array(boardSize).fill(null));
    const player = 'black';
    const computer = 'white';
    let currentPlayer = player;

    function drawBoard() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
                ctx.strokeRect(i * cellSize, j * cellSize, cellSize, cellSize);
                if (board[i][j]) drawStone(i, j, board[i][j]);
            }
        }
    }

    function drawStone(x, y, color) {
        ctx.fillStyle = color;
        ctx.beginPath();
        ctx.arc((x + 0.5) * cellSize, (y + 0.5) * cellSize, cellSize / 2.5, 0, 2 * Math.PI);
        ctx.fill();
        ctx.closePath();
    }

    function handleClick(event) {
        const { offsetX, offsetY } = event;
        const x = Math.floor(offsetX / cellSize);
        const y = Math.floor(offsetY / cellSize);
        if (!board[x][y]) {
            board[x][y] = currentPlayer;
            drawBoard();
            if (checkWin(x, y, currentPlayer)) {
                statusIndicator.textContent = currentPlayer === player ? 'Player (Black) Wins!' : 'Computer (White) Wins!';
                canvas.removeEventListener('click', handleClick);
                return;
            }
            currentPlayer = currentPlayer === player ? computer : player;
            statusIndicator.textContent = `Turn: ${currentPlayer === player ? 'Player (Black)' : 'Computer (White)'}`;
            if (currentPlayer === computer) setTimeout(computerMove, 500);
        }
    }

    function checkWin(x, y, color) {
        return checkDirection(x, y, color, 1, 0) || // Horizontal
               checkDirection(x, y, color, 0, 1) || // Vertical
               checkDirection(x, y, color, 1, 1) || // Diagonal /
               checkDirection(x, y, color, 1, -1);  // Diagonal \
    }

    function checkDirection(x, y, color, dx, dy) {
        let count = 1;
        for (let sign of [-1, 1]) {
            let step = 1;
            while (true) {
                const nx = x + sign * step * dx;
                const ny = y + sign * step * dy;
                if (nx >= 0 && nx < boardSize && ny >= 0 && ny < boardSize && board[nx][ny] === color) {
                    count++;
                    step++;
                } else {
                    break;
                }
            }
        }
        return count >= 5;
    }

    function computerMove() {
        // Placeholder simple AI - chooses random empty cell
        let emptyCells = [];
        for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
                if (!board[i][j]) emptyCells.push([i, j]);
            }
        }
        const [x, y] = emptyCells[Math.floor(Math.random() * emptyCells.length)];
        board[x][y] = computer;
        drawBoard();
        if (checkWin(x, y, computer)) {
            statusIndicator.textContent = 'Computer (White) Wins!';
            canvas.removeEventListener('click', handleClick);
            return;
        }
        currentPlayer = player;
        statusIndicator.textContent = 'Turn: Player (Black)';
    }

    function restartGame() {
        for (let i = 0; i < boardSize; i++) {
            for (let j = 0; j < boardSize; j++) {
                board[i][j] = null;
            }
        }
        currentPlayer = player;
        statusIndicator.textContent = 'Turn: Player (Black)';
        drawBoard();
        canvas.addEventListener('click', handleClick);
    }

    canvas.addEventListener('click', handleClick);
    restartButton.addEventListener('click', restartGame);

    drawBoard();
})();

Comments (0)

Log in to comment.
Working...