Skip to content
Extraits de code Groupes Projets
index.html 11,34 Kio
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title>Sudoku Thématique</title>
    <style>
        .container {
            max-width: 600px;
            margin: 20px auto;
            text-align: center;
        }
        .setup, .message, .controls {
            margin: 20px;
        }
        .board {
            display: inline-grid;
            gap: 2px;
            background: #ccc;
            padding: 2px;
            margin: 20px 0;
        }
        .cell {
            width: 60px;
            height: 60px;
            background: white;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 24px;
        }
        .cell.selected {
            background: #e3f2fd;
        }
        .cell.conflict {
            background: #ffebee;
        }
        .cell.fixed {
            background: #f5f5f5;
            cursor: not-allowed;
        }
        .icons {
            display: flex;
            gap: 10px;
            justify-content: center;
            margin: 20px;
        }
        .icon-choice {
            padding: 10px;
            cursor: pointer;
            border: 1px solid #ccc;
            border-radius: 4px;
        }
        .icon-choice:hover {
            background: #e3f2fd;
        }
        button {
            padding: 10px 20px;
            margin: 5px;
            cursor: pointer;
        }
        .message {
            font-size: 24px;
            color: #4CAF50;
            display: none;
        }
        select {
            padding: 8px;
            margin: 5px;
            font-size: 16px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="setup" id="setup">
            <h2>Choisissez la taille</h2>
            <button onclick="initGame(3)">3x3</button>
            <button onclick="initGame(9)">9x9</button>
        </div>
        <div class="controls" id="controls" style="display: none;">
            <select id="themeSelect" onchange="changeTheme()">
                <option value="jardin">Jardin</option>
                <option value="fruits">Fruits</option>
                <option value="emotions">Émotions</option>
                <option value="meteo">Météo</option>
            </select>
            <button onclick="newGame()">Nouvelle partie</button>
        </div>
        <div id="gameBoard"></div>
        <div id="message" class="message">Félicitations ! Vous avez résolu le puzzle !</div>
    </div>

    <script>
        const themes = {
            jardin: ['🌸', '🌿', '🍀', '🌺', '🌻', '🌹', '🌷', '🌼', '🍁'],
            fruits: ['🍎', '🍌', '🍇', '🍊', '🍓', '🍐', '🍑', '🍒', '🥝'],
            emotions: ['😀', '😍', '😎', '😊', '🤔', '😮', '😴', '🤓', '😇'],
            meteo: ['☀️', '🌧️', '⛈️', '🌈', '❄️', '🌤️', '🌙', '⭐', '☁️']
        };

        let size, board, selectedCell, currentTheme, fixedCells;

        function changeTheme() {
            currentTheme = document.getElementById('themeSelect').value;
            updateBoard();
            updateIconChoices();
        }

        function updateIconChoices() {
            const iconContainer = document.querySelector('.icons');
            iconContainer.innerHTML = '';
            for(let i = 0; i < size; i++) {
                const iconChoice = document.createElement('div');
                iconChoice.className = 'icon-choice';
                iconChoice.textContent = themes[currentTheme][i];
                iconChoice.onclick = () => placeIcon(i);
                iconContainer.appendChild(iconChoice);
            }
        }

        function newGame() {
            document.getElementById('setup').style.display = 'block';
            document.getElementById('controls').style.display = 'none';
            document.getElementById('gameBoard').innerHTML = '';
            document.getElementById('message').style.display = 'none';
        }

        function generateSolution(size) {
            const solution = Array(size).fill().map(() => Array(size).fill(null));
            
            function isValid(num, row, col) {
                for(let i = 0; i < size; i++) {
                    if(solution[row][i] === num || solution[i] && solution[i][col] === num) return false;
                }
                if (size === 9) {
                    const blockRow = Math.floor(row / 3) * 3;
                    const blockCol = Math.floor(col / 3) * 3;
                    for(let i = 0; i < 3; i++) {
                        for(let j = 0; j < 3; j++) {
                            if(solution[blockRow + i] && 
                               solution[blockRow + i][blockCol + j] === num) return false;
                        }
                    }
                }
                return true;
            }

            function solve(row = 0, col = 0) {
                if(col === size) {
                    row++;
                    col = 0;
                }
                if(row === size) return true;
                
                const nums = Array.from({length: size}, (_, i) => i);
                for(let i = nums.length - 1; i > 0; i--) {
                    const j = Math.floor(Math.random() * (i + 1));
                    [nums[i], nums[j]] = [nums[j], nums[i]];
                }

                for(const num of nums) {
                    if(isValid(num, row, col)) {
                        solution[row][col] = num;
                        if(solve(row, col + 1)) return true;
                        solution[row][col] = null;
                    }
                }
                return false;
            }

            solve();
            return solution;
        }

        function initGame(boardSize) {
            size = boardSize;
            const solution = generateSolution(size);
            board = Array(size).fill().map(() => Array(size).fill(null));
            fixedCells = new Set();
            currentTheme = document.getElementById('themeSelect')?.value || 'jardin';
            selectedCell = null;

            document.getElementById('setup').style.display = 'none';
            document.getElementById('controls').style.display = 'block';

            const cellsToFill = size === 3 ? 4 : 20;
            for(let i = 0; i < cellsToFill; i++) {
                const row = Math.floor(Math.random() * size);
                const col = Math.floor(Math.random() * size);
                if(board[row][col] === null) {
                    board[row][col] = solution[row][col];
                    fixedCells.add(`${row}-${col}`);
                }
            }

            createBoard();
        }

        function createBoard() {
            const gameBoard = document.getElementById('gameBoard');
            gameBoard.innerHTML = '';
            document.getElementById('message').style.display = 'none';

            const boardElement = document.createElement('div');
            boardElement.className = 'board';
            boardElement.style.gridTemplateColumns = `repeat(${size}, 1fr)`;

            for(let i = 0; i < size; i++) {
                for(let j = 0; j < size; j++) {
                    const cell = document.createElement('div');
                    cell.className = 'cell';
                    if(fixedCells.has(`${i}-${j}`)) {
                        cell.classList.add('fixed');
                    } else {
                        cell.onclick = () => selectCell(i, j);
                    }
                    if(board[i][j] !== null) {
                        cell.textContent = themes[currentTheme][board[i][j]];
                    }
                    boardElement.appendChild(cell);
                }
            }
            gameBoard.appendChild(boardElement);

            const icons = document.createElement('div');
            icons.className = 'icons';
            for(let i = 0; i < size; i++) {
                const iconChoice = document.createElement('div');
                iconChoice.className = 'icon-choice';
                iconChoice.textContent = themes[currentTheme][i];
                iconChoice.onclick = () => placeIcon(i);
                icons.appendChild(iconChoice);
            }
            gameBoard.appendChild(icons);
        }

        function selectCell(row, col) {
            if(fixedCells.has(`${row}-${col}`)) return;
            
            const cells = document.querySelectorAll('.cell');
            cells.forEach(cell => cell.classList.remove('selected'));
            cells[row * size + col].classList.add('selected');
            selectedCell = { row, col };
        }

        function placeIcon(iconIndex) {
            if(!selectedCell || fixedCells.has(`${selectedCell.row}-${selectedCell.col}`)) return;

            const { row, col } = selectedCell;
            board[row][col] = iconIndex;
            
            updateBoard();
            checkConflicts();
            checkWin();
        }

        function checkConflicts() {
            const cells = document.querySelectorAll('.cell');
            cells.forEach(cell => cell.classList.remove('conflict'));

            for(let row = 0; row < size; row++) {
                for(let col = 0; col < size; col++) {
                    if(board[row][col] === null) continue;

                    for(let i = 0; i < size; i++) {
                        if(i !== col && board[row][i] === board[row][col]) {
                            cells[row * size + col].classList.add('conflict');
                            cells[row * size + i].classList.add('conflict');
                        }
                        if(i !== row && board[i][col] === board[row][col]) {
                            cells[row * size + col].classList.add('conflict');
                            cells[i * size + col].classList.add('conflict');
                        }
                    }

                    if(size === 9) {
                        const blockRow = Math.floor(row / 3) * 3;
                        const blockCol = Math.floor(col / 3) * 3;
                        for(let i = 0; i < 3; i++) {
                            for(let j = 0; j < 3; j++) {
                                if((blockRow + i !== row || blockCol + j !== col) && 
                                   board[blockRow + i][blockCol + j] === board[row][col]) {
                                    cells[row * size + col].classList.add('conflict');
                                    cells[(blockRow + i) * size + blockCol + j].classList.add('conflict');
                                }
                            }
                        }
                    }
                }
            }
        }

        function checkWin() {
            const isFull = board.every(row => row.every(cell => cell !== null));
            if(!isFull) return;

            const hasConflicts = document.querySelectorAll('.conflict').length > 0;
            if(!hasConflicts) {
                document.getElementById('message').style.display = 'block';
            }
        }

        function updateBoard() {
            const cells = document.querySelectorAll('.cell');
            for(let row = 0; row < size; row++) {
                for(let col = 0; col < size; col++) {
                    const value = board[row][col];
                    cells[row * size + col].textContent = 
                        value !== null ? themes[currentTheme][value] : '';
                }
            }
        }
    </script>
</body>
</html>