恭请赏玩:

斗地主 - 修行版

网页源码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <!-- 针对iOS设备的优化 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
    <title>斗地主 - 修行版</title>
    <style>
        /* 基础重置 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            -webkit-tap-highlight-color: transparent; /* 移除点击高亮 */
            -webkit-touch-callout: none; /* 禁止长按菜单 */
            -webkit-user-select: none; /* 禁止文本选择 */
            user-select: none;
        }
        
        /* 针对iOS Safari的特定修复 */
        input {
            -webkit-user-select: text; /* 输入框允许选择文本 */
            user-select: text;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
            background-image: url('lianchi.jpg');
            background-repeat: repeat;
            background-size: auto;
            color: #fff;
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            padding: 10px;
            overflow-x: hidden;
            /* 防止iOS橡皮筋效果 */
            position: fixed;
            width: 100%;
            height: 100%;
        }
        
        /* 游戏区域容器 */
        .game-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            max-width: 1200px;
            margin: 0 auto;
            width: 100%;
            overflow: hidden;
        }
        
        .header {
            text-align: center;
            padding: 12px 0;
            margin-bottom: 10px;
            background-color: rgba(0, 0, 0, 0.7);
            border-radius: 12px;
            margin: 10px;
            border: 2px solid #ffcc00;
            position: relative;
            z-index: 10;
        }
        
        h1 {
            color: #ffcc00;
            font-size: 1.8rem;
            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
            margin-bottom: 5px;
        }
        
        /* 游戏信息区域 - 优化移动端显示 */
        .game-info {
            display: flex;
            justify-content: center;
            margin-bottom: 15px;
            width: 100%;
            padding: 0 10px;
        }
        
        .info-item {
            background-color: rgba(0, 0, 0, 0.7);
            border-radius: 10px;
            padding: 12px 20px;
            text-align: center;
            border: 2px solid #ffcc00;
            min-width: 180px;
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
        }
        
        .info-label {
            font-size: 0.95rem;
            color: #ffcc00;
            margin-bottom: 6px;
        }
        
        .info-value {
            font-size: 1.5rem;
            font-weight: bold;
        }
        
        /* 游戏主区域 */
        .game-area {
            display: flex;
            flex-direction: column;
            align-items: center;
            flex: 1;
            position: relative;
            width: 100%;
            padding: 0 5px;
        }
        
        /* 对手区域优化 */
        .opponent-area {
            display: flex;
            justify-content: space-between;
            width: 100%;
            margin-bottom: 20px;
            min-height: 120px;
        }
        
        .opponent {
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 8px;
            background-color: rgba(0, 0, 0, 0.7);
            border-radius: 10px;
            transition: all 0.3s;
            border: 2px solid #4a752c;
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
        }
        
        .opponent.active {
            background-color: rgba(255, 204, 0, 0.3);
            border: 2px solid #ffcc00;
            box-shadow: 0 0 15px rgba(255, 204, 0, 0.5);
        }
        
        .opponent-name {
            font-size: 1rem;
            margin-bottom: 8px;
            color: #ffcc00;
            text-align: center;
        }
        
        /* 牌背样式 */
        .card-stack {
            display: flex;
            height: 80px;
            position: relative;
            justify-content: center;
            width: 100%;
            min-width: 80px;
        }
        
        .card-back {
            width: 50px;
            height: 70px;
            background-image: url('wuliangsofo_s.jpg');
            background-size: cover;
            background-position: center;
            border-radius: 6px;
            border: 2px solid #fff;
            box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
            position: absolute;
            top: 0;
        }
        
        /* 中央区域 - 优化移动端 */
        .center-area {
            display: flex;
            flex-direction: column;
            align-items: center;
            margin-bottom: 10px;
            width: 100%;
            min-height: 180px;
        }
        
        /* 出牌区域 - 移动端优化 */
        .played-cards {
            display: flex;
            justify-content: center;
            flex-wrap: wrap;
            min-height: 120px;
            width: 100%;
            position: relative;
            margin-bottom: 15px;
            padding: 10px;
            gap: 5px;
            background-color: rgba(0, 0, 0, 0.6);
            border-radius: 12px;
            border: 3px solid #ffcc00;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
            overflow-x: auto;
            -webkit-overflow-scrolling: touch; /* iOS滑动优化 */
        }
        
        /* 已出牌样式 */
        .played-card {
            width: 60px;
            height: 85px;
            border-radius: 8px;
            border: 2px solid #fff;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding: 4px;
            background-color: white;
            color: #333;
            flex-shrink: 0;
            overflow: hidden;
        }
        
        .played-card .card-corner {
            font-size: 0.8rem;
            display: flex;
            flex-direction: column;
            align-items: center;
            line-height: 1;
            margin: 1px 0;
        }
        
        .played-card .card-center {
            font-size: 1.5rem;
            align-self: center;
            line-height: 1;
            margin: 3px 0;
        }
        
        /* 游戏状态 */
        .game-status {
            text-align: center;
            font-size: 1.1rem;
            color: #ffcc00;
            padding: 12px 15px;
            background-color: rgba(0, 0, 0, 0.7);
            border-radius: 10px;
            width: 100%;
            min-height: 50px;
            display: flex;
            align-items: center;
            justify-content: center;
            border: 2px solid #ffcc00;
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
        }
        
        /* 玩家区域 - 移动端优化 */
        .player-area {
            width: 100%;
            background-color: rgba(0, 0, 0, 0.7);
            border-radius: 12px;
            padding: 15px;
            border: 2px solid #4a752c;
            transition: all 0.3s;
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
            min-height: 180px;
            display: flex;
            flex-direction: column;
        }
        
        .player-area.active {
            border-color: #ffcc00;
            box-shadow: 0 0 20px rgba(255, 204, 0, 0.6);
        }
        
        .player-name {
            font-size: 1.2rem;
            color: #ffcc00;
            text-align: center;
            margin-bottom: 15px;
        }
        
        /* 玩家手牌容器 - 优化触摸区域 */
        .player-cards-container {
            display: flex;
            justify-content: center;
            position: relative;
            width: 100%;
            padding: 8px 0;
            overflow-x: auto;
            -webkit-overflow-scrolling: touch; /* iOS滑动优化 */
            flex: 1;
            min-height: 100px;
        }
        
        .player-card-stack {
            display: flex;
            position: relative;
            height: 100px;
            min-width: min-content;
            padding: 0 5px;
            align-items: flex-end;
        }
        
        /* 玩家手牌 - 增大触摸区域 */
        .player-card {
            width: 60px;
            height: 85px;
            border-radius: 8px;
            border: 2px solid #fff;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
            display: flex;
            flex-direction: column;
            justify-content: space-between;
            padding: 5px;
            position: relative;
            transition: transform 0.2s, margin-left 0.2s, z-index 0.2s;
            background-color: white;
            color: #333;
            cursor: pointer;
            flex-shrink: 0;
            margin-left: -15px;
            overflow: hidden;
        }
        
        .player-card .card-corner {
            font-size: 0.9rem;
            display: flex;
            flex-direction: column;
            align-items: center;
            line-height: 1;
            margin: 1px 0;
        }
        
        .player-card .card-center {
            font-size: 1.8rem;
            align-self: center;
            line-height: 1;
            margin: 3px 0;
        }
        
        .player-card:first-child {
            margin-left: 0;
        }
        
        /* 优化触摸交互 */
        .player-card:hover,
        .player-card:active {
            transform: translateY(-10px);
            z-index: 100 !important;
        }
        
        .player-card.selected {
            transform: translateY(-15px);
            border-color: #ffcc00;
            box-shadow: 0 8px 16px rgba(255, 204, 0, 0.5);
            z-index: 200 !important;
        }
        
        /* 颜色样式 */
        .card.red {
            color: #e53935;
        }
        
        .card.black {
            color: #333;
        }
        
        .card-joker {
            width: 100%;
            height: 100%;
            background-size: cover;
            background-position: center;
            border-radius: 6px;
        }
        
        /* 按钮区域 - 优化移动端 */
        .controls-container {
            width: 100%;
            max-width: 1200px;
            margin: 15px auto 10px;
            padding: 0 10px;
        }
        
        .controls {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 8px;
            width: 100%;
        }
        
        .btn {
            padding: 12px 8px;
            font-size: 0.95rem;
            background-color: #ffcc00;
            color: #8b0000;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-weight: bold;
            transition: all 0.2s;
            box-shadow: 0 3px 0 #cc9900;
            min-height: 44px; /* iOS最小触摸区域 */
            -webkit-appearance: none;
        }
        
        .btn:active {
            transform: translateY(2px);
            box-shadow: 0 1px 0 #cc9900;
        }
        
        .btn:disabled {
            background-color: #666;
            color: #999;
            cursor: not-allowed;
            transform: none;
            box-shadow: 0 3px 0 #444;
        }
        
        /* 音乐按钮 */
        .btn.music-btn {
            background-color: #4a752c;
            color: #ffcc00;
            box-shadow: 0 3px 0 #3a5c22;
        }
        
        .btn.music-btn.music-on {
            background-color: #8b0000;
            color: #ffcc00;
            box-shadow: 0 3px 0 #660000;
        }
        
        /* 弹窗样式优化 */
        .landlord-selection,
        .merit-transfer {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.95);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            padding: 20px;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }
        
        .selection-box,
        .merit-box {
            background-color: #2a5c2a;
            padding: 20px;
            border-radius: 15px;
            border: 3px solid #ffcc00;
            text-align: center;
            width: 90%;
            max-width: 400px;
            margin-bottom: 20px;
        }
        
        .selection-title,
        .merit-title {
            color: #ffcc00;
            font-size: 1.5rem;
            margin-bottom: 15px;
        }
        
        .selection-buttons,
        .merit-buttons {
            display: flex;
            flex-direction: column;
            gap: 12px;
            margin-top: 20px;
            width: 100%;
        }
        
        .selection-btn,
        .merit-btn {
            padding: 14px;
            font-size: 1.1rem;
            background-color: #ffcc00;
            color: #8b0000;
            border: none;
            border-radius: 10px;
            cursor: pointer;
            font-weight: bold;
            min-height: 50px;
        }
        
        .merit-input {
            padding: 12px;
            font-size: 1rem;
            border: 2px solid #ffcc00;
            border-radius: 8px;
            background-color: rgba(255, 255, 255, 0.9);
            color: #333;
            width: 100%;
            margin-top: 10px;
        }
        
        /* 功德牌样式 */
        .landlord-cards {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin: 15px 0;
            flex-wrap: wrap;
        }
        
        .landlord-card-back {
            width: 60px;
            height: 85px;
            background-image: url('wuliangsofo_s.jpg');
            background-size: cover;
            background-position: center;
            border-radius: 8px;
            border: 2px solid #ffcc00;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
        }
        
        /* 功德数动画 */
        .merit-value {
            color: #ffcc00;
            text-shadow: 0 0 10px rgba(255, 204, 0, 0.7);
            animation: pulse 2s infinite;
        }
        
        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.7; }
        }
        
        .merit-up {
            animation: meritUp 1s ease-out;
        }
        
        @keyframes meritUp {
            0% { transform: scale(1); }
            50% { transform: scale(1.3); }
            100% { transform: scale(1); }
        }
        
        /* 功德回向确认消息 */
        .merit-confirm {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: #2a5c2a;
            padding: 20px;
            border-radius: 12px;
            border: 3px solid #ffcc00;
            text-align: center;
            z-index: 1002;
            max-width: 350px;
            width: 90%;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
        }
        
        .merit-confirm-title {
            color: #ffcc00;
            font-size: 1.3rem;
            margin-bottom: 10px;
        }
        
        .merit-confirm-text {
            color: #fff;
            font-size: 1.1rem;
            margin-bottom: 15px;
            line-height: 1.4;
        }
        
        .merit-confirm-btn {
            padding: 10px 15px;
            font-size: 1rem;
            background-color: #ffcc00;
            color: #8b0000;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-weight: bold;
        }
        
        /* 隐藏类 */
        .hidden {
            display: none !important;
        }
        
        /* iPad横屏优化 */
        @media (min-width: 768px) and (max-width: 1024px) {
            .opponent {
                width: 30%;
            }
            
            .player-card {
                width: 70px;
                height: 100px;
                margin-left: -20px;
            }
            
            .played-card {
                width: 70px;
                height: 100px;
            }
            
            .controls {
                grid-template-columns: repeat(3, 1fr);
            }
            
            .btn {
                padding: 12px;
                font-size: 1rem;
            }
        }
        
        /* iPhone横屏优化 */
        @media (max-width: 767px) and (orientation: landscape) {
            .game-area {
                flex-direction: row;
                flex-wrap: wrap;
                gap: 10px;
            }
            
            .opponent-area {
                width: 40%;
                flex-direction: column;
                margin-bottom: 0;
            }
            
            .opponent {
                width: 100%;
                margin-bottom: 10px;
                min-height: 100px;
            }
            
            .center-area {
                width: 60%;
                margin-bottom: 0;
            }
            
            .player-area {
                width: 100%;
                margin-top: 0;
                min-height: 150px;
            }
            
            .player-card {
                width: 50px;
                height: 70px;
                margin-left: -12px;
            }
            
            .played-card {
                width: 50px;
                height: 70px;
            }
            
            .controls {
                grid-template-columns: repeat(3, 1fr);
                gap: 5px;
            }
        }
        
        /* 小屏幕手机优化 */
        @media (max-width: 480px) {
            h1 {
                font-size: 1.5rem;
            }
            
            .info-item {
                min-width: 150px;
                padding: 10px 15px;
            }
            
            .opponent-area {
                flex-direction: column;
                align-items: center;
                gap: 10px;
            }
            
            .opponent {
                width: 100%;
                max-width: 200px;
            }
            
            .opponent:nth-child(2) {
                order: -1;
            }
            
            .player-card {
                width: 50px;
                height: 70px;
                margin-left: -12px;
            }
            
            .played-card {
                width: 45px;
                height: 65px;
            }
            
            .played-card .card-center {
                font-size: 1.2rem;
            }
            
            .controls {
                grid-template-columns: repeat(2, 1fr);
            }
            
            .btn {
                font-size: 0.9rem;
                padding: 10px 6px;
            }
        }
        
        /* 超小屏幕优化 */
        @media (max-width: 350px) {
            .player-card {
                width: 45px;
                height: 63px;
                margin-left: -10px;
            }
            
            .played-card {
                width: 40px;
                height: 60px;
            }
            
            .controls {
                grid-template-columns: 1fr;
            }
        }
        
        /* 防止iOS缩放 */
        @supports (-webkit-touch-callout: none) {
            body {
                cursor: pointer;
            }
            
            input, textarea {
                font-size: 16px !important; /* 防止iOS缩放 */
            }
        }
    </style>
</head>
<body>
    <!-- 游戏容器 -->
    <div class="game-container">
        <div class="header">
            <h1>斗地主 - 修行版</h1>
        </div>
        
        <div class="game-info">
            <div class="info-item">
                <div class="info-label">功德数</div>
                <div id="merit-score" class="info-value merit-value">0</div>
            </div>
        </div>
        
        <div class="game-area">
            <div class="opponent-area">
                <div id="opponent1" class="opponent">
                    <div class="opponent-name">又见音</div>
                    <div id="opponent1-cards" class="card-stack"></div>
                </div>
                
                <div id="opponent2" class="opponent">
                    <div class="opponent-name">执力至</div>
                    <div id="opponent2-cards" class="card-stack"></div>
                </div>
            </div>
            
            <div class="center-area">
                <div id="played-cards" class="played-cards"></div>
                <div class="game-status" id="game-status">点击"开始游戏"按钮开始</div>
            </div>
            
            <div id="player-area" class="player-area">
                <div class="player-name">玩家</div>
                <div id="player-cards-container" class="player-cards-container"></div>
            </div>
        </div>
    </div>
    
    <!-- 控制按钮 -->
    <div class="controls-container">
        <div class="controls">
            <button id="start-btn" class="btn">开始游戏</button>
            <button id="play-btn" class="btn" disabled>出牌</button>
            <button id="pass-btn" class="btn" disabled>不出</button>
            <button id="hint-btn" class="btn" disabled>提示</button>
            <button id="music-toggle-btn" class="btn music-btn">背景音乐: 开</button>
            <button id="merit-transfer-btn" class="btn">功德回向</button>
        </div>
    </div>
    
    <!-- 弹窗和遮罩层 -->
    <div id="landlord-selection" class="landlord-selection hidden">
        <div class="selection-box">
            <div class="selection-title">是否叫功德主?</div>
            <div id="selection-info" style="margin-bottom: 15px; color: #ffcc00; font-size: 1.1rem;">您有3张底牌</div>
            
            <div id="landlord-cards" class="landlord-cards"></div>
            
            <div class="selection-buttons">
                <button id="call-landlord-btn" class="selection-btn">叫功德主</button>
                <button id="pass-landlord-btn" class="selection-btn">不叫</button>
            </div>
        </div>
    </div>
    
    <div id="merit-transfer" class="merit-transfer hidden">
        <div class="merit-box">
            <div class="merit-title">功德回向</div>
            <div id="merit-transfer-info" style="margin-bottom: 15px; color: #ffcc00; font-size: 1.1rem;">
                您当前有 <span id="current-merit-display">0</span> 点功德
            </div>
            
            <div class="merit-buttons">
                <button id="merit-to-all-btn" class="merit-btn">回向一切众生</button>
                <button id="merit-to-loved-btn" class="merit-btn">回向所爱的人</button>
                <div id="loved-name-input-container" style="display: none; width: 100%;">
                    <input type="text" id="loved-name-input" class="merit-input" placeholder="输入名字" maxlength="20">
                    <button id="submit-loved-name-btn" class="merit-btn" style="margin-top: 10px;">确认回向</button>
                </div>
                <button id="merit-cancel-btn" class="merit-btn">再想想</button>
            </div>
        </div>
    </div>
    
    <!-- 功德回向确认消息 -->
    <div id="merit-confirm" class="merit-confirm hidden">
        <div class="merit-confirm-title">功德回向成功</div>
        <div id="merit-confirm-text" class="merit-confirm-text"></div>
        <button id="merit-confirm-btn" class="merit-confirm-btn">确认</button>
    </div>
    
    <!-- 音频元素 -->
    <audio id="bg-music" loop>
        <source src="beijing.ogg" type="audio/ogg">
        您的浏览器不支持音频元素。
    </audio>
    <audio id="play-sound">
        <source src="xiaochu.mp3" type="audio/mpeg">
        您的浏览器不支持音频元素。
    </audio>
    <audio id="win-sound">
        <source src="win.mp3" type="audio/mpeg">
        您的浏览器不支持音频元素。
    </audio>
    <audio id="ai-sound">
        <source src="ai.mp3" type="audio/mpeg">
        您的浏览器不支持音频元素。
    </audio>
    <audio id="merit-sound">
        <source src="xiaochu.mp3" type="audio/mpeg">
        您的浏览器不支持音频元素。
    </audio>

    <script>
        // 游戏状态
        const gameState = {
            players: ['player', 'opponent1', 'opponent2'],
            currentPlayer: 'player',
            deck: [],
            playerCards: [],
            opponent1Cards: [],
            opponent2Cards: [],
            lastPlayedCards: [],
            lastPlayer: null,
            gameStarted: false,
            landlord: null,
            meritScore: 0,
            musicEnabled: true,
            soundEnabled: true,
            landlordCards: [],
            selectingLandlord: false,
            playerPassed: false,
            consecutivePasses: 0,
            gameEnded: false
        };
        
        // 牌型定义
        const cardSuits = [
            { name: 'spade', symbol: '♠', color: 'black' },
            { name: 'heart', symbol: '♥', color: 'red' },
            { name: 'club', symbol: '♣', color: 'black' },
            { name: 'diamond', symbol: '♦', color: 'red' }
        ];
        const cardValues = ['3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A', '2'];
        const cardDisplay = {
            'J': 'J',
            'Q': 'Q',
            'K': 'K',
            'A': 'A',
            '2': '2'
        };
        
        // 音频元素
        const bgMusic = document.getElementById('bg-music');
        const playSound = document.getElementById('play-sound');
        const winSound = document.getElementById('win-sound');
        const aiSound = document.getElementById('ai-sound');
        const meritSound = document.getElementById('merit-sound');
        
        // DOM元素
        const playerCardsContainer = document.getElementById('player-cards-container');
        const opponent1CardsEl = document.getElementById('opponent1-cards');
        const opponent2CardsEl = document.getElementById('opponent2-cards');
        const playedCardsEl = document.getElementById('played-cards');
        const meritScoreEl = document.getElementById('merit-score');
        const gameStatusEl = document.getElementById('game-status');
        const startBtn = document.getElementById('start-btn');
        const playBtn = document.getElementById('play-btn');
        const passBtn = document.getElementById('pass-btn');
        const hintBtn = document.getElementById('hint-btn');
        const musicToggleBtn = document.getElementById('music-toggle-btn');
        const meritTransferBtn = document.getElementById('merit-transfer-btn');
        const playerAreaEl = document.getElementById('player-area');
        const opponent1El = document.getElementById('opponent1');
        const opponent2El = document.getElementById('opponent2');
        const landlordSelectionEl = document.getElementById('landlord-selection');
        const callLandlordBtn = document.getElementById('call-landlord-btn');
        const passLandlordBtn = document.getElementById('pass-landlord-btn');
        const selectionInfoEl = document.getElementById('selection-info');
        const landlordCardsEl = document.getElementById('landlord-cards');
        const meritTransferEl = document.getElementById('merit-transfer');
        const currentMeritDisplay = document.getElementById('current-merit-display');
        const meritToAllBtn = document.getElementById('merit-to-all-btn');
        const meritToLovedBtn = document.getElementById('merit-to-loved-btn');
        const meritCancelBtn = document.getElementById('merit-cancel-btn');
        const lovedNameInputContainer = document.getElementById('loved-name-input-container');
        const lovedNameInput = document.getElementById('loved-name-input');
        const submitLovedNameBtn = document.getElementById('submit-loved-name-btn');
        const meritConfirmEl = document.getElementById('merit-confirm');
        const meritConfirmText = document.getElementById('merit-confirm-text');
        const meritConfirmBtn = document.getElementById('merit-confirm-btn');
        
        // 初始化游戏
        function initGame() {
            // 清除上一局的出牌
            gameState.lastPlayedCards = [];
            gameState.gameEnded = false;
            
            createDeck();
            shuffleDeck();
            dealCards();
            
            // 更新UI显示所有玩家的牌
            updateUI();
            
            // 显示功德主选择界面
            setTimeout(() => {
                showLandlordSelection();
            }, 500);
            
            gameState.gameStarted = true;
            gameState.playerPassed = false;
            gameState.consecutivePasses = 0;
            
            // 播放背景音乐
            if (gameState.musicEnabled) {
                bgMusic.play().catch(e => console.log("自动播放被阻止,请手动播放音乐"));
            }
        }
        
        // 创建一副牌
        function createDeck() {
            gameState.deck = [];
            
            // 添加普通牌
            for (let suit of cardSuits) {
                for (let value of cardValues) {
                    gameState.deck.push({
                        suit: suit.name,
                        symbol: suit.symbol,
                        value: value,
                        color: suit.color,
                        numericValue: getCardValueIndex(value)
                    });
                }
            }
            
            // 添加大小王
            gameState.deck.push({ 
                suit: 'joker', 
                symbol: '大王', 
                value: 'Joker', 
                color: 'red',
                numericValue: 17,
                jokerType: 'big',
                image: 'wuliangsofo_s.jpg'
            });
            gameState.deck.push({ 
                suit: 'joker', 
                symbol: '小王', 
                value: 'Joker', 
                color: 'black',
                numericValue: 16,
                jokerType: 'small',
                image: 'wuliangsofo_s2.jpg'
            });
        }
        
        // 洗牌
        function shuffleDeck() {
            for (let i = gameState.deck.length - 1; i > 0; i--) {
                const j = Math.floor(Math.random() * (i + 1));
                [gameState.deck[i], gameState.deck[j]] = [gameState.deck[j], gameState.deck[i]];
            }
        }
        
        // 发牌
        function dealCards() {
            // 清空玩家手牌
            gameState.playerCards = [];
            gameState.opponent1Cards = [];
            gameState.opponent2Cards = [];
            gameState.landlordCards = [];
            
            // 每位玩家发17张牌
            for (let i = 0; i < 17; i++) {
                gameState.playerCards.push(gameState.deck.pop());
                gameState.opponent1Cards.push(gameState.deck.pop());
                gameState.opponent2Cards.push(gameState.deck.pop());
            }
            
            // 保留3张底牌
            for (let i = 0; i < 3; i++) {
                gameState.landlordCards.push(gameState.deck.pop());
            }
            
            // 排序手牌
            sortCards(gameState.playerCards);
            sortCards(gameState.opponent1Cards);
            sortCards(gameState.opponent2Cards);
        }
        
        // 显示功德主选择界面
        function showLandlordSelection() {
            gameState.selectingLandlord = true;
            
            // 显示底牌(背面)
            landlordCardsEl.innerHTML = '';
            for (let i = 0; i < gameState.landlordCards.length; i++) {
                const cardBack = document.createElement('div');
                cardBack.className = 'landlord-card-back';
                landlordCardsEl.appendChild(cardBack);
            }
            
            landlordSelectionEl.classList.remove('hidden');
            updateGameStatus("请选择是否叫功德主");
        }
        
        // 增加功德数
        function addMeritScore(amount, reason = "") {
            gameState.meritScore += amount;
            updateMeritScore();
            
            // 播放功德增加音效
            if (gameState.soundEnabled) {
                meritSound.currentTime = 0;
                meritSound.play();
            }
            
            // 添加动画效果
            meritScoreEl.classList.add('merit-up');
            setTimeout(() => {
                meritScoreEl.classList.remove('merit-up');
            }, 1000);
            
            // 只有在非胜利出牌时才显示功德增加提示
            if (reason && !gameState.gameEnded) {
                const oldStatus = gameStatusEl.textContent;
                updateGameStatus(`${reason},功德+${amount}`);
                setTimeout(() => {
                    updateGameStatus(oldStatus);
                }, 2000);
            }
        }
        
        // 更新功德数显示
        function updateMeritScore() {
            meritScoreEl.textContent = gameState.meritScore;
        }
        
        // 玩家选择叫功德主
        function callLandlord() {
            gameState.landlord = 'player';
            
            // 玩家获得底牌
            for (let card of gameState.landlordCards) {
                gameState.playerCards.push(card);
            }
            
            sortCards(gameState.playerCards);
            gameState.landlordCards = [];
            
            landlordSelectionEl.classList.add('hidden');
            gameState.selectingLandlord = false;
            
            // 更新玩家手牌显示
            renderPlayerCards();
            
            startGameplay();
        }
        
        // 玩家选择不叫功德主
        function passLandlord() {
            // 随机选择一个电脑玩家作为功德主
            const randomIndex = Math.floor(Math.random() * 2) + 1;
            gameState.landlord = gameState.players[randomIndex];
            
            // 功德主获得底牌
            if (gameState.landlord === 'opponent1') {
                for (let card of gameState.landlordCards) {
                    gameState.opponent1Cards.push(card);
                }
                sortCards(gameState.opponent1Cards);
            } else {
                for (let card of gameState.landlordCards) {
                    gameState.opponent2Cards.push(card);
                }
                sortCards(gameState.opponent2Cards);
            }
            
            gameState.landlordCards = [];
            
            landlordSelectionEl.classList.add('hidden');
            gameState.selectingLandlord = false;
            
            startGameplay();
        }
        
        // 开始游戏
        function startGameplay() {
            // 如果玩家是功德主,自动激活玩家回合
            if (gameState.landlord === 'player') {
                gameState.currentPlayer = 'player';
                activatePlayerTurn();
                updateGameStatus("您是功德主,请先出牌");
            } else {
                // 否则,激活对应电脑玩家的回合
                gameState.currentPlayer = gameState.landlord;
                updateGameStatus(`${gameState.landlord === 'opponent1' ? '又见音' : '执力至'}是功德主`);
                setTimeout(computerPlay, 1500);
            }
            
            // 更新按钮状态
            startBtn.disabled = true;
            playBtn.disabled = false;
            passBtn.disabled = false;
            hintBtn.disabled = false;
        }
        
        // 排序手牌
        function sortCards(cards) {
            cards.sort((a, b) => {
                if (a.numericValue !== b.numericValue) {
                    return a.numericValue - b.numericValue;
                }
                // 如果牌值相同,按花色排序
                const suitOrder = { 'spade': 4, 'heart': 3, 'club': 2, 'diamond': 1, 'joker': 0 };
                return suitOrder[b.suit] - suitOrder[a.suit];
            });
        }
        
        // 获取牌值索引
        function getCardValueIndex(value) {
            if (value === 'Joker') {
                return 0;
            }
            
            const index = cardValues.indexOf(value);
            
            if (value === '2') {
                return 15;
            } else if (value === 'A') {
                return 14;
            } else if (value === 'K') {
                return 13;
            } else if (value === 'Q') {
                return 12;
            } else if (value === 'J') {
                return 11;
            } else if (value === '10') {
                return 10;
            } else if (value === '9') {
                return 9;
            } else if (value === '8') {
                return 8;
            } else if (value === '7') {
                return 7;
            } else if (value === '6') {
                return 6;
            } else if (value === '5') {
                return 5;
            } else if (value === '4') {
                return 4;
            } else if (value === '3') {
                return 3;
            }
            
            return index + 3;
        }
        
        // 更新UI
        function updateUI() {
            // 更新玩家手牌
            renderPlayerCards();
            
            // 更新电脑玩家手牌
            renderOpponentCards();
            
            // 更新已出牌区域
            renderPlayedCards();
            
            // 更新玩家区域激活状态
            if (gameState.currentPlayer === 'player' && !gameState.selectingLandlord) {
                playerAreaEl.classList.add('active');
            } else {
                playerAreaEl.classList.remove('active');
            }
            
            // 更新电脑玩家激活状态
            if (gameState.currentPlayer === 'opponent1') {
                opponent1El.classList.add('active');
            } else {
                opponent1El.classList.remove('active');
            }
            
            if (gameState.currentPlayer === 'opponent2') {
                opponent2El.classList.add('active');
            } else {
                opponent2El.classList.remove('active');
            }
        }
        
        // 渲染玩家手牌
        function renderPlayerCards() {
            playerCardsContainer.innerHTML = '';
            
            if (gameState.playerCards.length === 0) {
                const emptyMsg = document.createElement('div');
                emptyMsg.textContent = '手牌已出完';
                emptyMsg.style.color = '#ffcc00';
                emptyMsg.style.fontSize = '1.2rem';
                emptyMsg.style.margin = 'auto';
                playerCardsContainer.appendChild(emptyMsg);
                return;
            }
            
            const stackContainer = document.createElement('div');
            stackContainer.className = 'player-card-stack';
            
            // 计算需要的总宽度
            const cardWidth = 60;
            const cardOverlap = 15;
            const totalCards = gameState.playerCards.length;
            const totalWidth = cardWidth + (totalCards - 1) * (cardWidth - cardOverlap);
            
            // 设置容器最小宽度
            stackContainer.style.minWidth = `${totalWidth}px`;
            
            // 每张牌轻微层叠
            gameState.playerCards.forEach((card, index) => {
                const cardEl = createCardElement(card, index);
                stackContainer.appendChild(cardEl);
            });
            
            playerCardsContainer.appendChild(stackContainer);
            
            // 确保容器宽度不会导致滚动条
            playerCardsContainer.style.overflowX = 'auto';
            playerCardsContainer.style.maxWidth = '100%';
        }
        
        // 渲染电脑玩家手牌
        function renderOpponentCards() {
            // 清空现有牌背
            opponent1CardsEl.innerHTML = '';
            opponent2CardsEl.innerHTML = '';
            
            // 为电脑玩家1渲染牌背
            const cardCount1 = gameState.opponent1Cards.length;
            if (cardCount1 > 0) {
                const overlap = 6;
                const cardWidth = 50;
                const totalWidth = (cardCount1 - 1) * overlap + cardWidth;
                
                // 从右向左排列牌背
                for (let i = 0; i < Math.min(cardCount1, 15); i++) {
                    const cardBack = document.createElement('div');
                    cardBack.className = 'card-back';
                    
                    // 计算位置
                    const leftPosition = totalWidth - cardWidth - (i * overlap);
                    cardBack.style.left = `${leftPosition}px`;
                    cardBack.style.zIndex = i;
                    opponent1CardsEl.appendChild(cardBack);
                }
                
                // 如果牌数超过15张,显示一个额外的牌背表示更多
                if (cardCount1 > 15) {
                    const moreCards = document.createElement('div');
                    moreCards.className = 'card-back';
                    moreCards.style.left = '0px';
                    moreCards.style.zIndex = 15;
                    moreCards.style.opacity = '0.7';
                    opponent1CardsEl.appendChild(moreCards);
                }
            }
            
            // 为电脑玩家2渲染牌背
            const cardCount2 = gameState.opponent2Cards.length;
            if (cardCount2 > 0) {
                const overlap = 6;
                const cardWidth = 50;
                const totalWidth = (cardCount2 - 1) * overlap + cardWidth;
                
                for (let i = 0; i < Math.min(cardCount2, 15); i++) {
                    const cardBack = document.createElement('div');
                    cardBack.className = 'card-back';
                    
                    const leftPosition = totalWidth - cardWidth - (i * overlap);
                    cardBack.style.left = `${leftPosition}px`;
                    cardBack.style.zIndex = i;
                    opponent2CardsEl.appendChild(cardBack);
                }
                
                if (cardCount2 > 15) {
                    const moreCards = document.createElement('div');
                    moreCards.className = 'card-back';
                    moreCards.style.left = '0px';
                    moreCards.style.zIndex = 15;
                    moreCards.style.opacity = '0.7';
                    opponent2CardsEl.appendChild(moreCards);
                }
            }
        }
        
        // 渲染已出牌
        function renderPlayedCards() {
            playedCardsEl.innerHTML = '';
            
            if (gameState.lastPlayedCards.length === 0) {
                const emptyMsg = document.createElement('div');
                emptyMsg.textContent = '暂无出牌';
                emptyMsg.style.color = '#ccc';
                emptyMsg.style.fontSize = '1.2rem';
                emptyMsg.style.margin = 'auto';
                playedCardsEl.appendChild(emptyMsg);
                return;
            }
            
            // 创建紧凑显示区域
            gameState.lastPlayedCards.forEach((card, index) => {
                const cardEl = createPlayedCardElement(card);
                playedCardsEl.appendChild(cardEl);
            });
        }
        
        // 创建已出牌元素
        function createPlayedCardElement(card) {
            const cardEl = document.createElement('div');
            cardEl.className = `played-card card ${card.color}`;
            
            // 如果是大小王,使用图片
            if (card.value === 'Joker') {
                const jokerImage = document.createElement('div');
                jokerImage.className = 'card-joker';
                jokerImage.style.backgroundImage = `url('${card.image}')`;
                cardEl.appendChild(jokerImage);
            } else {
                // 普通牌
                const topCorner = document.createElement('div');
                topCorner.className = 'card-corner';
                topCorner.innerHTML = `<div>${getCardValueDisplay(card.value)}</div><div>${card.symbol}</div>`;
                
                const center = document.createElement('div');
                center.className = 'card-center';
                center.textContent = card.symbol;
                
                const bottomCorner = document.createElement('div');
                bottomCorner.className = 'card-corner';
                bottomCorner.innerHTML = `<div>${getCardValueDisplay(card.value)}</div><div>${card.symbol}</div>`;
                bottomCorner.style.transform = 'rotate(180deg)';
                
                cardEl.appendChild(topCorner);
                cardEl.appendChild(center);
                cardEl.appendChild(bottomCorner);
            }
            
            return cardEl;
        }
        
        // 创建牌元素(玩家手牌)
        function createCardElement(card, index) {
            const cardEl = document.createElement('div');
            cardEl.className = `player-card card ${card.color}`;
            cardEl.dataset.index = index;
            cardEl.dataset.value = card.value;
            cardEl.dataset.suit = card.suit;
            
            // 如果是大小王,使用图片
            if (card.value === 'Joker') {
                const jokerImage = document.createElement('div');
                jokerImage.className = 'card-joker';
                jokerImage.style.backgroundImage = `url('${card.image}')`;
                cardEl.appendChild(jokerImage);
            } else {
                // 普通牌
                const topCorner = document.createElement('div');
                topCorner.className = 'card-corner';
                topCorner.innerHTML = `<div>${getCardValueDisplay(card.value)}</div><div>${card.symbol}</div>`;
                
                const center = document.createElement('div');
                center.className = 'card-center';
                center.textContent = card.symbol;
                
                const bottomCorner = document.createElement('div');
                bottomCorner.className = 'card-corner';
                bottomCorner.innerHTML = `<div>${getCardValueDisplay(card.value)}</div><div>${card.symbol}</div>`;
                bottomCorner.style.transform = 'rotate(180deg)';
                
                cardEl.appendChild(topCorner);
                cardEl.appendChild(center);
                cardEl.appendChild(bottomCorner);
            }
            
            if (index >= 0) {
                cardEl.addEventListener('click', (e) => {
                    e.stopPropagation();
                    if (gameState.currentPlayer === 'player' && gameState.gameStarted && !gameState.selectingLandlord && !gameState.gameEnded) {
                        cardEl.classList.toggle('selected');
                        
                        // 如果选中了牌,确保它显示在最前面
                        if (cardEl.classList.contains('selected')) {
                            cardEl.style.zIndex = 1000;
                        } else {
                            cardEl.style.zIndex = 1;
                        }
                    }
                });
            }
            
            return cardEl;
        }
        
        // 获取牌值显示文本
        function getCardValueDisplay(value) {
            if (value === 'Joker') {
                return '';
            }
            return value in cardDisplay ? cardDisplay[value] : value;
        }
        
        // 激活玩家回合
        function activatePlayerTurn() {
            gameState.currentPlayer = 'player';
            gameState.playerPassed = false;
            updateUI();
            updateGameStatus("您的回合,请选择要出的牌");
        }
        
        // 玩家出牌
        function playerPlay() {
            const selectedCards = document.querySelectorAll('#player-cards-container .player-card.selected');
            if (selectedCards.length === 0) {
                updateGameStatus("请选择要出的牌");
                return;
            }
            
            // 获取选中的牌
            const selectedIndices = Array.from(selectedCards).map(card => parseInt(card.dataset.index));
            selectedIndices.sort((a, b) => b - a);
            
            // 检查出牌是否合法
            const cardsToPlay = selectedIndices.map(index => gameState.playerCards[index]);
            if (!isValidPlay(cardsToPlay, gameState.lastPlayedCards, gameState.lastPlayer === 'player')) {
                updateGameStatus("出牌不合法,请重新选择");
                return;
            }
            
            // 从玩家手牌中移除
            for (let index of selectedIndices) {
                gameState.playerCards.splice(index, 1);
            }
            
            // 更新上一轮出牌
            gameState.lastPlayedCards = cardsToPlay;
            gameState.lastPlayer = 'player';
            gameState.consecutivePasses = 0;
            
            // 检查游戏是否结束
            if (gameState.playerCards.length === 0) {
                // 玩家出完所有牌
                updateUI();
                
                setTimeout(() => {
                    endGame('player');
                }, 500);
                return;
            }
            
            // 增加功德数
            addMeritScore(100);
            
            // 播放出牌音效
            if (gameState.soundEnabled) {
                playSound.currentTime = 0;
                playSound.play();
            }
            
            // 切换到下一个玩家
            nextTurn();
        }
        
        // 玩家不出
        function playerPass() {
            if (gameState.lastPlayer === null || gameState.lastPlayer === 'player') {
                updateGameStatus("您是首家出牌,不能不出");
                return;
            }
            
            gameState.playerPassed = true;
            gameState.consecutivePasses++;
            
            updateGameStatus("您选择不出");
            
            // 如果连续两个玩家都选择不出,重新开始一轮
            if (gameState.consecutivePasses >= 2) {
                gameState.lastPlayedCards = [];
                gameState.lastPlayer = null;
                gameState.consecutivePasses = 0;
                updateGameStatus("");
            }
            
            nextTurn();
        }
        
        // 电脑玩家出牌
        function computerPlay() {
            const player = gameState.currentPlayer;
            let cards;
            
            if (player === 'opponent1') {
                cards = gameState.opponent1Cards;
            } else {
                cards = gameState.opponent2Cards;
            }
            
            // 获取可出的牌
            const playableCards = getPlayableCards(cards, gameState.lastPlayedCards, gameState.lastPlayer === player);
            
            if (playableCards.length > 0) {
                // 播放AI音效
                if (gameState.soundEnabled) {
                    aiSound.currentTime = 0;
                    aiSound.play();
                }
                
                // 从电脑手牌中移除
                const cardsToPlay = playableCards;
                for (let cardToRemove of cardsToPlay) {
                    const index = cards.findIndex(card => 
                        card.value === cardToRemove.value && 
                        card.suit === cardToRemove.suit);
                    if (index > -1) {
                        cards.splice(index, 1);
                    }
                }
                
                // 更新上一轮出牌
                gameState.lastPlayedCards = cardsToPlay;
                gameState.lastPlayer = player;
                gameState.consecutivePasses = 0;
                
                // 播放出牌音效
                if (gameState.soundEnabled) {
                    setTimeout(() => {
                        playSound.currentTime = 0;
                        playSound.play();
                    }, 500);
                }
                
                // 检查游戏是否结束
                if (cards.length === 0) {
                    updateGameStatus(`${player === 'opponent1' ? '又见音' : '执力至'}出完了所有牌!`);
                    setTimeout(() => {
                        endGame(player);
                    }, 1000);
                    return;
                }
                
                // 获取牌型描述
                const cardType = getCardType(cardsToPlay);
                let typeDescription = "";
                switch(cardType.type) {
                    case 'single': typeDescription = "单张"; break;
                    case 'pair': typeDescription = "对子"; break;
                    case 'triple': typeDescription = "三张"; break;
                    case 'triple_with_single': typeDescription = "三带一"; break;
                    case 'triple_with_pair': typeDescription = "三带二"; break;
                    case 'straight': typeDescription = "顺子"; break;
                    case 'consecutive_pairs': typeDescription = "连对"; break;
                    case 'plane': typeDescription = "飞机"; break;
                    case 'plane_with_single': typeDescription = "飞机带单"; break;
                    case 'plane_with_pair': typeDescription = "飞机带对"; break;
                    case 'bomb': typeDescription = "炸弹"; break;
                    case 'four_with_two_singles': typeDescription = "四带二单"; break;
                    case 'four_with_two_pairs': typeDescription = "四带二对"; break;
                    case 'rocket': typeDescription = "火箭"; break;
                    default: typeDescription = "牌组";
                }
                
                updateGameStatus(`${player === 'opponent1' ? '又见音' : '执力至'}出了${cardsToPlay.length}张牌 (${typeDescription})`);
                
                // 切换到下一个玩家
                setTimeout(nextTurn, 1000);
            } else {
                // 电脑选择不出
                updateGameStatus(`${player === 'opponent1' ? '又见音' : '执力至'}选择不出`);
                gameState.consecutivePasses++;
                
                // 如果连续两个玩家都选择不出,重新开始一轮
                if (gameState.consecutivePasses >= 2) {
                    gameState.lastPlayedCards = [];
                    gameState.lastPlayer = null;
                    gameState.consecutivePasses = 0;
                    updateGameStatus("");
                }
                
                setTimeout(nextTurn, 1000);
            }
        }
        
        // 获取可出的牌(AI逻辑)
        function getPlayableCards(cards, lastCards, isFirstPlay) {
            // 如果没有上一轮出牌或者是首家出牌,可以出任何合法牌型
            if (lastCards.length === 0 || isFirstPlay) {
                // 尝试出最小的合法牌型
                return findSmallestValidCards(cards);
            }
            
            // 如果不是首家出牌,需要出比上一轮大的牌
            const lastType = getCardType(lastCards);
            const allPossiblePlays = getAllPossiblePlays(cards);
            
            // 找出比上一轮大的牌
            for (let play of allPossiblePlays) {
                const playType = getCardType(play);
                if (compareCardTypes(playType, lastType) > 0) {
                    return play;
                }
            }
            
            // 如果没有合适的牌,返回空数组(不出)
            return [];
        }
        
        // 找出最小的合法牌
        function findSmallestValidCards(cards) {
            // 尝试单张
            if (cards.length >= 1) {
                return [cards[0]];
            }
            return [];
        }
        
        // 获取所有可能的出牌组合
        function getAllPossiblePlays(cards) {
            const plays = [];
            
            // 按牌值分组
            const cardsByValue = {};
            cards.forEach(card => {
                if (!cardsByValue[card.value]) {
                    cardsByValue[card.value] = [];
                }
                cardsByValue[card.value].push(card);
            });
            
            // 单张
            cards.forEach(card => {
                plays.push([card]);
            });
            
            // 对子
            for (let value in cardsByValue) {
                if (cardsByValue[value].length >= 2) {
                    plays.push(cardsByValue[value].slice(0, 2));
                }
            }
            
            // 三张
            for (let value in cardsByValue) {
                if (cardsByValue[value].length >= 3) {
                    plays.push(cardsByValue[value].slice(0, 3));
                }
            }
            
            // 顺子
            const straightPlays = getStraightPlays(cards);
            plays.push(...straightPlays);
            
            // 炸弹
            for (let value in cardsByValue) {
                if (cardsByValue[value].length >= 4) {
                    plays.push(cardsByValue[value].slice(0, 4));
                }
            }
            
            // 火箭
            const bigJoker = cards.find(c => c.value === 'Joker' && c.jokerType === 'big');
            const smallJoker = cards.find(c => c.value === 'Joker' && c.jokerType === 'small');
            if (bigJoker && smallJoker) {
                plays.push([bigJoker, smallJoker]);
            }
            
            return plays;
        }
        
        // 获取顺子组合
        function getStraightPlays(cards) {
            const plays = [];
            
            // 按数值排序
            const sortedCards = [...cards].sort((a, b) => a.numericValue - b.numericValue);
            
            // 移除2和大小王,因为它们不能组成顺子
            const validCards = sortedCards.filter(card => 
                card.value !== '2' && card.value !== 'Joker');
            
            if (validCards.length < 5) return plays;
            
            // 找出所有可能的顺子
            for (let i = 0; i <= validCards.length - 5; i++) {
                let straight = [validCards[i]];
                
                for (let j = i + 1; j < validCards.length; j++) {
                    const lastCard = straight[straight.length - 1];
                    const currentCard = validCards[j];
                    
                    // 检查是否连续
                    if (currentCard.numericValue === lastCard.numericValue + 1) {
                        straight.push(currentCard);
                        
                        // 如果顺子长度达到5或以上,添加到可出牌组
                        if (straight.length >= 5) {
                            plays.push([...straight]);
                        }
                    } else if (currentCard.numericValue > lastCard.numericValue + 1) {
                        // 不连续,重新开始
                        break;
                    }
                    // 如果牌值相同,跳过(顺子不能有重复牌值)
                }
            }
            
            // 移除重复的顺子
            const uniquePlays = [];
            const seen = new Set();
            
            for (let play of plays) {
                const key = play.map(card => card.numericValue).join('-');
                if (!seen.has(key)) {
                    seen.add(key);
                    uniquePlays.push(play);
                }
            }
            
            return uniquePlays;
        }
        
        // 检查出牌是否合法
        function isValidPlay(cards, lastCards, isFirstPlay) {
            if (cards.length === 0) return false;
            
            // 检查牌型是否合法
            const cardType = getCardType(cards);
            if (!cardType.valid) return false;
            
            // 如果是首家出牌,任何合法牌型都可以
            if (lastCards.length === 0 || isFirstPlay) {
                return true;
            }
            
            // 如果不是首家出牌,需要比上一轮牌大
            const lastType = getCardType(lastCards);
            return compareCardTypes(cardType, lastType) > 0;
        }
        
        // 获取牌型 - 修复了顺子判断逻辑
        function getCardType(cards) {
            const len = cards.length;
            if (len === 0) return { type: 'invalid', valid: false };
            
            const values = cards.map(card => card.numericValue);
            const uniqueValues = [...new Set(values)];
            
            // 火箭
            if (len === 2 && cards[0].value === 'Joker' && cards[1].value === 'Joker') {
                return { type: 'rocket', value: 100, valid: true };
            }
            
            // 单张
            if (len === 1) {
                return { type: 'single', value: values[0], valid: true };
            }
            
            // 对子
            if (len === 2 && uniqueValues.length === 1) {
                return { type: 'pair', value: values[0], valid: true };
            }
            
            // 三张
            if (len === 3 && uniqueValues.length === 1) {
                return { type: 'triple', value: values[0], valid: true };
            }
            
            // 三带一
            if (len === 4 && uniqueValues.length === 2) {
                const valueCounts = countCardValues(cards);
                const tripleValue = Object.keys(valueCounts).find(v => valueCounts[v] === 3);
                if (tripleValue) {
                    return { type: 'triple_with_single', value: parseInt(tripleValue), valid: true };
                }
            }
            
            // 三带二
            if (len === 5 && uniqueValues.length === 2) {
                const valueCounts = countCardValues(cards);
                const tripleValue = Object.keys(valueCounts).find(v => valueCounts[v] === 3);
                const pairValue = Object.keys(valueCounts).find(v => valueCounts[v] === 2);
                if (tripleValue && pairValue) {
                    return { type: 'triple_with_pair', value: parseInt(tripleValue), valid: true };
                }
            }
            
            // 炸弹
            if (len === 4 && uniqueValues.length === 1) {
                return { type: 'bomb', value: values[0], valid: true };
            }
            
            // 顺子 - 修复判断逻辑
            if (len >= 5 && isStraight(cards)) {
                // 顺子的值取最大牌的值
                const maxValue = Math.max(...values);
                return { type: 'straight', value: maxValue, valid: true, length: len };
            }
            
            // 连对
            if (len >= 6 && len % 2 === 0 && isConsecutivePairs(cards)) {
                return { type: 'consecutive_pairs', value: Math.max(...values), valid: true, length: len / 2 };
            }
            
            // 飞机(无翅膀)
            if (len >= 6 && len % 3 === 0 && isPlane(cards)) {
                return { type: 'plane', value: Math.max(...values), valid: true, length: len / 3 };
            }
            
            return { type: 'invalid', valid: false };
        }
        
        // 辅助函数:统计牌值数量
        function countCardValues(cards) {
            const counts = {};
            cards.forEach(card => {
                counts[card.numericValue] = (counts[card.numericValue] || 0) + 1;
            });
            return counts;
        }
        
        // 辅助函数:检查是否为顺子 - 修复版本
        function isStraight(cards) {
            if (cards.length < 5) return false;
            
            // 排序
            const sortedCards = [...cards].sort((a, b) => a.numericValue - b.numericValue);
            
            // 检查是否包含2或大小王,它们不能组成顺子
            for (let card of sortedCards) {
                if (card.value === '2' || card.value === 'Joker') {
                    return false;
                }
            }
            
            // 检查牌值是否连续
            for (let i = 1; i < sortedCards.length; i++) {
                if (sortedCards[i].numericValue !== sortedCards[i-1].numericValue + 1) {
                    return false;
                }
            }
            
            return true;
        }
        
        // 辅助函数:检查是否为连对
        function isConsecutivePairs(cards) {
            if (cards.length < 6 || cards.length % 2 !== 0) return false;
            
            const valueCounts = countCardValues(cards);
            
            // 每张牌必须出现2次
            for (let count of Object.values(valueCounts)) {
                if (count !== 2) return false;
            }
            
            const uniqueValues = Object.keys(valueCounts).map(Number).sort((a, b) => a - b);
            
            // 检查是否连续
            for (let i = 1; i < uniqueValues.length; i++) {
                if (uniqueValues[i] !== uniqueValues[i-1] + 1) {
                    return false;
                }
            }
            
            return true;
        }
        
        // 辅助函数:检查是否为飞机(无翅膀)
        function isPlane(cards) {
            if (cards.length < 6 || cards.length % 3 !== 0) return false;
            
            const valueCounts = countCardValues(cards);
            
            // 每张牌必须出现3次
            for (let count of Object.values(valueCounts)) {
                if (count !== 3) return false;
            }
            
            const uniqueValues = Object.keys(valueCounts).map(Number).sort((a, b) => a - b);
            
            // 检查是否连续
            for (let i = 1; i < uniqueValues.length; i++) {
                if (uniqueValues[i] !== uniqueValues[i-1] + 1) {
                    return false;
                }
            }
            
            return true;
        }
        
        // 比较牌型大小
        function compareCardTypes(type1, type2) {
            // 火箭最大
            if (type1.type === 'rocket') return 1;
            if (type2.type === 'rocket') return -1;
            
            // 炸弹比其他牌型大(除了火箭)
            if (type1.type === 'bomb' && type2.type !== 'bomb') return 1;
            if (type2.type === 'bomb' && type1.type !== 'bomb') return -1;
            
            // 相同牌型比较
            if (type1.type === type2.type) {
                // 特殊牌型需要长度也相同
                const lengthSensitiveTypes = ['straight', 'consecutive_pairs', 'plane'];
                if (lengthSensitiveTypes.includes(type1.type)) {
                    if (type1.length !== type2.length) return 0; // 长度不同不能比较
                }
                
                // 比较牌值,值大的牌型更大
                return type1.value - type2.value;
            }
            
            // 不同牌型不能比较(炸弹除外,已在上面处理)
            return 0;
        }
        
        // 切换到下一个回合
        function nextTurn() {
            const currentIndex = gameState.players.indexOf(gameState.currentPlayer);
            const nextIndex = (currentIndex + 1) % 3;
            gameState.currentPlayer = gameState.players[nextIndex];
            
            updateUI();
            
            if (gameState.currentPlayer === 'player') {
                activatePlayerTurn();
            } else {
                setTimeout(computerPlay, 1500);
            }
        }
        
        // 结束游戏
        function endGame(winner) {
            gameState.gameStarted = false;
            gameState.gameEnded = true;
            
            // 播放胜利音效
            if (gameState.soundEnabled) {
                winSound.currentTime = 0;
                winSound.play();
            }
            
            // 停止背景音乐
            bgMusic.pause();
            bgMusic.currentTime = 0;
            
            if (winner === 'player') {
                // 玩家获胜,根据是否为功德主增加功德数
                if (gameState.landlord === 'player') {
                    // 玩家是功德主,增加3000功德
                    const roundMerit = 3000;
                    addMeritScore(roundMerit, "功德主获胜");
                    updateGameStatus(`恭喜!您本局获得功德${roundMerit}点!累计功德${gameState.meritScore}点!`);
                } else {
                    // 玩家是农民,增加1000功德
                    const roundMerit = 1000;
                    addMeritScore(roundMerit, "农民获胜");
                    updateGameStatus(`恭喜!您本局获得功德${roundMerit}点!累计功德${gameState.meritScore}点!`);
                }
            } else {
                updateGameStatus("游戏结束!" + (winner === 'opponent1' ? "又见音" : "执力至") + "获得了胜利!");
            }
            
            // 禁用出牌按钮
            startBtn.disabled = false;
            playBtn.disabled = true;
            passBtn.disabled = true;
            hintBtn.disabled = true;
        }
        
        // 更新游戏状态信息
        function updateGameStatus(message) {
            gameStatusEl.textContent = message;
        }
        
        // 提示功能
        function showHint() {
            // 简单提示:选择最小的合法出牌
            const cards = gameState.playerCards;
            const hintCards = getPlayableCards(cards, gameState.lastPlayedCards, gameState.lastPlayer === 'player');
            
            if (hintCards.length > 0) {
                // 高亮提示的牌
                const cardElements = document.querySelectorAll('#player-cards-container .player-card');
                cardElements.forEach(cardEl => {
                    cardEl.classList.remove('selected');
                    const index = parseInt(cardEl.dataset.index);
                    const card = cards[index];
                    if (hintCards.some(hintCard => 
                        hintCard.value === card.value && hintCard.suit === card.suit)) {
                        cardEl.classList.add('selected');
                    }
                });
                
                updateGameStatus("已提示可出的牌");
            } else {
                updateGameStatus("没有合适的牌可出,建议点击'不出'");
            }
        }
        
        // 显示功德回向界面
        function showMeritTransfer() {
            if (gameState.meritScore <= 0) {
                updateGameStatus("您当前没有功德可以回向");
                return;
            }
            
            // 显示当前功德数
            currentMeritDisplay.textContent = gameState.meritScore;
            
            // 隐藏输入框
            lovedNameInputContainer.style.display = 'none';
            lovedNameInput.value = '';
            
            // 显示功德回向界面
            meritTransferEl.classList.remove('hidden');
        }
        
        // 功德回向给一切众生
        function meritToAllBeings() {
            const currentMerit = gameState.meritScore;
            
            // 清空功德数
            gameState.meritScore = 0;
            updateMeritScore();
            
            // 显示确认消息
            meritConfirmText.textContent = `您已将 ${currentMerit} 点功德全部回向给一切众生!`;
            meritConfirmEl.classList.remove('hidden');
            
            // 隐藏功德回向界面
            meritTransferEl.classList.add('hidden');
            
            // 更新游戏状态
            updateGameStatus(`已将 ${currentMerit} 点功德回向一切众生`);
        }
        
        // 功德回向给所爱的人
        function meritToLovedOnes() {
            // 显示输入框
            lovedNameInputContainer.style.display = 'block';
        }
        
        // 提交所爱人的名字
        function submitLovedName() {
            const lovedName = lovedNameInput.value.trim();
            const currentMerit = gameState.meritScore;
            
            if (!lovedName) {
                updateGameStatus("请输入所爱人的名字");
                return;
            }
            
            // 清空功德数
            gameState.meritScore = 0;
            updateMeritScore();
            
            // 显示确认消息
            meritConfirmText.textContent = `您已将 ${currentMerit} 点功德全部回向给 ${lovedName}!`;
            meritConfirmEl.classList.remove('hidden');
            
            // 隐藏功德回向界面和输入框
            meritTransferEl.classList.add('hidden');
            lovedNameInputContainer.style.display = 'none';
            lovedNameInput.value = '';
            
            // 更新游戏状态
            updateGameStatus(`已将 ${currentMerit} 点功德回向给 ${lovedName}`);
        }
        
        // 取消功德回向
        function cancelMeritTransfer() {
            // 隐藏功德回向界面
            meritTransferEl.classList.add('hidden');
            lovedNameInputContainer.style.display = 'none';
            lovedNameInput.value = '';
            
            // 返回游戏
            updateGameStatus("已取消功德回向");
        }
        
        // 音频控制 - 背景音乐开关
        function toggleMusic() {
            gameState.musicEnabled = !gameState.musicEnabled;
            
            // 更新按钮文本和样式
            if (gameState.musicEnabled) {
                musicToggleBtn.textContent = "背景音乐: 开";
                musicToggleBtn.classList.remove("music-on");
                bgMusic.play().catch(e => console.log("播放音乐失败"));
            } else {
                musicToggleBtn.textContent = "背景音乐: 关";
                musicToggleBtn.classList.add("music-on");
                bgMusic.pause();
            }
        }
        
        // 确认功德回向
        function confirmMeritTransfer() {
            meritConfirmEl.classList.add('hidden');
        }
        
        // 事件监听
        startBtn.addEventListener('click', initGame);
        playBtn.addEventListener('click', playerPlay);
        passBtn.addEventListener('click', playerPass);
        hintBtn.addEventListener('click', showHint);
        musicToggleBtn.addEventListener('click', toggleMusic);
        meritTransferBtn.addEventListener('click', showMeritTransfer);
        callLandlordBtn.addEventListener('click', callLandlord);
        passLandlordBtn.addEventListener('click', passLandlord);
        meritToAllBtn.addEventListener('click', meritToAllBeings);
        meritToLovedBtn.addEventListener('click', meritToLovedOnes);
        meritCancelBtn.addEventListener('click', cancelMeritTransfer);
        submitLovedNameBtn.addEventListener('click', submitLovedName);
        meritConfirmBtn.addEventListener('click', confirmMeritTransfer);
        
        // 初始UI更新
        updateMeritScore();
        updateUI();
        
        // 初始设置背景音乐按钮样式
        if (gameState.musicEnabled) {
            musicToggleBtn.textContent = "背景音乐: 开";
            musicToggleBtn.classList.remove("music-on");
        } else {
            musicToggleBtn.textContent = "背景音乐: 关";
            musicToggleBtn.classList.add("music-on");
        }
        
        // 初始播放背景音乐
        if (gameState.musicEnabled) {
            setTimeout(() => {
                bgMusic.play().catch(e => {
                    console.log("背景音乐自动播放被阻止,用户可能需要手动播放");
                });
            }, 1000);
        }
        
        // iOS触摸事件优化
        document.addEventListener('touchstart', function() {}, {passive: true});
        document.addEventListener('touchmove', function(e) {
            // 防止滚动时页面缩放
            if (e.scale !== 1) {
                e.preventDefault();
            }
        }, {passive: false});
    </script>
</body>
</html>

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐