【白板类-01-01】20260326水果连连看01(html+希沃白板)

自从装了希沃白板电视屏,发现它可以触屏后,我想设计更多"人机"互动的学习材料

教学类-133-02】20260309狮虎旗(井字棋)02豆包添加重置按钮、先手及音频提示、结果及音频提示、表格结果统计(HTML+ CSS + JavaScript)https://mp.csdn.net/mp_blog/creation/editor/159433649

问Deepseek

还是决定先做一个"水果练练看"套用狮虎旗里面的头尾(Python封装)

python 复制代码
'''
01水果连连看6*6 多个关卡,难度一样
Deepseek,阿夏
202060325

'''


def calculate_gold_profit():
    """
    积存金买卖计算器
    支持自定义买入价、卖出价、克数、手续费率
    计算利息、实际收益和收益率百分比
    """
    print("=" * 50)
    print("💰 积存金买卖计算器")
    print("=" * 50)
    
    # 获取用户输入
    try:
        buy_price = float(input("请输入买入价(元/克):"))
        sell_price = float(input("请输入卖出价(元/克):"))
        grams = float(input("请输入购买克数:"))
        fee_rate = float(input("请输入手续费率(%):"))
        
        print("\n" + "=" * 50)
        print("📊 计算中...")
        print("=" * 50)
        
        # 计算买入总金额
        buy_total = buy_price * grams
        
        # 计算卖出总金额(未扣除手续费)
        sell_total_before_fee = sell_price * grams
        
        # 计算手续费
        fee = sell_total_before_fee * (fee_rate / 100)
        
        # 实际到手金额(扣除手续费后)
        sell_total_after_fee = sell_total_before_fee - fee
        
        # 计算账面收益(未扣除手续费)
        paper_profit = sell_total_before_fee - buy_total
        paper_profit_percent = (paper_profit / buy_total) * 100 if buy_total > 0 else 0
        
        # 计算实际收益(扣除手续费后)
        actual_profit = sell_total_after_fee - buy_total
        actual_profit_percent = (actual_profit / buy_total) * 100 if buy_total > 0 else 0
        
        # 计算利息(实际收益)
        interest = actual_profit
        
        # 输出结果
        print(f"\n📈 交易明细:")
        print(f"  • 买入总金额:{buy_total:.2f} 元")
        print(f"  • 卖出总金额(未扣费):{sell_total_before_fee:.2f} 元")
        print(f"  • 手续费({fee_rate}%):{fee:.2f} 元")
        print(f"  • 实际到手金额:{sell_total_after_fee:.2f} 元")
        
        print(f"\n💰 收益分析:")
        print(f"  • 账面收益:{paper_profit:+.2f} 元")
        print(f"  • 账面收益率:{paper_profit_percent:+.2f}%")
        print(f"  • 实际收益(利息):{actual_profit:+.2f} 元")
        print(f"  • 实际收益率:{actual_profit_percent:+.2f}%")
        
        # 额外输出示例数据验证
        if buy_price == 1000 and sell_price == 1010 and grams == 1 and fee_rate == 0.4:
            print(f"\n✨ 验证示例(1000买入,1010卖出,1克,0.4%手续费):")
            print(f"  • 买入:{buy_total:.2f} 元")
            print(f"  • 卖出未扣费:{sell_total_before_fee:.2f} 元")
            print(f"  • 手续费:{fee:.2f} 元")
            print(f"  • 实际收益:{actual_profit:.2f} 元")
            print(f"  • 实际收益率:{actual_profit_percent:.2f}%")
        
        # 判断盈亏
        if actual_profit > 0:
            print(f"\n🎉 恭喜!本次交易盈利 {actual_profit:.2f} 元!")
        elif actual_profit < 0:
            print(f"\n📉 本次交易亏损 {abs(actual_profit):.2f} 元,请谨慎操作!")
        else:
            print(f"\n🤝 本次交易盈亏平衡,无利润。")
        
        # 盈亏平衡点分析
        if actual_profit < 0:
            break_even_price = (buy_total + fee) / grams
            print(f"\n💡 盈亏平衡点:{break_even_price:.2f} 元/克")
            print(f"   需要卖出价达到 {break_even_price:.2f} 元才能保本")
        
        # 返回结果字典,方便后续使用
        result = {
            'buy_price': buy_price,
            'sell_price': sell_price,
            'grams': grams,
            'fee_rate': fee_rate,
            'buy_total': buy_total,
            'sell_total_before_fee': sell_total_before_fee,
            'fee': fee,
            'sell_total_after_fee': sell_total_after_fee,
            'paper_profit': paper_profit,
            'paper_profit_percent': paper_profit_percent,
            'actual_profit': actual_profit,
            'actual_profit_percent': actual_profit_percent
        }
        
        return result
        
    except ValueError:
        print("❌ 输入错误!请输入有效的数字。")
        return None
    except Exception as e:
        print(f"❌ 计算错误:{e}")
        return None


def calculate_with_batch():
    """
    批量计算多个场景,方便对比
    """
    print("\n" + "=" * 50)
    print("📊 批量计算模式")
    print("=" * 50)
    
    # 定义几个典型场景
    scenarios = [
        {"name": "示例场景1(1000买入1010卖出1克)", "buy": 1000, "sell": 1010, "grams": 1, "fee": 0.4},
        {"name": "示例场景2(1000买入1020卖出1克)", "buy": 1000, "sell": 1020, "grams": 1, "fee": 0.4},
        {"name": "示例场景3(1000买入1005卖出1克)", "buy": 1000, "sell": 1005, "grams": 1, "fee": 0.4},
        {"name": "示例场景4(1000买入990卖出1克)", "buy": 1000, "sell": 990, "grams": 1, "fee": 0.4},
        {"name": "示例场景5(500买入510卖出10克)", "buy": 500, "sell": 510, "grams": 10, "fee": 0.4},
    ]
    
    print("\n📈 各场景收益对比:\n")
    print(f"{'场景名称':<30} {'实际收益':<15} {'实际收益率':<15}")
    print("-" * 60)
    
    for scenario in scenarios:
        buy_total = scenario["buy"] * scenario["grams"]
        sell_total_before = scenario["sell"] * scenario["grams"]
        fee = sell_total_before * (scenario["fee"] / 100)
        actual_profit = (sell_total_before - fee) - buy_total
        actual_profit_percent = (actual_profit / buy_total) * 100
        
        print(f"{scenario['name']:<30} {actual_profit:+.2f}元{'':<10} {actual_profit_percent:+.2f}%")
    
    print("\n💡 提示:手续费会显著影响实际收益,尤其是小额交易时")


def calculate_with_visual():
    """
    带可视化显示的版本,使用emoji和格式美化
    """
    print("\n" + "🌟" * 25)
    print("         积存金买卖计算器(豪华版)")
    print("🌟" * 25)
    
    try:
        print("\n请输入以下信息:")
        buy_price = float(input("  📊 买入价(元/克):"))
        sell_price = float(input("  📈 卖出价(元/克):"))
        grams = float(input("  ⚖️  购买克数:"))
        fee_rate = float(input("  💸 手续费率(%):"))
        
        # 计算
        buy_total = buy_price * grams
        sell_total_before = sell_price * grams
        fee = sell_total_before * (fee_rate / 100)
        sell_total_after = sell_total_before - fee
        actual_profit = sell_total_after - buy_total
        actual_profit_percent = (actual_profit / buy_total) * 100 if buy_total > 0 else 0
        
        # 输出结果(美化版)
        print("\n" + "=" * 50)
        print("📋 交易结算单")
        print("=" * 50)
        
        print(f"\n【买入信息】")
        print(f"  单价:{buy_price:.2f} 元/克")
        print(f"  数量:{grams:.2f} 克")
        print(f"  总价:{buy_total:.2f} 元")
        
        print(f"\n【卖出信息】")
        print(f"  单价:{sell_price:.2f} 元/克")
        print(f"  总价(毛额):{sell_total_before:.2f} 元")
        print(f"  手续费:{fee:.2f} 元")
        print(f"  净收入:{sell_total_after:.2f} 元")
        
        print(f"\n【收益分析】")
        if actual_profit > 0:
            print(f"  🎉 实际收益:{actual_profit:+.2f} 元")
            print(f"  🎉 收益率:{actual_profit_percent:+.2f}%")
            profit_icon = "📈"
        elif actual_profit < 0:
            print(f"  📉 实际亏损:{actual_profit:+.2f} 元")
            print(f"  📉 收益率:{actual_profit_percent:+.2f}%")
            profit_icon = "📉"
        else:
            print(f"  🤝 盈亏平衡")
            profit_icon = "⚖️"
        
        # 简单的趋势图
        print(f"\n【趋势示意】")
        price_change = sell_price - buy_price
        if price_change > 0:
            arrow = "▲"
            trend = "上涨"
        else:
            arrow = "▼"
            trend = "下跌"
        
        print(f"  价格变动:{arrow} {abs(price_change):.2f} 元/克 ({trend})")
        print(f"  本金:{buy_total:.2f} 元")
        print(f"  手续费占比:{(fee / buy_total * 100):.2f}%")
        
        # 盈亏平衡点提示
        if actual_profit <= 0:
            break_even = (buy_total + fee) / grams
            print(f"\n💡 盈亏平衡价:{break_even:.2f} 元/克")
            
        return {
            'buy_total': buy_total,
            'sell_total_after': sell_total_after,
            'actual_profit': actual_profit,
            'actual_profit_percent': actual_profit_percent
        }
        
    except ValueError:
        print("❌ 输入无效,请输入数字!")
        return None


if __name__ == "__main__":
    print("🎯 积存金买卖计算工具")
    print("=" * 50)
    print("请选择模式:")
    print("1. 单次计算模式")
    print("2. 批量对比模式")
    print("3. 豪华可视化模式")
    print("4. 退出")
    
    while True:
        try:
            choice = input("\n请选择(1/2/3/4):").strip()
            
            if choice == '1':
                calculate_gold_profit()
                break
            elif choice == '2':
                calculate_with_batch()
                break
            elif choice == '3':
                calculate_with_visual()
                break
            elif choice == '4':
                print("👋 再见!")
                break
            else:
                print("❌ 请输入 1、2、3 或 4")
        except KeyboardInterrupt:
            print("\n\n👋 程序已退出")
            break

点掉一组,显示10分

不会做,可以提示按那些

重新洗牌,重新排列

但是我感觉每个都是红红的水果,不容易辨认

python 复制代码
'''
02水果连连看6*6 多个关卡,难度一样
水果是红色,但是彩色背景
Deepseek,阿夏
202060325

'''

import os

def generate_fruit_link_game():
    """
    生成水果连连看游戏HTML文件
    包含积分、关卡机制,每关结束后自动进入下一关,难度保持不变
    每种水果都有独特的颜色,让游戏更加生动
    """
    html_content = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>彩色水果连连看 - 益智闯关</title>
    <style>
        * {
            user-select: none;
            -webkit-tap-highlight-color: transparent;
        }

        body {
            background: linear-gradient(145deg, #1a6d2b 0%, #0e4a1a 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Segoe UI', 'Comic Neue', 'Comic Neue', 'Comic Sans MS', 'Chalkboard SE', cursive, sans-serif;
            margin: 0;
            padding: 20px;
        }

        /* 游戏主面板 */
        .game-container {
            background: #fdf8e7;
            border-radius: 72px;
            box-shadow: 0 25px 40px rgba(0,0,0,0.3), inset 0 1px 3px rgba(255,255,200,0.8);
            padding: 20px 25px 30px 25px;
            text-align: center;
            transition: all 0.2s;
        }

        /* 头部信息 */
        .info-panel {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            background: #f5e5c8;
            padding: 12px 24px;
            border-radius: 60px;
            margin-bottom: 20px;
            gap: 20px;
            flex-wrap: wrap;
            box-shadow: inset 0 1px 4px rgba(0,0,0,0.05), 0 6px 12px rgba(0,0,0,0.1);
        }

        .score-box, .level-box {
            background: #5a3e2b;
            color: #ffefb9;
            padding: 8px 20px;
            border-radius: 40px;
            font-weight: bold;
            font-size: 1.5rem;
            text-shadow: 0 2px 0 #2e1e12;
            box-shadow: inset 0 1px 2px rgba(255,255,200,0.3), 0 4px 8px rgba(0,0,0,0.2);
        }

        .score-box span, .level-box span {
            font-size: 1.8rem;
            margin-left: 8px;
            color: #ffd966;
        }

        /* 网格区域 */
        .grid-wrapper {
            background: #fffaec;
            border-radius: 48px;
            padding: 20px;
            box-shadow: inset 0 0 0 2px #fff9e6, inset 0 0 0 6px #e7dbb8, 0 15px 20px rgba(0,0,0,0.2);
        }

        .game-grid {
            display: grid;
            grid-template-columns: repeat(6, 1fr);
            gap: 10px;
            justify-items: center;
            align-items: center;
            margin: 0 auto;
        }

        /* 卡片样式 - 带颜色的水果 */
        .card {
            aspect-ratio: 1 / 1;
            width: 100%;
            max-width: 85px;
            border-radius: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 2.7rem;
            cursor: pointer;
            transition: all 0.12s linear;
            box-shadow: 0 8px 0 rgba(0,0,0,0.2);
            transform: translateY(-2px);
            background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.8), rgba(255,255,255,0.4));
        }

        /* 各种水果的不同颜色 */
        .card[data-fruit="🍎"] { background: linear-gradient(135deg, #ff4d4d, #cc0000); box-shadow: 0 8px 0 #990000; }
        .card[data-fruit="🍊"] { background: linear-gradient(135deg, #ffaa33, #ff8800); box-shadow: 0 8px 0 #cc6600; }
        .card[data-fruit="🍒"] { background: linear-gradient(135deg, #cc3399, #990066); box-shadow: 0 8px 0 #660044; }
        .card[data-fruit="🍓"] { background: linear-gradient(135deg, #ff6699, #ff3366); box-shadow: 0 8px 0 #cc0044; }
        .card[data-fruit="🍉"] { background: linear-gradient(135deg, #66cc66, #339933); box-shadow: 0 8px 0 #226622; }
        .card[data-fruit="🍑"] { background: linear-gradient(135deg, #ffcc88, #ffaa66); box-shadow: 0 8px 0 #cc8844; }
        .card[data-fruit="🍍"] { background: linear-gradient(135deg, #ffdd77, #ffcc44); box-shadow: 0 8px 0 #ccaa33; }
        .card[data-fruit="🥝"] { background: linear-gradient(135deg, #88cc44, #66aa33); box-shadow: 0 8px 0 #448822; }
        .card[data-fruit="🍌"] { background: linear-gradient(135deg, #ffee88, #ffdd66); box-shadow: 0 8px 0 #ccaa44; }
        .card[data-fruit="🍇"] { background: linear-gradient(135deg, #aa66ff, #8844cc); box-shadow: 0 8px 0 #552299; }

        .card.selected {
            box-shadow: 0 0 0 4px #ffb347, 0 0 0 8px #ffe484, 0 8px 0 rgba(0,0,0,0.2);
            transform: scale(0.97) translateY(0px);
        }

        .card.removed {
            visibility: hidden;
            pointer-events: none;
            box-shadow: none;
            transform: scale(0.8);
            background: transparent;
        }

        /* 按钮区域 */
        .action-buttons {
            margin-top: 25px;
            display: flex;
            justify-content: center;
            gap: 20px;
            flex-wrap: wrap;
        }

        button {
            background: #ffb347;
            border: none;
            font-family: inherit;
            font-weight: bold;
            font-size: 1.3rem;
            padding: 10px 28px;
            border-radius: 60px;
            color: #3d2a1a;
            cursor: pointer;
            box-shadow: 0 5px 0 #a45d2e;
            transition: 0.07s linear;
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }

        button:active {
            transform: translateY(3px);
            box-shadow: 0 2px 0 #a45d2e;
        }

        .message-area {
            margin-top: 20px;
            background: #e9dbbc;
            border-radius: 40px;
            padding: 8px 16px;
            font-size: 1.2rem;
            font-weight: bold;
            color: #674e2c;
            min-height: 3.5rem;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 12px;
            flex-wrap: wrap;
        }

        /* 辅助工具 */
        @media (max-width: 550px) {
            .game-grid {
                gap: 6px;
            }
            .card {
                font-size: 2rem;
            }
            .score-box, .level-box {
                font-size: 1rem;
                padding: 4px 12px;
            }
            .score-box span, .level-box span {
                font-size: 1.4rem;
            }
            button {
                font-size: 1rem;
                padding: 6px 20px;
            }
        }

        footer {
            font-size: 0.7rem;
            margin-top: 15px;
            color: #b48b4b;
        }
    </style>
</head>
<body>
<div class="game-container">
    <div class="info-panel">
        <div class="score-box">🍍 积分 <span id="scoreValue">0</span></div>
        <div class="level-box">🍎 第 <span id="levelValue">1</span> 关</div>
    </div>

    <div class="grid-wrapper">
        <div class="game-grid" id="gameGrid"></div>
    </div>

    <div class="action-buttons">
        <button id="shuffleBtn">🔄 洗牌</button>
        <button id="refreshHintBtn">✨ 提示</button>
    </div>

    <div class="message-area" id="messageArea">
        🍉 点击相同水果,直线/拐两弯连接消除~
    </div>
    <footer>⭐ 每消除一对+10分 | 清空所有水果自动进入下一关,难度不变 | 🎨 每种水果都有独特颜色</footer>
</div>

<script>
    // ---------- 游戏配置 ----------
    const ROWS = 6;
    const COLS = 6;
    // 水果表情库 (丰富可爱,每个都有独特颜色)
    const FRUITS = ['🍎', '🍊', '🍒', '🍓', '🍉', '🍑', '🍍', '🥝', '🍌', '🍇'];
    // 每一关使用的水果种类数 (保持难度适中,6x6网格每种出现6次)
    const FRUIT_TYPES_PER_LEVEL = 6;   // 6种水果,每种出现6次 = 36格
    
    let currentLevel = 1;
    let currentScore = 0;
    let gridData = [];      // 二维数组存储水果字符,null表示已消除
    let selectedRow = null, selectedCol = null;
    
    // DOM 元素
    const gridContainer = document.getElementById('gameGrid');
    const scoreSpan = document.getElementById('scoreValue');
    const levelSpan = document.getElementById('levelValue');
    const messageDiv = document.getElementById('messageArea');
    const shuffleBtn = document.getElementById('shuffleBtn');
    const hintBtn = document.getElementById('refreshHintBtn');
    
    // 辅助函数: 显示消息
    function showMessage(msg, isError = false) {
        messageDiv.innerHTML = `${isError ? '⚠️ ' : '🍬 '} ${msg}`;
        setTimeout(() => {
            if (messageDiv.innerHTML.includes(msg)) {
                // 保持一会但是不清空过度消息
            }
        }, 2000);
    }
    
    // 刷新分数UI
    function updateScoreUI() {
        scoreSpan.innerText = currentScore;
    }
    
    // 刷新关卡UI
    function updateLevelUI() {
        levelSpan.innerText = currentLevel;
    }
    
    // 连连看核心算法: 判断两点之间是否能直线或一个拐点/两个拐点消除
    function canConnect(row1, col1, row2, col2, data) {
        if (row1 === row2 && col1 === col2) return false;
        if (data[row1][col1] === null || data[row2][col2] === null) return false;
        if (data[row1][col1] !== data[row2][col2]) return false;
        
        const rows = data.length;
        const cols = data[0].length;
        
        // 临时检查函数: 水平直线
        function checkRowClear(r, cA, cB) {
            let minC = Math.min(cA, cB);
            let maxC = Math.max(cA, cB);
            for (let i = minC + 1; i < maxC; i++) {
                if (data[r][i] !== null) return false;
            }
            return true;
        }
        // 垂直直线
        function checkColClear(c, rA, rB) {
            let minR = Math.min(rA, rB);
            let maxR = Math.max(rA, rB);
            for (let i = minR + 1; i < maxR; i++) {
                if (data[i][c] !== null) return false;
            }
            return true;
        }
        
        // 1. 同行直线
        if (row1 === row2 && checkRowClear(row1, col1, col2)) return true;
        // 同列直线
        if (col1 === col2 && checkColClear(col1, row1, row2)) return true;
        
        // 2. 一个拐点
        if (data[row1][col2] === null && checkRowClear(row1, col1, col2) && checkColClear(col2, row1, row2)) {
            return true;
        }
        if (data[row2][col1] === null && checkColClear(col1, row1, row2) && checkRowClear(row2, col1, col2)) {
            return true;
        }
        
        // 3. 两个拐点: 扫描列
        for (let i = 0; i < rows; i++) {
            if (i !== row1 && i !== row2) {
                if (data[i][col1] === null && data[i][col2] === null &&
                    checkColClear(col1, row1, i) && checkRowClear(i, col1, col2) && checkColClear(col2, i, row2)) {
                    return true;
                }
            }
        }
        // 扫描行
        for (let j = 0; j < cols; j++) {
            if (j !== col1 && j !== col2) {
                if (data[row1][j] === null && data[row2][j] === null &&
                    checkRowClear(row1, col1, j) && checkColClear(j, row1, row2) && checkRowClear(row2, j, col2)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    // 检查是否胜利
    function isWin() {
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) return false;
            }
        }
        return true;
    }
    
    // 进入下一关
    function nextLevel() {
        currentLevel++;
        updateLevelUI();
        initLevelGrid();
        clearSelected();
        showMessage(`🎉 恭喜过关!进入第 ${currentLevel} 关,继续消除彩色水果吧!`, false);
        setTimeout(() => {
            if (!hasRemainingMoves()) {
                autoShuffleSafe();
                showMessage("🃏 没有可消除的对子啦,自动洗牌一次", false);
            }
        }, 200);
    }
    
    // 检测当前是否还有可消除的对
    function hasRemainingMoves() {
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if ((i === m && j === n)) continue;
                            if (gridData[m][n] !== null && gridData[i][j] === gridData[m][n]) {
                                if (canConnect(i, j, m, n, gridData)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    
    // 自动洗牌
    function shuffleBoard() {
        let fruitsList = [];
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    fruitsList.push(gridData[i][j]);
                }
            }
        }
        for (let i = fruitsList.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [fruitsList[i], fruitsList[j]] = [fruitsList[j], fruitsList[i]];
        }
        let idx = 0;
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    gridData[i][j] = fruitsList[idx++];
                }
            }
        }
        renderGrid();
        clearSelected();
        showMessage("♻️ 重新洗牌啦,继续挑战彩色水果吧", false);
    }
    
    function autoShuffleSafe() {
        shuffleBoard();
        if (!hasRemainingMoves()) {
            shuffleBoard();
        }
    }
    
    // 提示功能
    let hintTimer = null;
    function giveHint() {
        if (hintTimer) clearTimeout(hintTimer);
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if ((i === m && j === n)) continue;
                            if (gridData[m][n] !== null && gridData[i][j] === gridData[m][n]) {
                                if (canConnect(i, j, m, n, gridData)) {
                                    highlightPair(i, j, m, n);
                                    showMessage(`💡 试试消除 ${gridData[i][j]} 吧!`, false);
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
        showMessage("🤔 暂时没有可消除的水果,试试洗牌吧!", true);
    }
    
    function highlightPair(row1, col1, row2, col2) {
        const cards = document.querySelectorAll('.card');
        const idx1 = row1 * COLS + col1;
        const idx2 = row2 * COLS + col2;
        if (cards[idx1] && cards[idx2]) {
            cards[idx1].style.boxShadow = "0 0 0 4px gold, 0 0 0 8px #ffb347, 0 8px 0 rgba(0,0,0,0.2)";
            cards[idx2].style.boxShadow = "0 0 0 4px gold, 0 0 0 8px #ffb347, 0 8px 0 rgba(0,0,0,0.2)";
            if (hintTimer) clearTimeout(hintTimer);
            hintTimer = setTimeout(() => {
                renderGrid();
            }, 1800);
        }
    }
    
    // 消除一对
    function eliminatePair(row1, col1, row2, col2) {
        if (!canConnect(row1, col1, row2, col2, gridData)) return false;
        gridData[row1][col1] = null;
        gridData[row2][col2] = null;
        currentScore += 10;
        updateScoreUI();
        renderGrid();
        clearSelected();
        showMessage(`🎉 +10分!消除成功!`, false);
        
        if (isWin()) {
            showMessage(`✨✨ 太厉害了!通关第 ${currentLevel} 关 ✨✨`, false);
            nextLevel();
            return true;
        }
        
        if (!hasRemainingMoves()) {
            autoShuffleSafe();
            showMessage("🧹 没有更多消除啦,已经帮你洗牌~", false);
        }
        return true;
    }
    
    function clearSelected() {
        selectedRow = null;
        selectedCol = null;
        renderGrid();
    }
    
    // 渲染网格 - 添加data-fruit属性来控制颜色
    function renderGrid() {
        gridContainer.innerHTML = '';
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                const fruit = gridData[i][j];
                const card = document.createElement('div');
                card.className = 'card';
                if (fruit === null) {
                    card.classList.add('removed');
                    card.innerText = '✨';
                    card.style.fontSize = '2rem';
                    card.style.opacity = '0.6';
                } else {
                    card.innerText = fruit;
                    card.setAttribute('data-fruit', fruit);
                }
                if (selectedRow === i && selectedCol === j && fruit !== null) {
                    card.classList.add('selected');
                }
                card.addEventListener('click', (function(r, c) {
                    return function() { onCardClick(r, c); };
                })(i, j));
                gridContainer.appendChild(card);
            }
        }
    }
    
    // 点击处理
    function onCardClick(row, col) {
        if (gridData[row][col] === null) return;
        
        if (selectedRow === null || selectedCol === null) {
            selectedRow = row;
            selectedCol = col;
            renderGrid();
            showMessage(`选中 ${gridData[row][col]} ,再点击另一个相同水果消除~`, false);
            return;
        }
        
        const sRow = selectedRow, sCol = selectedCol;
        if (sRow === row && sCol === col) {
            clearSelected();
            showMessage("已取消选中", false);
            return;
        }
        
        if (gridData[sRow][sCol] !== null && gridData[row][col] !== null &&
            gridData[sRow][sCol] === gridData[row][col] && canConnect(sRow, sCol, row, col, gridData)) {
            eliminatePair(sRow, sCol, row, col);
        } else {
            if (gridData[row][col] !== null) {
                if (gridData[sRow][sCol] !== gridData[row][col]) {
                    showMessage(`🍇 ${gridData[sRow][sCol]} 和 ${gridData[row][col]} 不一样,不能消除哦`, true);
                } else {
                    showMessage(`🚫 路径不通,最多拐两弯~ 再试试洗牌吧`, true);
                }
                selectedRow = row;
                selectedCol = col;
                renderGrid();
            } else {
                clearSelected();
            }
        }
    }
    
    // 初始化关卡网格
    function initLevelGrid() {
        const totalCells = ROWS * COLS;
        const typesCount = FRUIT_TYPES_PER_LEVEL;
        const eachCount = totalCells / typesCount;
        let fruitPool = [];
        for (let i = 0; i < typesCount; i++) {
            const fruitChar = FRUITS[i % FRUITS.length];
            for (let k = 0; k < eachCount; k++) {
                fruitPool.push(fruitChar);
            }
        }
        for (let i = fruitPool.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [fruitPool[i], fruitPool[j]] = [fruitPool[j], fruitPool[i]];
        }
        gridData = Array(ROWS).fill().map(() => Array(COLS).fill(null));
        let idx = 0;
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                gridData[i][j] = fruitPool[idx++];
            }
        }
        if (!hasRemainingMoves()) {
            for (let i = 0; i < ROWS && !hasRemainingMoves(); i++) {
                for (let j = 0; j < COLS; j++) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if (gridData[i][j] && gridData[m][n] && (i !== m || j !== n) && gridData[i][j] !== gridData[m][n]) {
                                let temp = gridData[i][j];
                                gridData[i][j] = gridData[m][n];
                                gridData[m][n] = temp;
                                if (hasRemainingMoves()) break;
                                else {
                                    let temp2 = gridData[i][j];
                                    gridData[i][j] = gridData[m][n];
                                    gridData[m][n] = temp2;
                                }
                            }
                        }
                        if (hasRemainingMoves()) break;
                    }
                    if (hasRemainingMoves()) break;
                }
            }
        }
    }
    
    // 重置游戏
    function resetGame() {
        currentLevel = 1;
        currentScore = 0;
        updateScoreUI();
        updateLevelUI();
        initLevelGrid();
        clearSelected();
        renderGrid();
        showMessage("🍍 彩色水果连连看开始啦!每种水果颜色都不同哦~", false);
        if (!hasRemainingMoves()) {
            shuffleBoard();
        }
    }
    
    function onShuffle() {
        shuffleBoard();
        if (!hasRemainingMoves()) {
            shuffleBoard();
            showMessage("🔁 再次洗牌保证可玩", false);
        }
    }
    
    shuffleBtn.addEventListener('click', () => onShuffle());
    hintBtn.addEventListener('click', () => giveHint());
    
    resetGame();
</script>
</body>
</html>'''
    
    # 保存到当前目录下的文件
    file_path = os.path.join(os.getcwd(), r'D:\test\20桌面素材\20260326水果连连看\02彩色水果连连看_闯关版.html')
    
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        print(f'✅ 彩色水果连连看游戏已成功生成!')
        print(f'📁 文件保存位置: {file_path}')
        print('🎮 游戏特性:')
        print('  - 🌈 每种水果都有独特的颜色:苹果红色、橙子橙色、樱桃紫红、草莓粉红、西瓜绿色等')
        print('  - 6x6水果连连看,经典的直线/拐弯消除规则')
        print('  - 每消除一对水果+10分')
        print('  - 清空所有水果自动进入下一关,难度保持不变')
        print('  - 支持洗牌和提示功能,避免卡关')
        print('  - 适合3-4岁幼儿的彩色水果设计和触摸操作')
        print('  - 响应式布局,支持平板和手机')
        return file_path
    except Exception as e:
        print(f'❌ 生成文件失败: {e}')
        return None

if __name__ == '__main__':
    # 直接运行即可生成HTML文件
    generate_fruit_link_game()

它是红色水果,彩色底纹,虽然与我想的不一样(我想要黄色生梨、橘色橘子、紫色葡萄)但是还行,能看到不同颜色的底纹。

最后添加一些音频效果

python 复制代码
'''
02水果连连看6*6 多个关卡,难度一样
水果是红色,但是彩色背景
增加音频,点按钮有声音,通关后会提示一共多少分
Deepseek,阿夏
202060325

'''

import os

def generate_fruit_link_game():
    """
    生成水果连连看游戏HTML文件
    包含积分、关卡机制,每关结束后自动进入下一关,难度保持不变
    每种水果都有独特的颜色,让游戏更加生动
    过关时播放音乐并语音播报得分
    """
    html_content = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>彩色水果连连看 - 益智闯关</title>
    <style>
        * {
            user-select: none;
            -webkit-tap-highlight-color: transparent;
        }

        body {
            background: linear-gradient(145deg, #1a6d2b 0%, #0e4a1a 100%);
            min-height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Segoe UI', 'Comic Neue', 'Comic Neue', 'Comic Sans MS', 'Chalkboard SE', cursive, sans-serif;
            margin: 0;
            padding: 20px;
        }

        /* 游戏主面板 */
        .game-container {
            background: #fdf8e7;
            border-radius: 72px;
            box-shadow: 0 25px 40px rgba(0,0,0,0.3), inset 0 1px 3px rgba(255,255,200,0.8);
            padding: 20px 25px 30px 25px;
            text-align: center;
            transition: all 0.2s;
        }

        /* 头部信息 */
        .info-panel {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            background: #f5e5c8;
            padding: 12px 24px;
            border-radius: 60px;
            margin-bottom: 20px;
            gap: 20px;
            flex-wrap: wrap;
            box-shadow: inset 0 1px 4px rgba(0,0,0,0.05), 0 6px 12px rgba(0,0,0,0.1);
        }

        .score-box, .level-box {
            background: #5a3e2b;
            color: #ffefb9;
            padding: 8px 20px;
            border-radius: 40px;
            font-weight: bold;
            font-size: 1.5rem;
            text-shadow: 0 2px 0 #2e1e12;
            box-shadow: inset 0 1px 2px rgba(255,255,200,0.3), 0 4px 8px rgba(0,0,0,0.2);
        }

        .score-box span, .level-box span {
            font-size: 1.8rem;
            margin-left: 8px;
            color: #ffd966;
        }

        /* 网格区域 */
        .grid-wrapper {
            background: #fffaec;
            border-radius: 48px;
            padding: 20px;
            box-shadow: inset 0 0 0 2px #fff9e6, inset 0 0 0 6px #e7dbb8, 0 15px 20px rgba(0,0,0,0.2);
        }

        .game-grid {
            display: grid;
            grid-template-columns: repeat(6, 1fr);
            gap: 10px;
            justify-items: center;
            align-items: center;
            margin: 0 auto;
        }

        /* 卡片样式 - 带颜色的水果 */
        .card {
            aspect-ratio: 1 / 1;
            width: 100%;
            max-width: 85px;
            border-radius: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 2.7rem;
            cursor: pointer;
            transition: all 0.12s linear;
            box-shadow: 0 8px 0 rgba(0,0,0,0.2);
            transform: translateY(-2px);
            background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.8), rgba(255,255,255,0.4));
        }

        /* 各种水果的不同颜色 */
        .card[data-fruit="🍎"] { background: linear-gradient(135deg, #ff4d4d, #cc0000); box-shadow: 0 8px 0 #990000; }
        .card[data-fruit="🍊"] { background: linear-gradient(135deg, #ffaa33, #ff8800); box-shadow: 0 8px 0 #cc6600; }
        .card[data-fruit="🍒"] { background: linear-gradient(135deg, #cc3399, #990066); box-shadow: 0 8px 0 #660044; }
        .card[data-fruit="🍓"] { background: linear-gradient(135deg, #ff6699, #ff3366); box-shadow: 0 8px 0 #cc0044; }
        .card[data-fruit="🍉"] { background: linear-gradient(135deg, #66cc66, #339933); box-shadow: 0 8px 0 #226622; }
        .card[data-fruit="🍑"] { background: linear-gradient(135deg, #ffcc88, #ffaa66); box-shadow: 0 8px 0 #cc8844; }
        .card[data-fruit="🍍"] { background: linear-gradient(135deg, #ffdd77, #ffcc44); box-shadow: 0 8px 0 #ccaa33; }
        .card[data-fruit="🥝"] { background: linear-gradient(135deg, #88cc44, #66aa33); box-shadow: 0 8px 0 #448822; }
        .card[data-fruit="🍌"] { background: linear-gradient(135deg, #ffee88, #ffdd66); box-shadow: 0 8px 0 #ccaa44; }
        .card[data-fruit="🍇"] { background: linear-gradient(135deg, #aa66ff, #8844cc); box-shadow: 0 8px 0 #552299; }

        .card.selected {
            box-shadow: 0 0 0 4px #ffb347, 0 0 0 8px #ffe484, 0 8px 0 rgba(0,0,0,0.2);
            transform: scale(0.97) translateY(0px);
        }

        .card.removed {
            visibility: hidden;
            pointer-events: none;
            box-shadow: none;
            transform: scale(0.8);
            background: transparent;
        }

        /* 按钮区域 */
        .action-buttons {
            margin-top: 25px;
            display: flex;
            justify-content: center;
            gap: 20px;
            flex-wrap: wrap;
        }

        button {
            background: #ffb347;
            border: none;
            font-family: inherit;
            font-weight: bold;
            font-size: 1.3rem;
            padding: 10px 28px;
            border-radius: 60px;
            color: #3d2a1a;
            cursor: pointer;
            box-shadow: 0 5px 0 #a45d2e;
            transition: 0.07s linear;
            display: inline-flex;
            align-items: center;
            gap: 8px;
        }

        button:active {
            transform: translateY(3px);
            box-shadow: 0 2px 0 #a45d2e;
        }

        .message-area {
            margin-top: 20px;
            background: #e9dbbc;
            border-radius: 40px;
            padding: 8px 16px;
            font-size: 1.2rem;
            font-weight: bold;
            color: #674e2c;
            min-height: 3.5rem;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 12px;
            flex-wrap: wrap;
        }

        /* 辅助工具 */
        @media (max-width: 550px) {
            .game-grid {
                gap: 6px;
            }
            .card {
                font-size: 2rem;
            }
            .score-box, .level-box {
                font-size: 1rem;
                padding: 4px 12px;
            }
            .score-box span, .level-box span {
                font-size: 1.4rem;
            }
            button {
                font-size: 1rem;
                padding: 6px 20px;
            }
        }

        footer {
            font-size: 0.7rem;
            margin-top: 15px;
            color: #b48b4b;
        }
        
        /* 庆祝动画 */
        @keyframes celebrate {
            0% { transform: scale(1); }
            50% { transform: scale(1.1); background: radial-gradient(circle, gold, #ffaa00); }
            100% { transform: scale(1); }
        }
        
        .celebrate-card {
            animation: celebrate 0.5s ease-in-out;
        }
    </style>
</head>
<body>
<div class="game-container">
    <div class="info-panel">
        <div class="score-box">🍍 积分 <span id="scoreValue">0</span></div>
        <div class="level-box">🍎 第 <span id="levelValue">1</span> 关</div>
    </div>

    <div class="grid-wrapper">
        <div class="game-grid" id="gameGrid"></div>
    </div>

    <div class="action-buttons">
        <button id="shuffleBtn">🔄 洗牌</button>
        <button id="refreshHintBtn">✨ 提示</button>
    </div>

    <div class="message-area" id="messageArea">
        🍉 点击相同水果,直线/拐两弯连接消除~
    </div>
    <footer>⭐ 每消除一对+10分 | 清空所有水果自动进入下一关 | 🎨 每种水果都有独特颜色 | 🎵 过关有音乐和语音庆祝</footer>
</div>

<script>
    // ---------- 游戏配置 ----------
    const ROWS = 6;
    const COLS = 6;
    // 水果表情库 (丰富可爱,每个都有独特颜色)
    const FRUITS = ['🍎', '🍊', '🍒', '🍓', '🍉', '🍑', '🍍', '🥝', '🍌', '🍇'];
    // 每一关使用的水果种类数 (保持难度适中,6x6网格每种出现6次)
    const FRUIT_TYPES_PER_LEVEL = 6;   // 6种水果,每种出现6次 = 36格
    
    let currentLevel = 1;
    let currentScore = 0;
    let gridData = [];      // 二维数组存储水果字符,null表示已消除
    let selectedRow = null, selectedCol = null;
    
    // 音频上下文 (用于播放简单音效)
    let audioContext = null;
    
    // DOM 元素
    const gridContainer = document.getElementById('gameGrid');
    const scoreSpan = document.getElementById('scoreValue');
    const levelSpan = document.getElementById('levelValue');
    const messageDiv = document.getElementById('messageArea');
    const shuffleBtn = document.getElementById('shuffleBtn');
    const hintBtn = document.getElementById('refreshHintBtn');
    
    // 播放简单胜利音乐 (使用Web Audio API)
    function playVictoryMusic() {
        try {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }
            
            const now = audioContext.currentTime;
            
            // 播放一段欢快的旋律 (C大调音阶)
            const notes = [523.25, 587.33, 659.25, 698.46, 783.99, 880.00, 987.77, 1046.50];
            const durations = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.5];
            
            notes.forEach((freq, index) => {
                const oscillator = audioContext.createOscillator();
                const gainNode = audioContext.createGain();
                
                oscillator.connect(gainNode);
                gainNode.connect(audioContext.destination);
                
                oscillator.frequency.value = freq;
                oscillator.type = 'sine';
                
                gainNode.gain.setValueAtTime(0.3, now + index * 0.2);
                gainNode.gain.exponentialRampToValueAtTime(0.0001, now + (index * 0.2) + durations[index]);
                
                oscillator.start(now + index * 0.2);
                oscillator.stop(now + (index * 0.2) + durations[index]);
            });
            
            // 添加和弦结尾
            const chordOsc = audioContext.createOscillator();
            const chordGain = audioContext.createGain();
            chordOsc.connect(chordGain);
            chordGain.connect(audioContext.destination);
            chordOsc.frequency.value = 523.25;
            chordOsc.type = 'triangle';
            chordGain.gain.setValueAtTime(0.4, now + 1.6);
            chordGain.gain.exponentialRampToValueAtTime(0.0001, now + 2.2);
            chordOsc.start(now + 1.6);
            chordOsc.stop(now + 2.2);
            
        } catch(e) {
            console.log('音频播放失败:', e);
        }
    }
    
    // 播放庆祝音效
    function playCheerSound() {
        try {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
            }
            
            const now = audioContext.currentTime;
            
            // 播放欢快的"叮叮当"音效
            const oscillator = audioContext.createOscillator();
            const gainNode = audioContext.createGain();
            
            oscillator.connect(gainNode);
            gainNode.connect(audioContext.destination);
            
            oscillator.frequency.value = 880;
            oscillator.type = 'sine';
            
            gainNode.gain.setValueAtTime(0.2, now);
            gainNode.gain.exponentialRampToValueAtTime(0.0001, now + 0.3);
            
            oscillator.start(now);
            oscillator.stop(now + 0.3);
            
            setTimeout(() => {
                const osc2 = audioContext.createOscillator();
                const gain2 = audioContext.createGain();
                osc2.connect(gain2);
                gain2.connect(audioContext.destination);
                osc2.frequency.value = 1046.5;
                osc2.type = 'sine';
                gain2.gain.setValueAtTime(0.2, now + 0.3);
                gain2.gain.exponentialRampToValueAtTime(0.0001, now + 0.6);
                osc2.start(now + 0.3);
                osc2.stop(now + 0.6);
            }, 300);
            
        } catch(e) {
            console.log('庆祝音效播放失败:', e);
        }
    }
    
    // 语音播报函数
    function speak(text) {
        if ('speechSynthesis' in window) {
            // 停止任何正在进行的语音
            window.speechSynthesis.cancel();
            
            const utterance = new SpeechSynthesisUtterance(text);
            utterance.lang = 'zh-CN';
            utterance.rate = 0.9;
            utterance.pitch = 1.2;
            utterance.volume = 1;
            
            // 选择中文语音
            const voices = window.speechSynthesis.getVoices();
            const chineseVoice = voices.find(voice => voice.lang === 'zh-CN');
            if (chineseVoice) {
                utterance.voice = chineseVoice;
            }
            
            window.speechSynthesis.speak(utterance);
        } else {
            console.log('浏览器不支持语音播报');
        }
    }
    
    // 过关庆祝函数
    function celebrateLevelCompletion() {
        const levelScore = currentScore;
        const message = `恭喜你获得 ${levelScore} 分!`;
        
        // 播放胜利音乐
        playVictoryMusic();
        
        // 语音播报
        setTimeout(() => {
            speak(message);
        }, 500);
        
        // 显示庆祝消息
        showMessage(`🎉🎉🎉 ${message} 🎉🎉🎉`, false);
        
        // 添加卡片庆祝动画
        const cards = document.querySelectorAll('.card:not(.removed)');
        cards.forEach((card, index) => {
            setTimeout(() => {
                card.classList.add('celebrate-card');
                setTimeout(() => {
                    card.classList.remove('celebrate-card');
                }, 500);
            }, index * 50);
        });
    }
    
    // 辅助函数: 显示消息
    function showMessage(msg, isError = false) {
        messageDiv.innerHTML = `${isError ? '⚠️ ' : '🍬 '} ${msg}`;
        setTimeout(() => {
            if (messageDiv.innerHTML.includes(msg)) {
                // 保持一会但是不清空过度消息
            }
        }, 3000);
    }
    
    // 刷新分数UI
    function updateScoreUI() {
        scoreSpan.innerText = currentScore;
    }
    
    // 刷新关卡UI
    function updateLevelUI() {
        levelSpan.innerText = currentLevel;
    }
    
    // 连连看核心算法: 判断两点之间是否能直线或一个拐点/两个拐点消除
    function canConnect(row1, col1, row2, col2, data) {
        if (row1 === row2 && col1 === col2) return false;
        if (data[row1][col1] === null || data[row2][col2] === null) return false;
        if (data[row1][col1] !== data[row2][col2]) return false;
        
        const rows = data.length;
        const cols = data[0].length;
        
        // 临时检查函数: 水平直线
        function checkRowClear(r, cA, cB) {
            let minC = Math.min(cA, cB);
            let maxC = Math.max(cA, cB);
            for (let i = minC + 1; i < maxC; i++) {
                if (data[r][i] !== null) return false;
            }
            return true;
        }
        // 垂直直线
        function checkColClear(c, rA, rB) {
            let minR = Math.min(rA, rB);
            let maxR = Math.max(rA, rB);
            for (let i = minR + 1; i < maxR; i++) {
                if (data[i][c] !== null) return false;
            }
            return true;
        }
        
        // 1. 同行直线
        if (row1 === row2 && checkRowClear(row1, col1, col2)) return true;
        // 同列直线
        if (col1 === col2 && checkColClear(col1, row1, row2)) return true;
        
        // 2. 一个拐点
        if (data[row1][col2] === null && checkRowClear(row1, col1, col2) && checkColClear(col2, row1, row2)) {
            return true;
        }
        if (data[row2][col1] === null && checkColClear(col1, row1, row2) && checkRowClear(row2, col1, col2)) {
            return true;
        }
        
        // 3. 两个拐点: 扫描列
        for (let i = 0; i < rows; i++) {
            if (i !== row1 && i !== row2) {
                if (data[i][col1] === null && data[i][col2] === null &&
                    checkColClear(col1, row1, i) && checkRowClear(i, col1, col2) && checkColClear(col2, i, row2)) {
                    return true;
                }
            }
        }
        // 扫描行
        for (let j = 0; j < cols; j++) {
            if (j !== col1 && j !== col2) {
                if (data[row1][j] === null && data[row2][j] === null &&
                    checkRowClear(row1, col1, j) && checkColClear(j, row1, row2) && checkRowClear(row2, j, col2)) {
                    return true;
                }
            }
        }
        return false;
    }
    
    // 检查是否胜利
    function isWin() {
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) return false;
            }
        }
        return true;
    }
    
    // 进入下一关
    function nextLevel() {
        // 先播放庆祝效果
        celebrateLevelCompletion();
        
        // 延迟进入下一关,让庆祝效果充分展示
        setTimeout(() => {
            currentLevel++;
            updateLevelUI();
            initLevelGrid();
            clearSelected();
            showMessage(`🎉 进入第 ${currentLevel} 关!继续加油~ 🎉`, false);
            setTimeout(() => {
                if (!hasRemainingMoves()) {
                    autoShuffleSafe();
                    showMessage("🃏 没有可消除的对子啦,自动洗牌一次", false);
                }
            }, 200);
        }, 2000);
    }
    
    // 检测当前是否还有可消除的对
    function hasRemainingMoves() {
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if ((i === m && j === n)) continue;
                            if (gridData[m][n] !== null && gridData[i][j] === gridData[m][n]) {
                                if (canConnect(i, j, m, n, gridData)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    
    // 自动洗牌
    function shuffleBoard() {
        let fruitsList = [];
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    fruitsList.push(gridData[i][j]);
                }
            }
        }
        for (let i = fruitsList.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [fruitsList[i], fruitsList[j]] = [fruitsList[j], fruitsList[i]];
        }
        let idx = 0;
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    gridData[i][j] = fruitsList[idx++];
                }
            }
        }
        renderGrid();
        clearSelected();
        showMessage("♻️ 重新洗牌啦,继续挑战彩色水果吧", false);
    }
    
    function autoShuffleSafe() {
        shuffleBoard();
        if (!hasRemainingMoves()) {
            shuffleBoard();
        }
    }
    
    // 提示功能
    let hintTimer = null;
    function giveHint() {
        if (hintTimer) clearTimeout(hintTimer);
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if ((i === m && j === n)) continue;
                            if (gridData[m][n] !== null && gridData[i][j] === gridData[m][n]) {
                                if (canConnect(i, j, m, n, gridData)) {
                                    highlightPair(i, j, m, n);
                                    showMessage(`💡 试试消除 ${gridData[i][j]} 吧!`, false);
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
        showMessage("🤔 暂时没有可消除的水果,试试洗牌吧!", true);
    }
    
    function highlightPair(row1, col1, row2, col2) {
        const cards = document.querySelectorAll('.card');
        const idx1 = row1 * COLS + col1;
        const idx2 = row2 * COLS + col2;
        if (cards[idx1] && cards[idx2]) {
            cards[idx1].style.boxShadow = "0 0 0 4px gold, 0 0 0 8px #ffb347, 0 8px 0 rgba(0,0,0,0.2)";
            cards[idx2].style.boxShadow = "0 0 0 4px gold, 0 0 0 8px #ffb347, 0 8px 0 rgba(0,0,0,0.2)";
            if (hintTimer) clearTimeout(hintTimer);
            hintTimer = setTimeout(() => {
                renderGrid();
            }, 1800);
        }
    }
    
    // 消除一对
    function eliminatePair(row1, col1, row2, col2) {
        if (!canConnect(row1, col1, row2, col2, gridData)) return false;
        gridData[row1][col1] = null;
        gridData[row2][col2] = null;
        currentScore += 10;
        updateScoreUI();
        renderGrid();
        clearSelected();
        
        // 播放消除音效
        playCheerSound();
        showMessage(`🎉 +10分!消除成功!`, false);
        
        if (isWin()) {
            // 胜利时触发过关庆祝
            nextLevel();
            return true;
        }
        
        if (!hasRemainingMoves()) {
            autoShuffleSafe();
            showMessage("🧹 没有更多消除啦,已经帮你洗牌~", false);
        }
        return true;
    }
    
    function clearSelected() {
        selectedRow = null;
        selectedCol = null;
        renderGrid();
    }
    
    // 渲染网格 - 添加data-fruit属性来控制颜色
    function renderGrid() {
        gridContainer.innerHTML = '';
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                const fruit = gridData[i][j];
                const card = document.createElement('div');
                card.className = 'card';
                if (fruit === null) {
                    card.classList.add('removed');
                    card.innerText = '✨';
                    card.style.fontSize = '2rem';
                    card.style.opacity = '0.6';
                } else {
                    card.innerText = fruit;
                    card.setAttribute('data-fruit', fruit);
                }
                if (selectedRow === i && selectedCol === j && fruit !== null) {
                    card.classList.add('selected');
                }
                card.addEventListener('click', (function(r, c) {
                    return function() { onCardClick(r, c); };
                })(i, j));
                gridContainer.appendChild(card);
            }
        }
    }
    
    // 点击处理
    function onCardClick(row, col) {
        if (gridData[row][col] === null) return;
        
        if (selectedRow === null || selectedCol === null) {
            selectedRow = row;
            selectedCol = col;
            renderGrid();
            showMessage(`选中 ${gridData[row][col]} ,再点击另一个相同水果消除~`, false);
            return;
        }
        
        const sRow = selectedRow, sCol = selectedCol;
        if (sRow === row && sCol === col) {
            clearSelected();
            showMessage("已取消选中", false);
            return;
        }
        
        if (gridData[sRow][sCol] !== null && gridData[row][col] !== null &&
            gridData[sRow][sCol] === gridData[row][col] && canConnect(sRow, sCol, row, col, gridData)) {
            eliminatePair(sRow, sCol, row, col);
        } else {
            if (gridData[row][col] !== null) {
                if (gridData[sRow][sCol] !== gridData[row][col]) {
                    showMessage(`🍇 ${gridData[sRow][sCol]} 和 ${gridData[row][col]} 不一样,不能消除哦`, true);
                } else {
                    showMessage(`🚫 路径不通,最多拐两弯~ 再试试洗牌吧`, true);
                }
                selectedRow = row;
                selectedCol = col;
                renderGrid();
            } else {
                clearSelected();
            }
        }
    }
    
    // 初始化关卡网格
    function initLevelGrid() {
        const totalCells = ROWS * COLS;
        const typesCount = FRUIT_TYPES_PER_LEVEL;
        const eachCount = totalCells / typesCount;
        let fruitPool = [];
        for (let i = 0; i < typesCount; i++) {
            const fruitChar = FRUITS[i % FRUITS.length];
            for (let k = 0; k < eachCount; k++) {
                fruitPool.push(fruitChar);
            }
        }
        for (let i = fruitPool.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [fruitPool[i], fruitPool[j]] = [fruitPool[j], fruitPool[i]];
        }
        gridData = Array(ROWS).fill().map(() => Array(COLS).fill(null));
        let idx = 0;
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                gridData[i][j] = fruitPool[idx++];
            }
        }
        if (!hasRemainingMoves()) {
            for (let i = 0; i < ROWS && !hasRemainingMoves(); i++) {
                for (let j = 0; j < COLS; j++) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if (gridData[i][j] && gridData[m][n] && (i !== m || j !== n) && gridData[i][j] !== gridData[m][n]) {
                                let temp = gridData[i][j];
                                gridData[i][j] = gridData[m][n];
                                gridData[m][n] = temp;
                                if (hasRemainingMoves()) break;
                                else {
                                    let temp2 = gridData[i][j];
                                    gridData[i][j] = gridData[m][n];
                                    gridData[m][n] = temp2;
                                }
                            }
                        }
                        if (hasRemainingMoves()) break;
                    }
                    if (hasRemainingMoves()) break;
                }
            }
        }
    }
    
    // 重置游戏
    function resetGame() {
        currentLevel = 1;
        currentScore = 0;
        updateScoreUI();
        updateLevelUI();
        initLevelGrid();
        clearSelected();
        renderGrid();
        showMessage("🍍 彩色水果连连看开始啦!每种水果颜色都不同哦~", false);
        if (!hasRemainingMoves()) {
            shuffleBoard();
        }
        
        // 初始化语音系统
        if ('speechSynthesis' in window) {
            // 预加载语音
            window.speechSynthesis.getVoices();
        }
    }
    
    function onShuffle() {
        shuffleBoard();
        if (!hasRemainingMoves()) {
            shuffleBoard();
            showMessage("🔁 再次洗牌保证可玩", false);
        }
    }
    
    shuffleBtn.addEventListener('click', () => onShuffle());
    hintBtn.addEventListener('click', () => giveHint());
    
    resetGame();
</script>
</body>
</html>'''
    
    # 保存到指定路径
    file_path = r'D:\test\20桌面素材\20260326水果连连看\03彩色声音水果连连看_闯关版.html'
    
    # 确保目录存在
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        print(f'✅ 彩色水果连连看游戏已成功生成!')
        print(f'📁 文件保存位置: {file_path}')
        print('🎮 游戏特性:')
        print('  - 🌈 每种水果都有独特的颜色:苹果红色、橙子橙色、樱桃紫红、草莓粉红、西瓜绿色等')
        print('  - 🎵 过关时播放动听的胜利音乐')
        print('  - 🗣️ 过关时语音播报"恭喜你获得X分"')
        print('  - 🎉 过关时有卡片庆祝动画效果')
        print('  - 6x6水果连连看,经典的直线/拐弯消除规则')
        print('  - 每消除一对水果+10分')
        print('  - 清空所有水果自动进入下一关,难度保持不变')
        print('  - 支持洗牌和提示功能,避免卡关')
        print('  - 适合3-4岁幼儿的彩色水果设计和触摸操作')
        print('  - 响应式布局,支持平板和手机')
        return file_path
    except Exception as e:
        print(f'❌ 生成文件失败: {e}')
        return None

if __name__ == '__main__':
    # 直接运行即可生成HTML文件
    generate_fruit_link_game()

点击最后两个,下面显示文字"恭喜您获得180分",同时出现声音"恭喜您获得180分"此时页面直接跳到第2关(满屏水果)

20260325小2班幼儿操作

身高够不到顶部的图案

高个子孩子可以点到顶部图案

大部分孩子都够不到顶部图案

把屏幕向下拉

幼儿抢着点,网页会放大、移动位置

因为是触屏,很灵敏,经常误触底部的360杀毒、微信、软件管家等页面会弹出来,遮挡连连看界面,幼儿无法操作。

问题:

1、多个触摸点,导致html网页会移动,放大、幼儿需要滑屏(固定操作界面)

2、其他软件页面会覆盖html页面,影响幼儿操作(关闭微信、杀毒软件。不要有其他弹窗)

3、幼儿都挤上去点击,网页四处跑动,要求幼儿排队,但是6*6的内容太多,幼儿也不熟悉玩法。后续考虑把每一关内容做的少一点,每位幼儿操作快一点。

4、希沃白板不能存储html,今天下载的html到白板里,第二天打开就删除了

5、本次用了中文.html ,结果显示html的文件名是中文或英文都不影响显示效果

在"找影子"中实现了屏幕锁定

python 复制代码
'''
02水果连连看6*6 多个关卡,难度一样
水果是红色,但是彩色背景
增加音频,
适配笔记本和希沃白板的不同显示屏比例
Deepseek,阿夏
20260324

'''

import os

def generate_fruit_link_game():
    """
    生成水果连连看游戏HTML文件
    包含积分、关卡机制,每关结束后自动进入下一关,难度保持不变
    每种水果都有独特的颜色,让游戏更加生动
    过关时播放音乐并语音播报得分
    已适配希沃白板:无滚动条、屏幕锁定、完全居中
    """
    html_content = '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, viewport-fit=cover">
    <title>彩色水果连连看 - 希沃白板适配版</title>
    <style>
        * {
            user-select: none;
            -webkit-tap-highlight-color: transparent;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        /* 完全锁定屏幕,无滚动条,固定视口 - 完美适配希沃白板 */
        html, body {
            width: 100%;
            height: 100%;
            overflow: hidden;
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            margin: 0;
            padding: 0;
            background: linear-gradient(145deg, #1a6d2b 0%, #0e4a1a 100%);
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            font-family: 'Segoe UI', 'Comic Neue', 'Comic Sans MS', 'Chalkboard SE', cursive, sans-serif;
            touch-action: none;      /* 禁止触摸滚动 */
            -ms-touch-action: none;
            overflow: hidden;
        }

        /* 游戏主面板 */
        .game-container {
            background: #fdf8e7;
            border-radius: 56px;
            box-shadow: 0 25px 40px rgba(0,0,0,0.3), inset 0 1px 3px rgba(255,255,200,0.8);
            padding: 18px 22px 24px 22px;
            width: 94%;
            max-width: 850px;
            height: auto;
            max-height: 96vh;
            display: flex;
            flex-direction: column;
            overflow: visible;
            transition: all 0.2s;
        }

        /* 头部信息 */
        .info-panel {
            display: flex;
            justify-content: space-between;
            align-items: baseline;
            background: #f5e5c8;
            padding: 10px 22px;
            border-radius: 60px;
            margin-bottom: 14px;
            gap: 16px;
            flex-wrap: wrap;
            box-shadow: inset 0 1px 4px rgba(0,0,0,0.05), 0 6px 12px rgba(0,0,0,0.1);
            flex-shrink: 0;
        }

        .score-box, .level-box {
            background: #5a3e2b;
            color: #ffefb9;
            padding: 6px 18px;
            border-radius: 40px;
            font-weight: bold;
            font-size: 1.3rem;
            text-shadow: 0 2px 0 #2e1e12;
            box-shadow: inset 0 1px 2px rgba(255,255,200,0.3), 0 4px 8px rgba(0,0,0,0.2);
        }

        .score-box span, .level-box span {
            font-size: 1.6rem;
            margin-left: 6px;
            color: #ffd966;
        }

        /* 进度条 */
        .progress-bar {
            margin: 5px 0 12px 0;
            background: #e0d6bd;
            border-radius: 20px;
            height: 8px;
            overflow: hidden;
            flex-shrink: 0;
        }

        .progress-fill {
            background: linear-gradient(90deg, #ffb347, #ff6b4a);
            height: 100%;
            width: 0%;
            transition: width 0.3s ease;
            border-radius: 20px;
        }

        /* 网格区域 */
        .grid-wrapper {
            background: #fffaec;
            border-radius: 40px;
            padding: 14px;
            box-shadow: inset 0 0 0 2px #fff9e6, inset 0 0 0 6px #e7dbb8, 0 12px 18px rgba(0,0,0,0.15);
            flex-shrink: 1;
            overflow: visible;
        }

        .game-grid {
            display: grid;
            grid-template-columns: repeat(6, 1fr);
            gap: 10px;
            justify-items: center;
            align-items: center;
            margin: 0 auto;
        }

        /* 卡片样式 - 带颜色的水果 */
        .card {
            aspect-ratio: 1 / 1;
            width: 100%;
            max-width: 92px;
            border-radius: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 2.6rem;
            cursor: pointer;
            transition: all 0.12s linear;
            box-shadow: 0 7px 0 rgba(0,0,0,0.2);
            transform: translateY(-2px);
            background: radial-gradient(circle at 30% 25%, rgba(255,255,255,0.8), rgba(255,255,255,0.4));
            touch-action: manipulation;
        }

        /* 各种水果的不同颜色 */
        .card[data-fruit="🍎"] { background: linear-gradient(135deg, #ff4d4d, #cc0000); box-shadow: 0 7px 0 #990000; }
        .card[data-fruit="🍊"] { background: linear-gradient(135deg, #ffaa33, #ff8800); box-shadow: 0 7px 0 #cc6600; }
        .card[data-fruit="🍒"] { background: linear-gradient(135deg, #cc3399, #990066); box-shadow: 0 7px 0 #660044; }
        .card[data-fruit="🍓"] { background: linear-gradient(135deg, #ff6699, #ff3366); box-shadow: 0 7px 0 #cc0044; }
        .card[data-fruit="🍉"] { background: linear-gradient(135deg, #66cc66, #339933); box-shadow: 0 7px 0 #226622; }
        .card[data-fruit="🍑"] { background: linear-gradient(135deg, #ffcc88, #ffaa66); box-shadow: 0 7px 0 #cc8844; }
        .card[data-fruit="🍍"] { background: linear-gradient(135deg, #ffdd77, #ffcc44); box-shadow: 0 7px 0 #ccaa33; }
        .card[data-fruit="🥝"] { background: linear-gradient(135deg, #88cc44, #66aa33); box-shadow: 0 7px 0 #448822; }
        .card[data-fruit="🍌"] { background: linear-gradient(135deg, #ffee88, #ffdd66); box-shadow: 0 7px 0 #ccaa44; }
        .card[data-fruit="🍇"] { background: linear-gradient(135deg, #aa66ff, #8844cc); box-shadow: 0 7px 0 #552299; }

        .card.selected {
            box-shadow: 0 0 0 4px #ffb347, 0 0 0 8px #ffe484, 0 7px 0 rgba(0,0,0,0.2);
            transform: scale(0.97) translateY(0px);
        }

        .card.removed {
            visibility: hidden;
            pointer-events: none;
            box-shadow: none;
            transform: scale(0.8);
            background: transparent;
        }

        /* 按钮区域 */
        .action-buttons {
            margin-top: 16px;
            display: flex;
            justify-content: center;
            gap: 20px;
            flex-wrap: wrap;
            flex-shrink: 0;
        }

        button {
            background: #ffb347;
            border: none;
            font-family: inherit;
            font-weight: bold;
            font-size: 1.15rem;
            padding: 8px 26px;
            border-radius: 60px;
            color: #3d2a1a;
            cursor: pointer;
            box-shadow: 0 5px 0 #a45d2e;
            transition: 0.07s linear;
            touch-action: manipulation;
        }

        button:active {
            transform: translateY(3px);
            box-shadow: 0 2px 0 #a45d2e;
        }

        .message-area {
            margin-top: 12px;
            background: #e9dbbc;
            border-radius: 40px;
            padding: 8px 14px;
            font-size: 1rem;
            font-weight: bold;
            color: #674e2c;
            min-height: 3rem;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            flex-wrap: wrap;
            text-align: center;
            flex-shrink: 0;
        }

        footer {
            font-size: 0.68rem;
            margin-top: 10px;
            color: #b48b4b;
            text-align: center;
            flex-shrink: 0;
        }
        
        /* 庆祝动画 */
        @keyframes celebrate {
            0% { transform: scale(1); }
            50% { transform: scale(1.1); background: radial-gradient(circle, gold, #ffaa00); }
            100% { transform: scale(1); }
        }
        
        .celebrate-card {
            animation: celebrate 0.5s ease-in-out;
        }

        /* 响应式 - 完美适配希沃白板和各种屏幕比例 */
        @media (max-width: 750px) {
            .game-grid {
                gap: 8px;
            }
            .card {
                font-size: 2.2rem;
            }
            .info-panel {
                padding: 6px 16px;
            }
            .score-box, .level-box {
                font-size: 1rem;
                padding: 4px 14px;
            }
            .score-box span, .level-box span {
                font-size: 1.3rem;
            }
            button {
                font-size: 1rem;
                padding: 6px 20px;
            }
        }

        @media (max-width: 580px) {
            .game-grid {
                gap: 6px;
            }
            .card {
                font-size: 1.9rem;
            }
            .grid-wrapper {
                padding: 8px;
            }
            .game-container {
                padding: 12px 15px;
            }
        }

        @media (max-height: 700px) {
            .game-container {
                padding: 12px 18px;
            }
            .card {
                font-size: 2rem;
            }
            .action-buttons {
                margin-top: 10px;
            }
            .message-area {
                min-height: 2.6rem;
                font-size: 0.9rem;
            }
        }
    </style>
</head>
<body>
<div class="game-container">
    <div class="info-panel">
        <div class="score-box">🍍 积分 <span id="scoreValue">0</span></div>
        <div class="level-box">🍎 第 <span id="levelValue">1</span> 关</div>
    </div>

    <div class="progress-bar">
        <div class="progress-fill" id="progressFill"></div>
    </div>

    <div class="grid-wrapper">
        <div class="game-grid" id="gameGrid"></div>
    </div>

    <div class="action-buttons">
        <button id="shuffleBtn">🔄 洗牌</button>
        <button id="refreshHintBtn">✨ 提示</button>
    </div>

    <div class="message-area" id="messageArea">
        🍉 点击相同水果,直线/拐两弯连接消除~
    </div>
    <footer>⭐ 每消除一对+10分 | 清空所有水果自动进入下一关 | 🎨 每种水果都有独特颜色 | 🎵 过关有音乐和语音庆祝</footer>
</div>

<script>
    // ---------- 完全锁定屏幕滚动 (无滚动条,适配希沃白板) ----------
    (function lockScreen() {
        // 禁止触摸移动导致页面滚动
        document.body.addEventListener('touchmove', function(e) {
            e.preventDefault();
        }, { passive: false });
        // 禁止鼠标滚轮滚动
        document.body.addEventListener('wheel', function(e) {
            e.preventDefault();
        }, { passive: false });
        // 禁止键盘方向键滚动
        window.addEventListener('keydown', function(e) {
            const keys = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PageUp', 'PageDown', 'Home', 'End', ' ', 'Space'];
            if (keys.includes(e.key) || e.key === ' ') {
                e.preventDefault();
            }
        });
        // 禁止页面滚动条 (双重保险)
        document.documentElement.style.overflow = 'hidden';
        document.body.style.overflow = 'hidden';
    })();

    // ---------- 游戏配置 ----------
    const ROWS = 6;
    const COLS = 6;
    // 水果表情库 (丰富可爱,每个都有独特颜色)
    const FRUITS = ['🍎', '🍊', '🍒', '🍓', '🍉', '🍑', '🍍', '🥝', '🍌', '🍇'];
    // 每一关使用的水果种类数 (保持难度适中,6x6网格每种出现6次)
    const FRUIT_TYPES_PER_LEVEL = 6;   // 6种水果,每种出现6次 = 36格
    
    let currentLevel = 1;
    let currentScore = 0;
    let gridData = [];      // 二维数组存储水果字符,null表示已消除
    let selectedRow = null, selectedCol = null;
    
    // 音频上下文 (用于播放简单音效)
    let audioContext = null;
    
    // DOM 元素
    const gridContainer = document.getElementById('gameGrid');
    const scoreSpan = document.getElementById('scoreValue');
    const levelSpan = document.getElementById('levelValue');
    const messageDiv = document.getElementById('messageArea');
    const shuffleBtn = document.getElementById('shuffleBtn');
    const hintBtn = document.getElementById('refreshHintBtn');
    const progressFill = document.getElementById('progressFill');
    
    // 更新进度条
    function updateProgress() {
        let percent = ((currentLevel - 1) % 20) / 20 * 100;
        if (currentLevel <= 20) percent = ((currentLevel - 1) / 20) * 100;
        progressFill.style.width = `${Math.min(100, percent)}%`;
    }
    
    // 播放简单胜利音乐
    function playVictoryMusic() {
        try {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                if (audioContext.state === 'suspended') audioContext.resume();
            }
            
            const now = audioContext.currentTime;
            const notes = [523.25, 587.33, 659.25, 698.46, 783.99, 880.00, 987.77, 1046.50];
            const durations = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.3, 0.5];
            
            notes.forEach((freq, index) => {
                const oscillator = audioContext.createOscillator();
                const gainNode = audioContext.createGain();
                oscillator.connect(gainNode);
                gainNode.connect(audioContext.destination);
                oscillator.frequency.value = freq;
                oscillator.type = 'sine';
                gainNode.gain.setValueAtTime(0.3, now + index * 0.2);
                gainNode.gain.exponentialRampToValueAtTime(0.0001, now + (index * 0.2) + durations[index]);
                oscillator.start(now + index * 0.2);
                oscillator.stop(now + (index * 0.2) + durations[index]);
            });
            
            const chordOsc = audioContext.createOscillator();
            const chordGain = audioContext.createGain();
            chordOsc.connect(chordGain);
            chordGain.connect(audioContext.destination);
            chordOsc.frequency.value = 523.25;
            chordOsc.type = 'triangle';
            chordGain.gain.setValueAtTime(0.4, now + 1.6);
            chordGain.gain.exponentialRampToValueAtTime(0.0001, now + 2.2);
            chordOsc.start(now + 1.6);
            chordOsc.stop(now + 2.2);
        } catch(e) {
            console.log('音频播放失败:', e);
        }
    }
    
    // 播放庆祝音效 (点击按钮和消除时)
    function playCheerSound() {
        try {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                if (audioContext.state === 'suspended') audioContext.resume();
            }
            const now = audioContext.currentTime;
            const oscillator = audioContext.createOscillator();
            const gainNode = audioContext.createGain();
            oscillator.connect(gainNode);
            gainNode.connect(audioContext.destination);
            oscillator.frequency.value = 880;
            oscillator.type = 'sine';
            gainNode.gain.setValueAtTime(0.2, now);
            gainNode.gain.exponentialRampToValueAtTime(0.0001, now + 0.3);
            oscillator.start(now);
            oscillator.stop(now + 0.3);
        } catch(e) {
            console.log('庆祝音效播放失败:', e);
        }
    }
    
    // 语音播报函数
    function speak(text) {
        if ('speechSynthesis' in window) {
            window.speechSynthesis.cancel();
            const utterance = new SpeechSynthesisUtterance(text);
            utterance.lang = 'zh-CN';
            utterance.rate = 0.9;
            utterance.pitch = 1.2;
            utterance.volume = 1;
            const voices = window.speechSynthesis.getVoices();
            const chineseVoice = voices.find(voice => voice.lang === 'zh-CN');
            if (chineseVoice) utterance.voice = chineseVoice;
            window.speechSynthesis.speak(utterance);
        }
    }
    
    // 过关庆祝函数
    function celebrateLevelCompletion() {
        const message = `恭喜过关!当前总得分 ${currentScore} 分!`;
        playVictoryMusic();
        setTimeout(() => speak(message), 300);
        showMessage(`🎉🎉🎉 ${message} 🎉🎉🎉`, false);
        
        const cards = document.querySelectorAll('.card:not(.removed)');
        cards.forEach((card, index) => {
            setTimeout(() => {
                card.classList.add('celebrate-card');
                setTimeout(() => card.classList.remove('celebrate-card'), 500);
            }, index * 50);
        });
    }
    
    function showMessage(msg, isError = false) {
        messageDiv.innerHTML = `${isError ? '⚠️ ' : '🍬 '} ${msg}`;
        setTimeout(() => {}, 3000);
    }
    
    function updateScoreUI() {
        scoreSpan.innerText = currentScore;
    }
    
    function updateLevelUI() {
        levelSpan.innerText = currentLevel;
        updateProgress();
    }
    
    // 连连看核心算法
    function canConnect(row1, col1, row2, col2, data) {
        if (row1 === row2 && col1 === col2) return false;
        if (data[row1][col1] === null || data[row2][col2] === null) return false;
        if (data[row1][col1] !== data[row2][col2]) return false;
        
        const rows = data.length;
        const cols = data[0].length;
        
        function checkRowClear(r, cA, cB) {
            let minC = Math.min(cA, cB), maxC = Math.max(cA, cB);
            for (let i = minC + 1; i < maxC; i++) if (data[r][i] !== null) return false;
            return true;
        }
        function checkColClear(c, rA, rB) {
            let minR = Math.min(rA, rB), maxR = Math.max(rA, rB);
            for (let i = minR + 1; i < maxR; i++) if (data[i][c] !== null) return false;
            return true;
        }
        
        if (row1 === row2 && checkRowClear(row1, col1, col2)) return true;
        if (col1 === col2 && checkColClear(col1, row1, row2)) return true;
        if (data[row1][col2] === null && checkRowClear(row1, col1, col2) && checkColClear(col2, row1, row2)) return true;
        if (data[row2][col1] === null && checkColClear(col1, row1, row2) && checkRowClear(row2, col1, col2)) return true;
        
        for (let i = 0; i < rows; i++) {
            if (i !== row1 && i !== row2 && data[i][col1] === null && data[i][col2] === null &&
                checkColClear(col1, row1, i) && checkRowClear(i, col1, col2) && checkColClear(col2, i, row2)) return true;
        }
        for (let j = 0; j < cols; j++) {
            if (j !== col1 && j !== col2 && data[row1][j] === null && data[row2][j] === null &&
                checkRowClear(row1, col1, j) && checkColClear(j, row1, row2) && checkRowClear(row2, j, col2)) return true;
        }
        return false;
    }
    
    function isWin() {
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) return false;
            }
        }
        return true;
    }
    
    function hasRemainingMoves() {
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if ((i === m && j === n)) continue;
                            if (gridData[m][n] !== null && gridData[i][j] === gridData[m][n] && canConnect(i, j, m, n, gridData)) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }
    
    function shuffleBoard() {
        let fruitsList = [];
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) fruitsList.push(gridData[i][j]);
            }
        }
        for (let i = fruitsList.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [fruitsList[i], fruitsList[j]] = [fruitsList[j], fruitsList[i]];
        }
        let idx = 0;
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) gridData[i][j] = fruitsList[idx++];
            }
        }
        renderGrid();
        clearSelected();
        showMessage("♻️ 重新洗牌啦,继续挑战彩色水果吧", false);
        playCheerSound();
    }
    
    let hintTimer = null;
    function giveHint() {
        if (hintTimer) clearTimeout(hintTimer);
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                if (gridData[i][j] !== null) {
                    for (let m = 0; m < ROWS; m++) {
                        for (let n = 0; n < COLS; n++) {
                            if ((i === m && j === n)) continue;
                            if (gridData[m][n] !== null && gridData[i][j] === gridData[m][n] && canConnect(i, j, m, n, gridData)) {
                                highlightPair(i, j, m, n);
                                showMessage(`💡 试试消除 ${gridData[i][j]} 吧!`, false);
                                playCheerSound();
                                return;
                            }
                        }
                    }
                }
            }
        }
        showMessage("🤔 暂时没有可消除的水果,试试洗牌吧!", true);
    }
    
    function highlightPair(row1, col1, row2, col2) {
        const cards = document.querySelectorAll('.card');
        const idx1 = row1 * COLS + col1;
        const idx2 = row2 * COLS + col2;
        if (cards[idx1] && cards[idx2]) {
            cards[idx1].style.boxShadow = "0 0 0 4px gold, 0 0 0 8px #ffb347, 0 7px 0 rgba(0,0,0,0.2)";
            cards[idx2].style.boxShadow = "0 0 0 4px gold, 0 0 0 8px #ffb347, 0 7px 0 rgba(0,0,0,0.2)";
            hintTimer = setTimeout(() => renderGrid(), 1800);
        }
    }
    
    function eliminatePair(row1, col1, row2, col2) {
        if (!canConnect(row1, col1, row2, col2, gridData)) return false;
        gridData[row1][col1] = null;
        gridData[row2][col2] = null;
        currentScore += 10;
        updateScoreUI();
        renderGrid();
        clearSelected();
        playCheerSound();
        showMessage(`🎉 +10分!消除成功!`, false);
        
        if (isWin()) {
            celebrateLevelCompletion();
            setTimeout(() => {
                currentLevel++;
                updateLevelUI();
                initLevelGrid();
                clearSelected();
                showMessage(`🎉 进入第 ${currentLevel} 关!继续加油~ 🎉`, false);
                setTimeout(() => {
                    if (!hasRemainingMoves()) shuffleBoard();
                }, 200);
            }, 2000);
            return true;
        }
        
        if (!hasRemainingMoves()) {
            setTimeout(() => {
                if (!hasRemainingMoves()) shuffleBoard();
            }, 200);
        }
        return true;
    }
    
    function clearSelected() {
        selectedRow = null;
        selectedCol = null;
        renderGrid();
    }
    
    function renderGrid() {
        gridContainer.innerHTML = '';
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                const fruit = gridData[i][j];
                const card = document.createElement('div');
                card.className = 'card';
                if (fruit === null) {
                    card.classList.add('removed');
                    card.innerText = '✨';
                    card.style.fontSize = '2rem';
                    card.style.opacity = '0.6';
                } else {
                    card.innerText = fruit;
                    card.setAttribute('data-fruit', fruit);
                }
                if (selectedRow === i && selectedCol === j && fruit !== null) {
                    card.classList.add('selected');
                }
                card.addEventListener('click', (function(r, c) {
                    return function() { onCardClick(r, c); };
                })(i, j));
                gridContainer.appendChild(card);
            }
        }
    }
    
    function onCardClick(row, col) {
        if (gridData[row][col] === null) return;
        playCheerSound();
        
        if (selectedRow === null || selectedCol === null) {
            selectedRow = row;
            selectedCol = col;
            renderGrid();
            showMessage(`选中 ${gridData[row][col]} ,再点击另一个相同水果消除~`, false);
            return;
        }
        
        const sRow = selectedRow, sCol = selectedCol;
        if (sRow === row && sCol === col) {
            clearSelected();
            showMessage("已取消选中", false);
            return;
        }
        
        if (gridData[sRow][sCol] !== null && gridData[row][col] !== null &&
            gridData[sRow][sCol] === gridData[row][col] && canConnect(sRow, sCol, row, col, gridData)) {
            eliminatePair(sRow, sCol, row, col);
        } else {
            if (gridData[row][col] !== null) {
                if (gridData[sRow][sCol] !== gridData[row][col]) {
                    showMessage(`🍇 ${gridData[sRow][sCol]} 和 ${gridData[row][col]} 不一样,不能消除哦`, true);
                } else {
                    showMessage(`🚫 路径不通,最多拐两弯~ 再试试洗牌吧`, true);
                }
                selectedRow = row;
                selectedCol = col;
                renderGrid();
            } else {
                clearSelected();
            }
        }
    }
    
    function initLevelGrid() {
        const totalCells = ROWS * COLS;
        const typesCount = FRUIT_TYPES_PER_LEVEL;
        const eachCount = totalCells / typesCount;
        let fruitPool = [];
        for (let i = 0; i < typesCount; i++) {
            const fruitChar = FRUITS[i % FRUITS.length];
            for (let k = 0; k < eachCount; k++) fruitPool.push(fruitChar);
        }
        for (let i = fruitPool.length - 1; i > 0; i--) {
            const j = Math.floor(Math.random() * (i + 1));
            [fruitPool[i], fruitPool[j]] = [fruitPool[j], fruitPool[i]];
        }
        gridData = Array(ROWS).fill().map(() => Array(COLS).fill(null));
        let idx = 0;
        for (let i = 0; i < ROWS; i++) {
            for (let j = 0; j < COLS; j++) {
                gridData[i][j] = fruitPool[idx++];
            }
        }
        if (!hasRemainingMoves()) shuffleBoard();
    }
    
    function resetGame() {
        currentLevel = 1;
        currentScore = 0;
        updateScoreUI();
        updateLevelUI();
        initLevelGrid();
        clearSelected();
        showMessage("🍍 彩色水果连连看开始啦!每种水果颜色都不同哦~", false);
        if (!hasRemainingMoves()) shuffleBoard();
        if ('speechSynthesis' in window) window.speechSynthesis.getVoices();
    }
    
    shuffleBtn.addEventListener('click', () => { shuffleBoard(); });
    hintBtn.addEventListener('click', () => { giveHint(); });
    
    resetGame();
</script>
</body>
</html>'''
    
    # 保存到指定路径
    file_path = r'D:\test\20桌面素材\20260326水果连连看\04 锁定屏幕,彩色声音水果连连看_希沃白板适配版.html'
    
    # 确保目录存在
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    
    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        print(f'✅ 彩色水果连连看游戏已成功生成!')
        print(f'📁 文件保存位置: {file_path}')
        print('🎮 游戏特性:')
        print('  - 🔒 屏幕完全锁定,无滚动条,完美适配希沃白板')
        print('  - 🌈 每种水果都有独特的颜色:苹果红色、橙子橙色、樱桃紫红、草莓粉红、西瓜绿色等')
        print('  - 🎵 点击按钮和消除时有音效,过关时播放动听的胜利音乐')
        print('  - 🗣️ 过关时语音播报"恭喜过关!当前总得分X分"')
        print('  - 🎉 过关时有卡片庆祝动画效果')
        print('  - 6x6水果连连看,经典的直线/拐弯消除规则')
        print('  - 每消除一对水果+10分')
        print('  - 清空所有水果自动进入下一关,难度保持不变')
        print('  - 支持洗牌和提示功能,避免卡关')
        print('  - 进度条显示闯关进度')
        print('  - 响应式布局,完美支持希沃白板、平板和手机')
        return file_path
    except Exception as e:
        print(f'❌ 生成文件失败: {e}')
        return None

if __name__ == '__main__':
    # 直接运行即可生成HTML文件
    generate_fruit_link_game()

撑满屏幕,无滚动条,但是很高,矮个子估计点不到顶部图案

相关推荐
HelloReader2 小时前
Qt Quick 视觉元素、交互与自定义组件(七)
前端
We་ct2 小时前
LeetCode 153. 旋转排序数组找最小值:二分最优思路
前端·算法·leetcode·typescript·二分·数组
程序员阿峰2 小时前
前端3D·Three.js一学就会系列:第二 画线
前端·three.js
HelloReader2 小时前
Qt Quick Controls 控件库、样式与布局(八)
前端
兔司基2 小时前
Node.js/Express 实现 AI 流式输出 (SSE) 踩的坑:为什么客户端会“瞬间断开连接”?
前端
yuki_uix2 小时前
一次 CR 引发的思考:我的 rules.ts 构想,究竟属于哪种开发哲学?
前端·ai编程
dear_bi_MyOnly2 小时前
【 HTML + CSS + JavaScript 学习速通 max】
javascript·css·学习·html·学习方法
可视之道2 小时前
前端大屏适配方案:rem、vw/vh、scale 到底选哪个?
前端
小码哥_常2 小时前
别在Android ViewModel里处理异常啦,真的很坑!
前端