电脑没网时可以做的事(html)

· · 休闲·娱乐

下面是用HTML编写的五子棋离线游戏:
  1. 先在电脑桌面新建文本文档;
  2. 将下面代码复制进去,保存;
  3. 将文件改为HTML格式(.html),回车;
  4. 选择用浏览器打开它,就可以了。

可在评论区改进代码,觉得好的话可以关注作者

代码如下(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;
            font-family: "Microsoft YaHei", sans-serif;
        }

        body {
            display: flex;
            flex-direction: column;
            align-items: center;
            background-color: #f5f5f5;
            padding: 20px;
        }

        .game-container {
            display: flex;
            align-items: flex-start;
            gap: 30px;
            margin-top: 20px;
        }

        .game-info {
            width: 200px;
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .game-info h2 {
            color: #333;
            margin-bottom: 15px;
            text-align: center;
        }

        .difficulty {
            margin: 15px 0;
        }

        .difficulty h3 {
            font-size: 16px;
            color: #666;
            margin-bottom: 10px;
            text-align: center;
        }

        .difficulty-buttons {
            display: flex;
            gap: 5px;
            justify-content: center;
        }

        .diff-btn {
            padding: 5px 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            background-color: #f8f8f8;
            cursor: pointer;
            transition: all 0.2s;
            font-size: 14px;
        }

        .diff-btn.active {
            background-color: #4CAF50;
            color: white;
            border-color: #4CAF50;
        }

        .diff-btn:hover:not(.active) {
            background-color: #eee;
        }

        .status {
            font-size: 18px;
            margin: 20px 0;
            color: #555;
            text-align: center;
        }

        #reset-btn {
            width: 100%;
            padding: 10px;
            background-color: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            font-size: 16px;
            cursor: pointer;
            transition: background-color 0.3s;
            margin-top: 15px;
        }

        #reset-btn:hover {
            background-color: #45a049;
        }

        .chessboard {
            display: grid;
            grid-template-columns: repeat(15, 30px);
            grid-template-rows: repeat(15, 30px);
            gap: 1px;
            background-color: #e6b87d;
            padding: 5px;
            border-radius: 5px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
        }

        .chess-cell {
            width: 30px;
            height: 30px;
            background-color: #e6b87d;
            position: relative;
            cursor: pointer;
        }

        /* 棋盘网格线 */
        .chess-cell::before {
            content: '';
            position: absolute;
            width: 1px;
            height: 100%;
            background-color: #8b5a2b;
            left: 50%;
            top: 0;
            transform: translateX(-50%);
        }

        .chess-cell::after {
            content: '';
            position: absolute;
            height: 1px;
            width: 100%;
            background-color: #8b5a2b;
            top: 50%;
            left: 0;
            transform: translateY(-50%);
        }

        /* 去掉边缘的网格线 */
        .chess-cell:first-child::before,
        .chess-cell:nth-child(15n+1)::before {
            display: none;
        }

        .chess-cell:nth-child(-n+15)::after {
            display: none;
        }

        /* 棋子样式 */
        .chess {
            position: absolute;
            width: 26px;
            height: 26px;
            border-radius: 50%;
            top: 2px;
            left: 2px;
            z-index: 10;
            box-shadow: 0 2px 5px rgba(0,0,0,0.3);
        }

        .black {
            background-color: #000;
        }

        .white {
            background-color: #fff;
            border: 1px solid #ddd;
        }

        /* 胜利提示 */
        .win-message {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: rgba(0,0,0,0.8);
            color: white;
            padding: 30px 50px;
            border-radius: 10px;
            font-size: 24px;
            z-index: 100;
            display: none;
        }
    </style>
</head>
<body>
    <h1>离线五子棋 - 人机对战</h1>
    <div class="game-container">
        <div class="chessboard" id="chessboard"></div>
        <div class="game-info">
            <h2>游戏信息</h2>
            <div class="difficulty">
                <h3>选择难度</h3>
                <div class="difficulty-buttons">
                    <button class="diff-btn active" data-level="easy">简单</button>
                    <button class="diff-btn" data-level="medium">中等</button>
                    <button class="diff-btn" data-level="hard">困难</button>
                </div>
            </div>
            <div class="status" id="game-status">你的回合 (黑子)</div>
            <button id="reset-btn">重新开始</button>
        </div>
    </div>
    <div class="win-message" id="win-message"></div>

    <script>
        // 游戏状态常量
        const EMPTY = 0;
        const BLACK = 1; // 玩家
        const WHITE = 2; // AI

        // 难度等级常量
        const DIFFICULTY = {
            EASY: 'easy',
            MEDIUM: 'medium',
            HARD: 'hard'
        };

        // 游戏变量
        let chessboard = Array(15).fill().map(() => Array(15).fill(EMPTY));
        let gameOver = false;
        let currentPlayer = BLACK;
        let currentDifficulty = DIFFICULTY.EASY; // 默认简单难度

        // 获取DOM元素
        const chessboardDom = document.getElementById('chessboard');
        const gameStatus = document.getElementById('game-status');
        const resetBtn = document.getElementById('reset-btn');
        const winMessage = document.getElementById('win-message');
        const difficultyButtons = document.querySelectorAll('.diff-btn');

        // 初始化棋盘
        function initChessboard() {
            chessboardDom.innerHTML = '';
            chessboard = Array(15).fill().map(() => Array(15).fill(EMPTY));
            gameOver = false;
            currentPlayer = BLACK;
            gameStatus.textContent = `你的回合 (黑子) - ${getDifficultyText()}`;
            winMessage.style.display = 'none';

            // 创建15x15的棋盘格子
            for (let row = 0; row < 15; row++) {
                for (let col = 0; col < 15; col++) {
                    const cell = document.createElement('div');
                    cell.className = 'chess-cell';
                    cell.dataset.row = row;
                    cell.dataset.col = col;

                    // 点击落子事件
                    cell.addEventListener('click', () => handleCellClick(row, col));

                    chessboardDom.appendChild(cell);
                }
            }
        }

        // 获取难度显示文本
        function getDifficultyText() {
            switch(currentDifficulty) {
                case DIFFICULTY.EASY: return '简单难度';
                case DIFFICULTY.MEDIUM: return '中等难度';
                case DIFFICULTY.HARD: return '困难难度';
                default: return '简单难度';
            }
        }

        // 处理难度选择
        function handleDifficultyChange(level) {
            // 如果游戏中切换难度,提示重新开始
            if (!gameOver && !isBoardEmpty()) {
                if (confirm('切换难度将重新开始游戏,确定吗?')) {
                    currentDifficulty = level;
                    updateDifficultyButtons();
                    initChessboard();
                }
            } else {
                currentDifficulty = level;
                updateDifficultyButtons();
                gameStatus.textContent = `你的回合 (黑子) - ${getDifficultyText()}`;
            }
        }

        // 检查棋盘是否为空
        function isBoardEmpty() {
            for (let row = 0; row < 15; row++) {
                for (let col = 0; col < 15; col++) {
                    if (chessboard[row][col] !== EMPTY) {
                        return false;
                    }
                }
            }
            return true;
        }

        // 更新难度按钮样式
        function updateDifficultyButtons() {
            difficultyButtons.forEach(btn => {
                if (btn.dataset.level === currentDifficulty) {
                    btn.classList.add('active');
                } else {
                    btn.classList.remove('active');
                }
            });
        }

        // 处理格子点击事件
        function handleCellClick(row, col) {
            // 游戏结束或位置已有棋子则返回
            if (gameOver || chessboard[row][col] !== EMPTY) return;

            // 玩家落子(黑子)
            placeChess(row, col, BLACK);

            // 检查玩家是否获胜
            if (checkWin(row, col, BLACK)) {
                gameOver = true;
                gameStatus.textContent = `恭喜你获胜! - ${getDifficultyText()}`;
                winMessage.textContent = '恭喜你获胜!';
                winMessage.style.display = 'block';
                return;
            }

            // 检查是否平局
            if (checkDraw()) {
                gameOver = true;
                gameStatus.textContent = `平局! - ${getDifficultyText()}`;
                winMessage.textContent = '平局!';
                winMessage.style.display = 'block';
                return;
            }

            // AI回合
            gameStatus.textContent = `AI思考中... - ${getDifficultyText()}`;
            setTimeout(() => aiMove(), 500); // 延迟500ms,模拟思考
        }

        // 落子函数
        function placeChess(row, col, player) {
            chessboard[row][col] = player;

            // 创建棋子DOM元素
            const cell = document.querySelector(`[data-row="${row}"][data-col="${col}"]`);
            const chess = document.createElement('div');
            chess.className = `chess ${player === BLACK ? 'black' : 'white'}`;
            cell.appendChild(chess);
        }

        // 评估位置得分(核心AI逻辑)
        function evaluatePosition(row, col, player) {
            let score = 0;
            const opponent = player === BLACK ? WHITE : BLACK;

            // 检查四个方向
            const directions = [[0, 1], [1, 0], [1, 1], [1, -1]];

            for (const [dx, dy] of directions) {
                let count = 0;      // 连续棋子数
                let empty = 0;      // 两端空位数量
                let block = 0;      // 被阻挡的端数

                // 正向检查
                let r = row + dx;
                let c = col + dy;
                while (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === player) {
                    count++;
                    r += dx;
                    c += dy;
                }
                // 检查正向末端
                if (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === EMPTY) {
                    empty++;
                } else if (r >= 0 && r < 15 && c >= 0 && c < 15) {
                    block++;
                }

                // 反向检查
                r = row - dx;
                c = col - dy;
                while (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === player) {
                    count++;
                    r -= dx;
                    c -= dy;
                }
                // 检查反向末端
                if (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] === EMPTY) {
                    empty++;
                } else if (r >= 0 && r < 15 && c >= 0 && c < 15) {
                    block++;
                }

                // 根据连续棋子数和两端情况打分
                if (count >= 4) score += 100000;    // 五连(必胜)
                else if (count === 3 && empty === 2) score += 10000; // 活四
                else if (count === 3 && empty === 1) score += 1000;  // 冲四
                else if (count === 2 && empty === 2) score += 100;   // 活三
                else if (count === 2 && empty === 1) score += 10;    // 冲三
                else if (count === 1 && empty === 2) score += 5;     // 活二
            }

            return score;
        }

        // AI落子逻辑(根据难度调整)
        function aiMove() {
            if (gameOver) return;

            let bestScore = -1;
            let bestPos = null;
            let allPossibleMoves = [];

            // 遍历所有空位,计算得分
            for (let row = 0; row < 15; row++) {
                for (let col = 0; col < 15; col++) {
                    if (chessboard[row][col] !== EMPTY) continue;

                    // 1. 计算AI落在此处的得分(进攻)
                    const aiScore = evaluatePosition(row, col, WHITE);
                    // 2. 计算玩家落在此处的得分(防守)
                    const playerScore = evaluatePosition(row, col, BLACK);

                    // 综合得分:防守优先级高于进攻
                    const totalScore = Math.max(aiScore, playerScore * 1.1);

                    allPossibleMoves.push({
                        row,
                        col,
                        score: totalScore
                    });

                    // 更新最佳位置
                    if (totalScore > bestScore) {
                        bestScore = totalScore;
                        bestPos = { row, col };
                    }
                }
            }

            // 根据难度调整AI落子策略
            switch(currentDifficulty) {
                case DIFFICULTY.EASY:
                    // 简单难度:30%概率选择非最佳位置
                    if (Math.random() < 0.3 && allPossibleMoves.length > 1) {
                        // 过滤掉最高分的位置
                        const filteredMoves = allPossibleMoves.filter(move => move.score < bestScore);
                        if (filteredMoves.length > 0) {
                            const randomIndex = Math.floor(Math.random() * filteredMoves.length);
                            bestPos = filteredMoves[randomIndex];
                        }
                    }
                    break;

                case DIFFICULTY.MEDIUM:
                    // 中等难度:15%概率选择非最佳位置
                    if (Math.random() < 0.15 && allPossibleMoves.length > 1) {
                        const filteredMoves = allPossibleMoves.filter(move => move.score < bestScore);
                        if (filteredMoves.length > 0) {
                            const randomIndex = Math.floor(Math.random() * filteredMoves.length);
                            bestPos = filteredMoves[randomIndex];
                        }
                    }
                    break;

                case DIFFICULTY.HARD:
                    // 困难难度:总是选择最佳位置
                    break;
            }

            // 如果没有找到有价值的位置,选择已有棋子周围的空位(兜底)
            if (!bestPos) {
                const emptyPositions = [];
                for (let row = 0; row < 15; row++) {
                    for (let col = 0; col < 15; col++) {
                        if (chessboard[row][col] === EMPTY) {
                            // 检查周围是否有棋子(3x3范围)
                            let hasNearChess = false;
                            for (let dr = -1; dr <= 1; dr++) {
                                for (let dc = -1; dc <= 1; dc++) {
                                    const r = row + dr;
                                    const c = col + dc;
                                    if (r >= 0 && r < 15 && c >= 0 && c < 15 && chessboard[r][c] !== EMPTY) {
                                        hasNearChess = true;
                                        break;
                                    }
                                }
                                if (hasNearChess) break;
                            }
                            if (hasNearChess || emptyPositions.length === 0) {
                                emptyPositions.push({ row, col });
                            }
                        }
                    }
                }
                bestPos = emptyPositions[Math.floor(Math.random() * emptyPositions.length)];
            }

            // AI落子
            placeChess(bestPos.row, bestPos.col, WHITE);

            // 检查AI是否获胜
            if (checkWin(bestPos.row, bestPos.col, WHITE)) {
                gameOver = true;
                gameStatus.textContent = `AI获胜! - ${getDifficultyText()}`;
                winMessage.textContent = 'AI获胜!';
                winMessage.style.display = 'block';
                return;
            }

            // 检查是否平局
            if (checkDraw()) {
                gameOver = true;
                gameStatus.textContent = `平局! - ${getDifficultyText()}`;
                winMessage.textContent = '平局!';
                winMessage.style.display = 'block';
                return;
            }

            // 回到玩家回合
            currentPlayer = BLACK;
            gameStatus.textContent = `你的回合 (黑子) - ${getDifficultyText()}`;
        }

        // 检查是否获胜
        function checkWin(row, col, player) {
            // 检查方向:横向、竖向、左对角线、右对角线
            const directions = [
                [0, 1],  // 横向
                [1, 0],  // 竖向
                [1, 1],  // 右对角线
                [1, -1]  // 左对角线
            ];

            for (const [dx, dy] of directions) {
                let count = 1; // 当前位置已有一个棋子

                // 正向检查
                for (let i = 1; i < 5; i++) {
                    const newRow = row + dx * i;
                    const newCol = col + dy * i;
                    if (newRow >= 0 && newRow < 15 && newCol >= 0 && newCol < 15 && chessboard[newRow][newCol] === player) {
                        count++;
                    } else {
                        break;
                    }
                }

                // 反向检查
                for (let i = 1; i < 5; i++) {
                    const newRow = row - dx * i;
                    const newCol = col - dy * i;
                    if (newRow >= 0 && newRow < 15 && newCol >= 0 && newCol < 15 && chessboard[newRow][newCol] === player) {
                        count++;
                    } else {
                        break;
                    }
                }

                // 五子连珠
                if (count >= 5) {
                    return true;
                }
            }

            return false;
        }

        // 检查是否平局
        function checkDraw() {
            for (let row = 0; row < 15; row++) {
                for (let col = 0; col < 15; col++) {
                    if (chessboard[row][col] === EMPTY) {
                        return false; // 还有空位置,不是平局
                    }
                }
            }
            return true; // 棋盘已满,平局
        }

        // 绑定事件监听
        resetBtn.addEventListener('click', initChessboard);

        // 难度选择按钮事件
        difficultyButtons.forEach(btn => {
            btn.addEventListener('click', () => {
                handleDifficultyChange(btn.dataset.level);
            });
        });

        // 初始化游戏
        initChessboard();
    </script>
</body>
</html>