多蛇竞技贪吃蛇游戏aiHTML

<!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: 'Arial', 'Microsoft YaHei', sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
            color: #e6e6e6;
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            padding: 20px;
        }
        
        .game-container {
            width: 100%;
            max-width: 1200px;
            background-color: rgba(30, 30, 46, 0.9);
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
            overflow: hidden;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .game-header {
            background: linear-gradient(90deg, #0f3460 0%, #1a5f7a 100%);
            padding: 20px;
            text-align: center;
            border-bottom: 3px solid #00b4d8;
        }
        
        .game-header h1 {
            font-size: 2.5rem;
            color: #ffffff;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
            margin-bottom: 10px;
            background: linear-gradient(90deg, #00b4d8, #90e0ef);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        
        .game-content {
            display: flex;
            padding: 20px;
            gap: 20px;
        }
        
        .control-panel {
            flex: 1;
            min-width: 300px;
            background-color: rgba(40, 40, 60, 0.8);
            border-radius: 10px;
            padding: 20px;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .game-area {
            flex: 2;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        .game-screen {
            position: relative;
            background-color: #0d1b2a;
            border: 2px solid #00b4d8;
            border-radius: 5px;
            overflow: hidden;
        }
        
        canvas {
            display: block;
        }
        
        .control-section {
            margin-bottom: 25px;
            padding-bottom: 20px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .control-section:last-child {
            margin-bottom: 0;
            padding-bottom: 0;
            border-bottom: none;
        }
        
        .control-section h3 {
            color: #90e0ef;
            margin-bottom: 15px;
            font-size: 1.2rem;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .control-section h3 i {
            color: #00b4d8;
        }
        
        .input-group {
            margin-bottom: 15px;
        }
        
        .input-group label {
            display: block;
            margin-bottom: 8px;
            color: #cccccc;
            font-size: 0.95rem;
        }
        
        .input-group input, .input-group select {
            width: 100%;
            padding: 10px 15px;
            background-color: rgba(20, 20, 35, 0.9);
            border: 1px solid rgba(0, 180, 216, 0.5);
            border-radius: 8px;
            color: white;
            font-size: 1rem;
            transition: all 0.3s;
        }
        
        .input-group input:focus, .input-group select:focus {
            outline: none;
            border-color: #00b4d8;
            box-shadow: 0 0 10px rgba(0, 180, 216, 0.3);
        }
        
        .number-input {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .number-input input {
            flex: 1;
        }
        
        .range-value {
            min-width: 40px;
            text-align: center;
            font-weight: bold;
            color: #00b4d8;
        }
        
        .ai-snake-controls {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 15px;
            margin-top: 10px;
        }
        
        .ai-snake-control {
            background-color: rgba(20, 20, 35, 0.9);
            border-radius: 8px;
            padding: 15px;
            border: 1px solid rgba(255, 255, 255, 0.1);
        }
        
        .ai-snake-control h4 {
            color: #90e0ef;
            margin-bottom: 10px;
            font-size: 1rem;
        }
        
        .map-options {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 10px;
        }
        
        .map-option {
            background-color: rgba(20, 20, 35, 0.9);
            border-radius: 8px;
            padding: 12px;
            text-align: center;
            cursor: pointer;
            border: 2px solid transparent;
            transition: all 0.3s;
        }
        
        .map-option:hover {
            border-color: rgba(0, 180, 216, 0.5);
            transform: translateY(-3px);
        }
        
        .map-option.selected {
            border-color: #00b4d8;
            background-color: rgba(0, 180, 216, 0.1);
        }
        
        .map-size {
            font-size: 1.1rem;
            font-weight: bold;
            color: #90e0ef;
            margin-bottom: 5px;
        }
        
        .map-features {
            font-size: 0.8rem;
            color: #aaaaaa;
        }
        
        .button-group {
            display: flex;
            flex-direction: column;
            gap: 10px;
            margin-top: 20px;
        }
        
        button {
            padding: 14px;
            border: none;
            border-radius: 8px;
            font-size: 1rem;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
        }
        
        #start-btn {
            background: linear-gradient(90deg, #00b4d8, #0077b6);
            color: white;
        }
        
        #start-btn:hover {
            background: linear-gradient(90deg, #0096c7, #005f8a);
            transform: translateY(-3px);
            box-shadow: 0 5px 15px rgba(0, 180, 216, 0.3);
        }
        
        #pause-btn {
            background: linear-gradient(90deg, #ff9e00, #ff9100);
            color: white;
        }
        
        #pause-btn:hover {
            background: linear-gradient(90deg, #e68900, #cc7a00);
            transform: translateY(-3px);
        }
        
        #reset-btn {
            background: linear-gradient(90deg, #ef476f, #e63946);
            color: white;
        }
        
        #reset-btn:hover {
            background: linear-gradient(90deg, #d43d63, #c1121f);
            transform: translateY(-3px);
        }
        
        .stats-panel {
            display: flex;
            justify-content: space-between;
            margin-top: 20px;
            background-color: rgba(40, 40, 60, 0.8);
            border-radius: 10px;
            padding: 15px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            width: 100%;
            max-width: 800px;
        }
        
        .stat-item {
            text-align: center;
            flex: 1;
        }
        
        .stat-label {
            font-size: 0.9rem;
            color: #90e0ef;
            margin-bottom: 5px;
        }
        
        .stat-value {
            font-size: 1.8rem;
            font-weight: bold;
            color: white;
            font-family: 'Courier New', monospace;
        }
        
        .game-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(13, 27, 42, 0.9);
            display: none;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 100;
        }
        
        .game-message {
            background: linear-gradient(135deg, #0f3460, #1a5f7a);
            padding: 40px;
            border-radius: 15px;
            text-align: center;
            border: 3px solid #00b4d8;
            max-width: 500px;
            width: 90%;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
        }
        
        .game-message h2 {
            font-size: 2.5rem;
            color: white;
            margin-bottom: 20px;
            background: linear-gradient(90deg, #00b4d8, #90e0ef);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }
        
        .game-message p {
            font-size: 1.2rem;
            margin-bottom: 25px;
            line-height: 1.5;
        }
        
        .snake-colors {
            display: flex;
            gap: 10px;
            margin-top: 15px;
            justify-content: center;
        }
        
        .color-sample {
            width: 20px;
            height: 20px;
            border-radius: 4px;
            border: 1px solid rgba(255, 255, 255, 0.3);
        }
        
        .player-color {
            background-color: #00b4d8;
        }
        
        .smart-ai-color {
            background-color: #2a9d8f;
        }
        
        .dumb-ai-color {
            background-color: #e76f51;
        }
        
        .food-color {
            background-color: #e9c46a;
        }
        
        .obstacle-color {
            background-color: #9d4edd;
        }
        
        .color-label {
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 0.8rem;
            color: #cccccc;
        }
        
        .legend {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 15px;
            flex-wrap: wrap;
        }
        
        .instructions {
            background-color: rgba(40, 40, 60, 0.8);
            border-radius: 10px;
            padding: 20px;
            margin-top: 20px;
            border: 1px solid rgba(255, 255, 255, 0.1);
            width: 100%;
            max-width: 800px;
        }
        
        .instructions h3 {
            color: #90e0ef;
            margin-bottom: 15px;
            font-size: 1.2rem;
        }
        
        .instructions ul {
            padding-left: 20px;
            color: #cccccc;
            line-height: 1.6;
        }
        
        .instructions li {
            margin-bottom: 8px;
        }
        
        @media (max-width: 1024px) {
            .game-content {
                flex-direction: column;
            }
            
            .control-panel {
                min-width: 100%;
            }
            
            .game-screen {
                width: 100%;
            }
        }
        
        @media (max-width: 768px) {
            .game-header h1 {
                font-size: 2rem;
            }
            
            .stats-panel {
                flex-wrap: wrap;
            }
            
            .stat-item {
                flex: 0 0 50%;
                margin-bottom: 15px;
            }
            
            .map-options {
                grid-template-columns: 1fr;
            }
            
            .ai-snake-controls {
                grid-template-columns: 1fr;
            }
        }
    </style>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
</head>
<body>
    <div class="game-container">
        <div class="game-header">
            <h1><i class="fas fa-gamepad"></i> 多蛇竞技贪吃蛇</h1>
            <p>控制你的蛇,与AI蛇同台竞技,成为最后的生存者!</p>
        </div>
        
        <div class="game-content">
            <div class="control-panel">
                <div class="control-section">
                    <h3><i class="fas fa-sliders-h"></i> 游戏设置</h3>
                    
                    <div class="input-group">
                        <label for="smart-ai-count">聪明AI蛇数量</label>
                        <div class="number-input">
                            <input type="range" id="smart-ai-count" min="0" max="10" value="2">
                            <span class="range-value" id="smart-ai-value">2</span>
                        </div>
                    </div>
                    
                    <div class="input-group">
                        <label for="dumb-ai-count">愚蠢AI蛇数量</label>
                        <div class="number-input">
                            <input type="range" id="dumb-ai-count" min="0" max="10" value="2">
                            <span class="range-value" id="dumb-ai-value">2</span>
                        </div>
                    </div>
                    
                    <div class="input-group">
                        <label for="game-speed">游戏速度</label>
                        <div class="number-input">
                            <input type="range" id="game-speed" min="5" max="20" value="10">
                            <span class="range-value" id="speed-value">10</span>
                        </div>
                    </div>
                </div>
                
                <div class="control-section">
                    <h3><i class="fas fa-map"></i> 地图选择</h3>
                    <div class="map-options">
                        <div class="map-option selected" data-size="50" data-obstacles="false">
                            <div class="map-size">50×50</div>
                            <div class="map-features">基础地图</div>
                        </div>
                        <div class="map-option" data-size="50" data-obstacles="true">
                            <div class="map-size">50×50</div>
                            <div class="map-features">随机障碍</div>
                        </div>
                        <div class="map-option" data-size="100" data-obstacles="false">
                            <div class="map-size">100×100</div>
                            <div class="map-features">大地图</div>
                        </div>
                        <div class="map-option" data-size="150" data-obstacles="false">
                            <div class="map-size">150×150</div>
                            <div class="map-features">超大地图</div>
                        </div>
                        <div class="map-option" data-size="100" data-obstacles="true">
                            <div class="map-size">100×100</div>
                            <div class="map-features">大地图+障碍</div>
                        </div>
                        <div class="map-option" data-size="150" data-obstacles="true">
                            <div class="map-size">150×150</div>
                            <div class="map-features">超大+障碍</div>
                        </div>
                    </div>
                </div>
                
                <div class="control-section">
                    <h3><i class="fas fa-robot"></i> AI蛇设置</h3>
                    <div class="ai-snake-controls">
                        <div class="ai-snake-control">
                            <h4><i class="fas fa-brain"></i> 聪明AI</h4>
                            <p>智能路径寻找,会避开障碍和其他蛇</p>
                        </div>
                        <div class="ai-snake-control">
                            <h4><i class="fas fa-dizzy"></i> 愚蠢AI</h4>
                            <p>随机移动,经常撞墙或撞到其他蛇</p>
                        </div>
                    </div>
                </div>
                
                <div class="control-section">
                    <h3><i class="fas fa-keyboard"></i> 控制说明</h3>
                    <ul style="color: #cccccc; padding-left: 20px; line-height: 1.6;">
                        <li><strong>W/↑</strong>: 向上移动</li>
                        <li><strong>A/←</strong>: 向左移动</li>
                        <li><strong>S/↓</strong>: 向下移动</li>
                        <li><strong>D/→</strong>: 向右移动</li>
                        <li><strong>空格键</strong>: 暂停/继续游戏</li>
                    </ul>
                </div>
                
                <div class="button-group">
                    <button id="start-btn">
                        <i class="fas fa-play"></i> 开始游戏
                    </button>
                    <button id="pause-btn">
                        <i class="fas fa-pause"></i> 暂停游戏
                    </button>
                    <button id="reset-btn">
                        <i class="fas fa-redo"></i> 重置游戏
                    </button>
                </div>
            </div>
            
            <div class="game-area">
                <div class="game-screen">
                    <canvas id="game-canvas"></canvas>
                    <div class="game-overlay" id="game-overlay">
                        <div class="game-message">
                            <h2 id="game-title">多蛇竞技贪吃蛇</h2>
                            <p id="game-message">设置游戏参数,然后点击"开始游戏"</p>
                            <button id="overlay-start-btn" style="margin-top: 20px;">
                                <i class="fas fa-play"></i> 开始游戏
                            </button>
                        </div>
                    </div>
                </div>
                
                <div class="stats-panel">
                    <div class="stat-item">
                        <div class="stat-label">玩家长度</div>
                        <div id="player-length" class="stat-value">3</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-label">存活AI蛇</div>
                        <div id="alive-ai" class="stat-value">0</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-label">食物数量</div>
                        <div id="food-count" class="stat-value">1</div>
                    </div>
                    <div class="stat-item">
                        <div class="stat-label">游戏时间</div>
                        <div id="game-time" class="stat-value">0s</div>
                    </div>
                </div>
                
                <div class="legend">
                    <div class="color-label">
                        <div class="color-sample player-color"></div>
                        <span>玩家蛇</span>
                    </div>
                    <div class="color-label">
                        <div class="color-sample smart-ai-color"></div>
                        <span>聪明AI蛇</span>
                    </div>
                    <div class="color-label">
                        <div class="color-sample dumb-ai-color"></div>
                        <span>愚蠢AI蛇</span>
                    </div>
                    <div class="color-label">
                        <div class="color-sample food-color"></div>
                        <span>食物</span>
                    </div>
                    <div class="color-label">
                        <div class="color-sample obstacle-color"></div>
                        <span>障碍物</span>
                    </div>
                </div>
                
                <div class="instructions">
                    <h3><i class="fas fa-info-circle"></i> 游戏规则</h3>
                    <ul>
                        <li>控制你的蛇(蓝色)使用方向键或WASD键移动</li>
                        <li>吃掉食物(黄色)可以增加长度</li>
                        <li>避免撞到墙壁、障碍物(紫色)或其他蛇</li>
                        <li>生存到最后,成为最长的蛇</li>
                        <li>聪明AI蛇(绿色)会智能寻找食物和躲避危险</li>
                        <li>愚蠢AI蛇(红色)会随机移动,经常自毁</li>
                    </ul>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 游戏配置
        const config = {
            gridSize: 50,
            cellSize: 0,
            obstacles: false,
            gameSpeed: 10,
            smartAICount: 2,
            dumbAICount: 2,
            foodCount: 5,
            obstacleCount: 20,
            gameRunning: false,
            gamePaused: false,
            gameTime: 0,
            gameInterval: null
        };
        
        // 游戏状态
        const gameState = {
            playerSnake: null,
            aiSnakes: [],
            food: [],
            obstacles: [],
            allSnakes: []
        };
        
        // 颜色配置
        const colors = {
            player: '#00b4d8',
            smartAI: '#2a9d8f',
            dumbAI: '#e76f51',
            food: '#e9c46a',
            obstacle: '#9d4edd',
            grid: '#14213d',
            background: '#0d1b2a'
        };
        
        // DOM元素
        const canvas = document.getElementById('game-canvas');
        const ctx = canvas.getContext('2d');
        const gameOverlay = document.getElementById('game-overlay');
        const gameTitle = document.getElementById('game-title');
        const gameMessage = document.getElementById('game-message');
        
        // 蛇类定义
        class Snake {
            constructor(x, y, color, isPlayer = false, intelligence = 'smart') {
                this.x = x;
                this.y = y;
                this.color = color;
                this.isPlayer = isPlayer;
                this.intelligence = intelligence;
                this.direction = this.getRandomDirection();
                this.body = [{x, y}];
                this.length = 3;
                this.speed = 1;
                this.alive = true;
                this.score = 0;
                this.moveCounter = 0;
                this.moveDelay = isPlayer ? 1 : (intelligence === 'smart' ? 2 : 1);
                
                // 初始化蛇身
                for (let i = 1; i < this.length; i++) {
                    this.body.push({x: x - i, y});
                }
            }
            
            getRandomDirection() {
                const directions = ['up', 'down', 'left', 'right'];
                return directions[Math.floor(Math.random() * directions.length)];
            }
            
            move() {
                if (!this.alive) return;
                
                this.moveCounter++;
                if (this.moveCounter < this.moveDelay) return;
                this.moveCounter = 0;
                
                // 保存头部位置
                const head = {x: this.body[0].x, y: this.body[0].y};
                
                // 根据方向移动头部
                switch(this.direction) {
                    case 'up': head.y--; break;
                    case 'down': head.y++; break;
                    case 'left': head.x--; break;
                    case 'right': head.x++; break;
                }
                
                // 检查边界
                if (head.x < 0 || head.x >= config.gridSize || 
                    head.y < 0 || head.y >= config.gridSize) {
                    this.die();
                    return;
                }
                
                // 检查障碍物
                for (const obstacle of gameState.obstacles) {
                    if (head.x === obstacle.x && head.y === obstacle.y) {
                        this.die();
                        return;
                    }
                }
                
                // 检查是否撞到自己或其他蛇
                for (const snake of gameState.allSnakes) {
                    if (!snake.alive) continue;
                    
                    for (let i = 0; i < snake.body.length; i++) {
                        // 对于自己,跳过头部(因为头部会移动到新位置)
                        if (snake === this && i === 0) continue;
                        
                        const segment = snake.body[i];
                        if (head.x === segment.x && head.y === segment.y) {
                            this.die();
                            return;
                        }
                    }
                }
                
                // 移动身体
                this.body.unshift(head);
                if (this.body.length > this.length) {
                    this.body.pop();
                }
                
                // 检查是否吃到食物
                for (let i = 0; i < gameState.food.length; i++) {
                    const food = gameState.food[i];
                    if (head.x === food.x && head.y === food.y) {
                        this.length++;
                        this.score += 10;
                        gameState.food.splice(i, 1);
                        spawnFood();
                        updateStats();
                        break;
                    }
                }
            }
            
            die() {
                this.alive = false;
                updateStats();
                
                // 如果是玩家死亡,结束游戏
                if (this.isPlayer) {
                    endGame(false);
                }
            }
            
            draw() {
                if (!this.alive) return;
                
                // 绘制蛇身
                for (let i = 0; i < this.body.length; i++) {
                    const segment = this.body[i];
                    
                    // 计算颜色渐变
                    const alpha = 1 - (i / this.body.length) * 0.7;
                    ctx.fillStyle = this.color;
                    ctx.globalAlpha = alpha;
                    
                    // 绘制蛇身段
                    ctx.fillRect(
                        segment.x * config.cellSize,
                        segment.y * config.cellSize,
                        config.cellSize - 1,
                        config.cellSize - 1
                    );
                    
                    // 绘制蛇眼睛(头部)
                    if (i === 0) {
                        ctx.fillStyle = 'white';
                        ctx.globalAlpha = 1;
                        
                        // 根据方向绘制眼睛
                        const eyeSize = config.cellSize / 5;
                        const offset = config.cellSize / 3;
                        
                        if (this.direction === 'right') {
                            ctx.fillRect(
                                segment.x * config.cellSize + config.cellSize - offset,
                                segment.y * config.cellSize + offset,
                                eyeSize, eyeSize
                            );
                            ctx.fillRect(
                                segment.x * config.cellSize + config.cellSize - offset,
                                segment.y * config.cellSize + config.cellSize - offset - eyeSize,
                                eyeSize, eyeSize
                            );
                        } else if (this.direction === 'left') {
                            ctx.fillRect(
                                segment.x * config.cellSize + offset - eyeSize,
                                segment.y * config.cellSize + offset,
                                eyeSize, eyeSize
                            );
                            ctx.fillRect(
                                segment.x * config.cellSize + offset - eyeSize,
                                segment.y * config.cellSize + config.cellSize - offset - eyeSize,
                                eyeSize, eyeSize
                            );
                        } else if (this.direction === 'up') {
                            ctx.fillRect(
                                segment.x * config.cellSize + offset,
                                segment.y * config.cellSize + offset - eyeSize,
                                eyeSize, eyeSize
                            );
                            ctx.fillRect(
                                segment.x * config.cellSize + config.cellSize - offset - eyeSize,
                                segment.y * config.cellSize + offset - eyeSize,
                                eyeSize, eyeSize
                            );
                        } else if (this.direction === 'down') {
                            ctx.fillRect(
                                segment.x * config.cellSize + offset,
                                segment.y * config.cellSize + config.cellSize - offset,
                                eyeSize, eyeSize
                            );
                            ctx.fillRect(
                                segment.x * config.cellSize + config.cellSize - offset - eyeSize,
                                segment.y * config.cellSize + config.cellSize - offset,
                                eyeSize, eyeSize
                            );
                        }
                    }
                }
                
                ctx.globalAlpha = 1;
            }
            
            // AI决策
            makeDecision() {
                if (this.isPlayer || !this.alive) return;
                
                if (this.intelligence === 'smart') {
                    this.smartAI();
                } else {
                    this.dumbAI();
                }
            }
            
            // 聪明AI:寻找食物并避开障碍
            smartAI() {
                // 寻找最近的食物
                let nearestFood = null;
                let nearestDistance = Infinity;
                
                for (const food of gameState.food) {
                    const distance = Math.abs(this.body[0].x - food.x) + Math.abs(this.body[0].y - food.y);
                    if (distance < nearestDistance) {
                        nearestDistance = distance;
                        nearestFood = food;
                    }
                }
                
                // 如果有食物,朝食物移动
                if (nearestFood) {
                    const directions = [];
                    
                    // 计算各个方向的价值
                    const directionValues = {
                        'up': {x: 0, y: -1, value: 0},
                        'down': {x: 0, y: 1, value: 0},
                        'left': {x: -1, y: 0, value: 0},
                        'right': {x: 1, y: 0, value: 0}
                    };
                    
                    for (const dir in directionValues) {
                        const dx = directionValues[dir].x;
                        const dy = directionValues[dir].y;
                        const newX = this.body[0].x + dx;
                        const newY = this.body[0].y + dy;
                        
                        // 检查边界
                        if (newX < 0 || newX >= config.gridSize || 
                            newY < 0 || newY >= config.gridSize) {
                            directionValues[dir].value = -1000;
                            continue;
                        }
                        
                        // 检查障碍物
                        let hitObstacle = false;
                        for (const obstacle of gameState.obstacles) {
                            if (newX === obstacle.x && newY === obstacle.y) {
                                hitObstacle = true;
                                break;
                            }
                        }
                        if (hitObstacle) {
                            directionValues[dir].value = -1000;
                            continue;
                        }
                        
                        // 检查其他蛇
                        let hitSnake = false;
                        for (const snake of gameState.allSnakes) {
                            if (!snake.alive) continue;
                            
                            for (let i = 0; i < snake.body.length; i++) {
                                // 跳过自己的头部
                                if (snake === this && i === 0) continue;
                                
                                const segment = snake.body[i];
                                if (newX === segment.x && newY === segment.y) {
                                    hitSnake = true;
                                    break;
                                }
                            }
                            if (hitSnake) break;
                        }
                        if (hitSnake) {
                            directionValues[dir].value = -500;
                            continue;
                        }
                        
                        // 计算到食物的距离
                        if (nearestFood) {
                            const distToFood = Math.abs(newX - nearestFood.x) + Math.abs(newY - nearestFood.y);
                            directionValues[dir].value = -distToFood; // 距离越近,值越大(因为是负值)
                        }
                        
                        // 避免反向移动(导致撞到自己)
                        if ((dir === 'up' && this.direction === 'down') ||
                            (dir === 'down' && this.direction === 'up') ||
                            (dir === 'left' && this.direction === 'right') ||
                            (dir === 'right' && this.direction === 'left')) {
                            directionValues[dir].value -= 50;
                        }
                    }
                    
                    // 选择最佳方向
                    let bestDirection = this.direction;
                    let bestValue = -Infinity;
                    
                    for (const dir in directionValues) {
                        if (directionValues[dir].value > bestValue) {
                            bestValue = directionValues[dir].value;
                            bestDirection = dir;
                        }
                    }
                    
                    this.direction = bestDirection;
                } else {
                    // 没有食物时随机移动
                    this.dumbAI();
                }
            }
            
            // 愚蠢AI:随机移动
            dumbAI() {
                // 20%的几率改变方向
                if (Math.random() < 0.2) {
                    const directions = ['up', 'down', 'left', 'right'];
                    // 避免立即反向移动
                    const validDirections = directions.filter(dir => {
                        return !((dir === 'up' && this.direction === 'down') ||
                                (dir === 'down' && this.direction === 'up') ||
                                (dir === 'left' && this.direction === 'right') ||
                                (dir === 'right' && this.direction === 'left'));
                    });
                    
                    if (validDirections.length > 0) {
                        this.direction = validDirections[Math.floor(Math.random() * validDirections.length)];
                    }
                }
            }
        }
        
        // 初始化游戏
        function initGame() {
            // 获取配置
            config.smartAICount = parseInt(document.getElementById('smart-ai-count').value);
            config.dumbAICount = parseInt(document.getElementById('dumb-ai-count').value);
            config.gameSpeed = parseInt(document.getElementById('game-speed').value);
            
            // 重置游戏状态
            gameState.playerSnake = null;
            gameState.aiSnakes = [];
            gameState.food = [];
            gameState.obstacles = [];
            gameState.allSnakes = [];
            config.gameTime = 0;
            
            // 设置画布大小
            const screenSize = Math.min(800, window.innerWidth - 400);
            config.cellSize = Math.floor(screenSize / config.gridSize);
            canvas.width = config.gridSize * config.cellSize;
            canvas.height = config.gridSize * config.cellSize;
            
            // 生成障碍物
            if (config.obstacles) {
                generateObstacles();
            }
            
            // 生成玩家蛇
            const playerPos = getValidPosition();
            gameState.playerSnake = new Snake(playerPos.x, playerPos.y, colors.player, true);
            gameState.allSnakes.push(gameState.playerSnake);
            
            // 生成聪明AI蛇
            for (let i = 0; i < config.smartAICount; i++) {
                const pos = getValidPosition();
                const snake = new Snake(pos.x, pos.y, colors.smartAI, false, 'smart');
                gameState.aiSnakes.push(snake);
                gameState.allSnakes.push(snake);
            }
            
            // 生成愚蠢AI蛇
            for (let i = 0; i < config.dumbAICount; i++) {
                const pos = getValidPosition();
                const snake = new Snake(pos.x, pos.y, colors.dumbAI, false, 'dumb');
                gameState.aiSnakes.push(snake);
                gameState.allSnakes.push(snake);
            }
            
            // 生成食物
            for (let i = 0; i < config.foodCount; i++) {
                spawnFood();
            }
            
            // 更新统计
            updateStats();
            
            // 绘制初始状态
            drawGame();
            
            // 显示游戏界面
            gameOverlay.style.display = 'none';
            config.gameRunning = true;
            config.gamePaused = false;
            
            // 更新游戏时间
            document.getElementById('game-time').textContent = '0s';
        }
        
        // 生成有效位置(不与其他物体重叠)
        function getValidPosition() {
            let x, y, valid;
            
            do {
                valid = true;
                x = Math.floor(Math.random() * config.gridSize);
                y = Math.floor(Math.random() * config.gridSize);
                
                // 检查是否在障碍物上
                for (const obstacle of gameState.obstacles) {
                    if (x === obstacle.x && y === obstacle.y) {
                        valid = false;
                        break;
                    }
                }
                
                // 检查是否在蛇身上
                if (valid) {
                    for (const snake of gameState.allSnakes) {
                        for (const segment of snake.body) {
                            if (x === segment.x && y === segment.y) {
                                valid = false;
                                break;
                            }
                        }
                        if (!valid) break;
                    }
                }
                
                // 检查是否在食物上
                if (valid) {
                    for (const food of gameState.food) {
                        if (x === food.x && y === food.y) {
                            valid = false;
                            break;
                        }
                    }
                }
            } while (!valid);
            
            return {x, y};
        }
        
        // 生成障碍物
        function generateObstacles() {
            gameState.obstacles = [];
            const obstacleCount = config.obstacleCount;
            
            for (let i = 0; i < obstacleCount; i++) {
                const obstacle = getValidPosition();
                gameState.obstacles.push(obstacle);
            }
        }
        
        // 生成食物
        function spawnFood() {
            const food = getValidPosition();
            gameState.food.push(food);
        }
        
        // 绘制游戏
        function drawGame() {
            // 清空画布
            ctx.fillStyle = colors.background;
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            // 绘制网格
            ctx.strokeStyle = colors.grid;
            ctx.lineWidth = 0.5;
            
            for (let x = 0; x <= config.gridSize; x++) {
                ctx.beginPath();
                ctx.moveTo(x * config.cellSize, 0);
                ctx.lineTo(x * config.cellSize, canvas.height);
                ctx.stroke();
            }
            
            for (let y = 0; y <= config.gridSize; y++) {
                ctx.beginPath();
                ctx.moveTo(0, y * config.cellSize);
                ctx.lineTo(canvas.width, y * config.cellSize);
                ctx.stroke();
            }
            
            // 绘制障碍物
            ctx.fillStyle = colors.obstacle;
            for (const obstacle of gameState.obstacles) {
                ctx.fillRect(
                    obstacle.x * config.cellSize,
                    obstacle.y * config.cellSize,
                    config.cellSize - 1,
                    config.cellSize - 1
                );
            }
            
            // 绘制食物
            ctx.fillStyle = colors.food;
            for (const food of gameState.food) {
                // 绘制圆形食物
                ctx.beginPath();
                ctx.arc(
                    food.x * config.cellSize + config.cellSize / 2,
                    food.y * config.cellSize + config.cellSize / 2,
                    config.cellSize / 2 - 2,
                    0,
                    Math.PI * 2
                );
                ctx.fill();
                
                // 添加高光效果
                ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
                ctx.beginPath();
                ctx.arc(
                    food.x * config.cellSize + config.cellSize / 3,
                    food.y * config.cellSize + config.cellSize / 3,
                    config.cellSize / 6,
                    0,
                    Math.PI * 2
                );
                ctx.fill();
                ctx.fillStyle = colors.food;
            }
            
            // 绘制所有蛇
            for (const snake of gameState.allSnakes) {
                snake.draw();
            }
        }
        
        // 更新游戏状态
        function updateGame() {
            if (!config.gameRunning || config.gamePaused) return;
            
            // 更新玩家蛇
            gameState.playerSnake.move();
            
            // 更新AI蛇并让它们做决策
            for (const snake of gameState.aiSnakes) {
                snake.makeDecision();
                snake.move();
            }
            
            // 检查游戏是否结束
            checkGameEnd();
            
            // 更新游戏时间
            config.gameTime++;
            if (config.gameTime % 10 === 0) {
                const seconds = Math.floor(config.gameTime / 10);
                document.getElementById('game-time').textContent = `${seconds}s`;
            }
            
            // 重新绘制游戏
            drawGame();
            updateStats();
        }
        
        // 更新统计信息
        function updateStats() {
            // 玩家长度
            if (gameState.playerSnake && gameState.playerSnake.alive) {
                document.getElementById('player-length').textContent = gameState.playerSnake.length;
            }
            
            // 存活AI数量
            const aliveAI = gameState.aiSnakes.filter(snake => snake.alive).length;
            document.getElementById('alive-ai').textContent = aliveAI;
            
            // 食物数量
            document.getElementById('food-count').textContent = gameState.food.length;
        }
        
        // 检查游戏是否结束
        function checkGameEnd() {
            // 检查玩家是否存活
            if (!gameState.playerSnake.alive) {
                endGame(false);
                return;
            }
            
            // 检查是否所有AI都死亡
            const aliveAI = gameState.aiSnakes.filter(snake => snake.alive).length;
            if (aliveAI === 0) {
                endGame(true);
                return;
            }
        }
        
        // 结束游戏
        function endGame(isWin) {
            config.gameRunning = false;
            clearInterval(config.gameInterval);
            
            gameOverlay.style.display = 'flex';
            if (isWin) {
                gameTitle.textContent = '胜利!';
                gameMessage.textContent = `恭喜!你击败了所有AI蛇!最终长度: ${gameState.playerSnake.length}`;
            } else {
                gameTitle.textContent = '游戏结束';
                gameMessage.textContent = `你的蛇死亡了!最终长度: ${gameState.playerSnake.length}`;
            }
        }
        
        // 开始游戏循环
        function startGameLoop() {
            if (config.gameInterval) {
                clearInterval(config.gameInterval);
            }
            
            const interval = 1000 / config.gameSpeed;
            config.gameInterval = setInterval(updateGame, interval);
        }
        
        // 暂停/继续游戏
        function togglePause() {
            if (!config.gameRunning) return;
            
            config.gamePaused = !config.gamePaused;
            
            if (config.gamePaused) {
                gameOverlay.style.display = 'flex';
                gameTitle.textContent = '游戏暂停';
                gameMessage.textContent = '按空格键或点击"继续游戏"按钮继续';
            } else {
                gameOverlay.style.display = 'none';
                startGameLoop();
            }
        }
        
        // 事件监听器
        function setupEventListeners() {
            // 滑块事件
            document.getElementById('smart-ai-count').addEventListener('input', function() {
                document.getElementById('smart-ai-value').textContent = this.value;
            });
            
            document.getElementById('dumb-ai-count').addEventListener('input', function() {
                document.getElementById('dumb-ai-value').textContent = this.value;
            });
            
            document.getElementById('game-speed').addEventListener('input', function() {
                document.getElementById('speed-value').textContent = this.value;
                if (config.gameRunning && !config.gamePaused) {
                    startGameLoop();
                }
            });
            
            // 地图选择
            document.querySelectorAll('.map-option').forEach(option => {
                option.addEventListener('click', function() {
                    document.querySelectorAll('.map-option').forEach(opt => {
                        opt.classList.remove('selected');
                    });
                    this.classList.add('selected');
                    
                    config.gridSize = parseInt(this.dataset.size);
                    config.obstacles = this.dataset.obstacles === 'true';
                });
            });
            
            // 控制按钮
            document.getElementById('start-btn').addEventListener('click', function() {
                if (!config.gameRunning) {
                    initGame();
                    startGameLoop();
                } else if (config.gamePaused) {
                    togglePause();
                }
            });
            
            document.getElementById('overlay-start-btn').addEventListener('click', function() {
                if (!config.gameRunning) {
                    initGame();
                    startGameLoop();
                } else if (config.gamePaused) {
                    togglePause();
                }
            });
            
            document.getElementById('pause-btn').addEventListener('click', togglePause);
            
            document.getElementById('reset-btn').addEventListener('click', function() {
                config.gameRunning = false;
                config.gamePaused = false;
                clearInterval(config.gameInterval);
                initGame();
                gameOverlay.style.display = 'flex';
                gameTitle.textContent = '多蛇竞技贪吃蛇';
                gameMessage.textContent = '设置游戏参数,然后点击"开始游戏"';
            });
            
            // 键盘控制
            document.addEventListener('keydown', function(e) {
                if (!config.gameRunning || !gameState.playerSnake || !gameState.playerSnake.alive) return;
                
                switch(e.key.toLowerCase()) {
                    case 'w':
                    case 'arrowup':
                        if (gameState.playerSnake.direction !== 'down') {
                            gameState.playerSnake.direction = 'up';
                        }
                        break;
                    case 's':
                    case 'arrowdown':
                        if (gameState.playerSnake.direction !== 'up') {
                            gameState.playerSnake.direction = 'down';
                        }
                        break;
                    case 'a':
                    case 'arrowleft':
                        if (gameState.playerSnake.direction !== 'right') {
                            gameState.playerSnake.direction = 'left';
                        }
                        break;
                    case 'd':
                    case 'arrowright':
                        if (gameState.playerSnake.direction !== 'left') {
                            gameState.playerSnake.direction = 'right';
                        }
                        break;
                    case ' ':
                        e.preventDefault();
                        togglePause();
                        break;
                }
            });
        }
        
        // 初始化
        window.onload = function() {
            setupEventListeners();
            
            // 初始绘制
            config.cellSize = 16;
            canvas.width = config.gridSize * config.cellSize;
            canvas.height = config.gridSize * config.cellSize;
            drawGame();
            
            // 显示开始界面
            gameOverlay.style.display = 'flex';
        };
    </script>
</body>
</html>
posted @ 2026-02-24 19:37  bz02_2023f2  阅读(3)  评论(0)    收藏  举报  来源