JSFiddle - React, Tailwind, and code Playground

by gjgroen

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Boter-Kaas-en-Eieren</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="game-container">
        <h1>Boter-Kaas-en-Eieren</h1>
        <div class="board" id="board">
            <!-- Cells will be dynamically generated -->
        </div>
        <p id="message">Speler X is aan de beurt</p>
        <button id="reset">Opnieuw Spelen</button>
    </div>
    <audio id="move-sound" src="https://www.techhome.nl/muisklik.mp3"></audio>
    <script src="script.js"></script>
</body>
</html>

CSS

/* Basic styling */
body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
}

.game-container {
    text-align: center;
    background: white;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}

h1 {
    margin-bottom: 20px;
}

.board {
    display: grid;
    grid-template-columns: repeat(3, 100px);
    grid-template-rows: repeat(3, 100px);
    gap: 5px;
    margin: 20px auto;
}

.cell {
    width: 100px;
    height: 100px;
    background-color: #e0e0e0;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 2rem;
    font-weight: bold;
    cursor: pointer;
    border-radius: 5px;
    transition: background-color 0.3s;
}

.cell:hover {
    background-color: #d6d6d6;
}

#message {
    margin: 20px 0;
    font-size: 1.2rem;
}

button {
    padding: 10px 20px;
    font-size: 1rem;
    color: white;
    background-color: #007bff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s;
}

button:hover {
    background-color: #0056b3;
}

JavaScript

// JavaScript logic for Tic-Tac-Toe

const board = document.getElementById("board");
const message = document.getElementById("message");
const resetButton = document.getElementById("reset");
const moveSound = document.getElementById("move-sound");

let currentPlayer;
let boardState = Array(9).fill(null);
let isComputerOpponent = true;

function createBoard() {
    board.innerHTML = "";
    boardState.forEach((cell, index) => {
        const cellElement = document.createElement("div");
        cellElement.classList.add("cell");
        cellElement.dataset.index = index;
        cellElement.textContent = cell;
        cellElement.addEventListener("click", handleCellClick);
        board.appendChild(cellElement);
    });
}

function handleCellClick(event) {
    const index = event.target.dataset.index;

    if (boardState[index] || checkWinner() || (currentPlayer === "O" && isComputerOpponent)) {
        return;
    }

    makeMove(index);

    if (!checkWinner() && isComputerOpponent && currentPlayer === "O") {
        setTimeout(computerMove, 500);
    }
}

function makeMove(index) {
    boardState[index] = currentPlayer;
    document.querySelector(`[data-index='${index}']`).textContent = currentPlayer;

    // Play move sound
    moveSound.currentTime = 0;
    moveSound.play();

    if (checkWinner()) {
        message.textContent = `Speler ${currentPlayer} wint!`;
        return;
    }

    currentPlayer = currentPlayer === "X" ? "O" : "X";
    message.textContent = `Speler ${currentPlayer} is aan de beurt`;
}

function computerMove() {
    const emptyIndices = boardState.map((cell, index) => (cell === null ? index : null)).filter(index => index !== null);

    // Improved AI: Check for winning or blocking moves
    for (let combination of winningCombinations) {
        const [a, b, c] = combination;
        if (boardState[a] === "O" && boardState[b] === "O" && boardState[c] === null) {
            return makeMove(c);
        }
        if (boardState[a] === "O"...