脚本网页 三人四字棋

博主闲得无聊,自己摸鱼做了一个游戏

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>三人四子棋</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Microsoft YaHei', sans-serif;
            background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 10px;
        }

        header {
            text-align: center;
            margin-bottom: 15px;
            width: 100%;
            max-width: 500px;
        }

        .stats {
            background: rgba(255,255,255,0.9);
            padding: 10px 20px;
            border-radius: 20px;
            display: inline-block;
            margin-bottom: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .stats span {
            margin: 0 10px;
            font-weight: bold;
            color: #2c3e50;
        }

        h1 {
            color: white;
            font-size: 2em;
            text-shadow: 2px 2px 4px rgba(0,0,0,0.2);
        }

        .players-info {
            display: flex;
            gap: 20px;
            margin-bottom: 15px;
            background: rgba(255,255,255,0.9);
            padding: 10px 20px;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .player {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.9em;
            font-weight: bold;
        }

        .player-indicator {
            width: 25px;
            height: 25px;
            border-radius: 50%;
            transition: all 0.3s;
        }

        .player1 { background: linear-gradient(135deg, #667eea, #764ba2); }
        .player2 { background: linear-gradient(135deg, #f093fb, #f5576c); }
        .player3 { background: linear-gradient(135deg, #4facfe, #00f2fe); }

        .current-turn {
            transform: scale(1.3);
            box-shadow: 0 0 15px rgba(255,215,0,0.8);
        }

        main {
            background: rgba(255,255,255,0.95);
            padding: 15px;
            border-radius: 15px;
            box-shadow: 0 5px 20px rgba(0,0,0,0.1);
            max-width: 500px;
            width: 100%;
        }

        #board {
            display: grid;
            grid-template-columns: repeat(10, 1fr);
            gap: 2px;
            background: #34495e;
            padding: 8px;
            border-radius: 10px;
            aspect-ratio: 1;
        }

        .cell {
            background: #ecf0f1;
            cursor: pointer;
            position: relative;
            border-radius: 3px;
            aspect-ratio: 1;
        }

        .cell:hover:not(.occupied) {
            background: #bdc3c7;
            transform: scale(1.05);
        }

        .piece {
            width: 80%;
            height: 80%;
            border-radius: 50%;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            animation: dropIn 0.3s ease;
            box-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }

        @keyframes dropIn {
            from { transform: translate(-50%, -50%) scale(0); opacity: 0; }
            to { transform: translate(-50%, -50%) scale(1); opacity: 1; }
        }

        .winning-piece {
            animation: pulse 1s infinite;
        }

        @keyframes pulse {
            0%, 100% { transform: translate(-50%, -50%) scale(1); }
            50% { transform: translate(-50%, -50%) scale(1.2); }
        }

        .controls {
            margin-top: 15px;
            text-align: center;
        }

        button {
            padding: 10px 20px;
            font-size: 14px;
            font-weight: bold;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            background: linear-gradient(135deg, #667eea, #764ba2);
            color: white;
            transition: all 0.3s;
        }

        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0,0,0,0.2);
        }

        .status {
            margin-top: 15px;
            text-align: center;
            font-size: 1.1em;
            font-weight: bold;
            color: #2c3e50;
            min-height: 25px;
        }

        .winner {
            color: #27ae60;
            animation: celebrate 0.5s ease;
        }

        @keyframes celebrate {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.1); }
        }

        @media (max-width: 500px) {
            #board {
                max-width: 90vw;
            }
        }
    </style>
</head>
<body>
    <header>
        <div class="stats">
            <span>胜: <span id="wins">0</span></span>
            <span>负: <span id="losses">0</span></span>
            <span>平: <span id="draws">0</span></span>
        </div>
        <h1>三人四子棋</h1>
    </header>

    <div class="players-info">
        <div class="player">
            <div class="player-indicator player1" id="indicator1"></div>
            <span>你</span>
        </div>
        <div class="player">
            <div class="player-indicator player2" id="indicator2"></div>
            <span>凤九歌</span>
        </div>
        <div class="player">
            <div class="player-indicator player3" id="indicator3"></div>
            <span>凉安</span>
        </div>
    </div>

    <main>
        <div id="board"></div>
        <div class="controls">
            <button onclick="resetGame()">重新开始</button>
        </div>
        <div class="status" id="status"></div>
    </main>

    <script>
        const BOARD_SIZE = 10;
        const WIN_COUNT = 4;
        let board, currentPlayer, gameOver;
        
        const players = {
            1: { name: '你', class: 'player1' },
            2: { name: '凤九歌', class: 'player2' },
            3: { name: '凉安', class: 'player3' }
        };

        function initGame() {
            board = Array(BOARD_SIZE).fill(null).map(() => Array(BOARD_SIZE).fill(null));
            currentPlayer = 1;
            gameOver = false;
            createBoard();
            updateStatus('');
            updateTurnIndicator();
        }

        function createBoard() {
            const boardEl = document.getElementById('board');
            boardEl.innerHTML = '';
            
            for (let row = 0; row < BOARD_SIZE; row++) {
                for (let col = 0; col < BOARD_SIZE; col++) {
                    const cell = document.createElement('div');
                    cell.className = 'cell';
                    cell.dataset.row = row;
                    cell.dataset.col = col;
                    cell.onclick = () => handleCellClick(row, col);
                    boardEl.appendChild(cell);
                }
            }
        }

        function handleCellClick(row, col) {
            if (gameOver || currentPlayer !== 1 || board[row][col]) return;
            
            makeMove(row, col, 1);
            if (!gameOver) setTimeout(aiTurn, 500);
        }

        function makeMove(row, col, player) {
            board[row][col] = player;
            
            const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
            cell.classList.add('occupied');
            cell.innerHTML = `<div class="piece ${players[player].class}"></div>`;
            
            if (checkWin(row, col, player)) {
                gameOver = true;
                highlightWinning(row, col, player);
                updateStatus(`${players[player].name} 获胜!`, true);
                updateStats(player);
            } else if (isBoardFull()) {
                gameOver = true;
                updateStatus('平局!', true);
                updateStats(0);
            } else {
                currentPlayer = currentPlayer % 3 + 1;
                updateTurnIndicator();
            }
        }

        function checkWin(row, col, player) {
            const dirs = [[[0,1],[0,-1]], [[1,0],[-1,0]], [[1,1],[-1,-1]], [[1,-1],[-1,1]]];
            
            for (const dir of dirs) {
                let count = 1;
                for (const [dr, dc] of dir) {
                    let r = row + dr, c = col + dc;
                    while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] === player) {
                        count++;
                        r += dr;
                        c += dc;
                    }
                }
                if (count >= WIN_COUNT) return true;
            }
            return false;
        }

        function highlightWinning(row, col, player) {
            const dirs = [[[0,1],[0,-1]], [[1,0],[-1,0]], [[1,1],[-1,-1]], [[1,-1],[-1,1]]];
            
            for (const dir of dirs) {
                let pieces = [{row, col}];
                let count = 1;
                
                for (const [dr, dc] of dir) {
                    let r = row + dr, c = col + dc;
                    while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] === player) {
                        pieces.push({row: r, col: c});
                        count++;
                        r += dr;
                        c += dc;
                    }
                }
                
                if (count >= WIN_COUNT) {
                    pieces.forEach(pos => {
                        const piece = document.querySelector(`[data-row="${pos.row}"][data-col="${pos.col}"] .piece`);
                        if (piece) piece.classList.add('winning-piece');
                    });
                    return;
                }
            }
        }

        function isBoardFull() {
            return board.every(row => row.every(cell => cell !== null));
        }

        function aiTurn() {
            if (gameOver) return;
            
            const move = currentPlayer === 2 ? 
                findBestMove(2, true) : findBestMove(3, false);
            
            if (move) {
                makeMove(move.row, move.col, currentPlayer);
                if (!gameOver && currentPlayer !== 1) setTimeout(aiTurn, 500);
            }
        }

        function findBestMove(player, aggressive) {
            let move = findWinningMove(player);
            if (move) return move;
            
            if (aggressive) {
                for (let p of [1, 3]) {
                    move = findWinningMove(p);
                    if (move) return move;
                }
            } else {
                for (let p of [1, 2]) {
                    move = findWinningMove(p);
                    if (move) return move;
                }
            }
            
            let bestScore = -1, bestMove = null;
            for (let row = 0; row < BOARD_SIZE; row++) {
                for (let col = 0; col < BOARD_SIZE; col++) {
                    if (!board[row][col]) {
                        const score = evaluatePosition(row, col, player);
                        if (score > bestScore) {
                            bestScore = score;
                            bestMove = {row, col};
                        }
                    }
                }
            }
            return bestMove;
        }

        function findWinningMove(player) {
            for (let row = 0; row < BOARD_SIZE; row++) {
                for (let col = 0; col < BOARD_SIZE; col++) {
                    if (!board[row][col]) {
                        board[row][col] = player;
                        if (checkWin(row, col, player)) {
                            board[row][col] = null;
                            return {row, col};
                        }
                        board[row][col] = null;
                    }
                }
            }
            return null;
        }

        function evaluatePosition(row, col, player) {
            let score = 0;
            const dirs = [[0,1], [1,0], [1,1], [1,-1]];
            
            for (const [dr, dc] of dirs) {
                let count = 0, open = 0;
                
                for (const [rDir, cDir] of [[dr, dc], [-dr, -dc]]) {
                    let r = row + rDir, c = col + cDir;
                    while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) {
                        if (board[r][c] === player) count++;
                        else if (!board[r][c]) { open++; break; }
                        else break;
                        r += rDir;
                        c += cDir;
                    }
                }
                
                if (count >= 3) score += 100;
                else if (count === 2 && open >= 1) score += 10;
                else if (count === 1 && open >= 2) score += 1;
            }
            
            const center = BOARD_SIZE / 2;
            score += Math.max(0, 5 - (Math.abs(row - center) + Math.abs(col - center)));
            
            return score;
        }

        function updateTurnIndicator() {
            document.querySelectorAll('.player-indicator').forEach(el => 
                el.classList.remove('current-turn'));
            document.getElementById(`indicator${currentPlayer}`).classList.add('current-turn');
        }

        function updateStatus(msg, isWinner = false) {
            const status = document.getElementById('status');
            status.textContent = msg;
            status.className = isWinner ? 'status winner' : 'status';
        }

        function updateStats(winner) {
            const stats = JSON.parse(localStorage.getItem('gameStats') || '{"wins":0,"losses":0,"draws":0}');
            
            if (winner === 1) stats.wins++;
            else if (winner === 0) stats.draws++;
            else stats.losses++;
            
            localStorage.setItem('gameStats', JSON.stringify(stats));
            document.getElementById('wins').textContent = stats.wins;
            document.getElementById('losses').textContent = stats.losses;
            document.getElementById('draws').textContent = stats.draws;
        }

        function loadStats() {
            const stats = JSON.parse(localStorage.getItem('gameStats') || '{"wins":0,"losses":0,"draws":0}');
            document.getElementById('wins').textContent = stats.wins;
            document.getElementById('losses').textContent = stats.losses;
            document.getElementById('draws').textContent = stats.draws;
        }

        function resetGame() {
            initGame();
        }

        loadStats();
        initGame();
    </script>
</body>
</html>
相关推荐
莫物2 小时前
element el-table表格 添加唯一标识
前端·javascript·vue.js
我看刑2 小时前
【已解决】el-table 前端分页多选、跨页全选等
前端·vue·element
凯_kyle2 小时前
Python 算法竞赛 —— 基础篇(更新ing)
笔记·python·算法
小光学长2 小时前
基于ssm的考研复习平台w0ws1848(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库
-大头.2 小时前
数据库高可用架构终极指南
数据库·架构
我会一直在的2 小时前
Fiddler基础使用介绍
前端·测试工具·fiddler
小明记账簿2 小时前
前端文件流下载方法封装
前端
Elastic 中国社区官方博客2 小时前
Elasticsearch:构建一个 AI 驱动的电子邮件钓鱼检测
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
lizz312 小时前
C++操作符重载深度解析
java·c++·算法