欢迎光临
我们一直在努力

编程启蒙|Scratch 转 Python 系列第8天:节奏敲击机游戏实战(AI节奏谱生成实战)

摘要

本篇是 Scratch 转 Python 系列第 8 天,核心学习 time 模块的计时(time.time())和延时(time.sleep())功能。我们将 Scratch 的"计时器"和"等待秒数"积木与 Python 的 time 模块进行双向对照,串联 Day 3 的 while True 循环和 Day 5 的函数知识,最终完成一个"节奏敲击机"游戏实战——AI 生成节奏谱,玩家在限定时间内按下对应按键,反应越快得分越高,节奏越来越快!🎮


1. 本节课学习目标

  • ⏱️ 掌握 time.time() 获取当前时间戳,理解如何用两个时间点相减计算经过的时间
  • 😴 掌握 time.sleep() 实现程序延时,理解它与 Scratch"等待()秒"积木的对应关系
  • 🔄 能够综合运用 while True 循环(Day 3)、函数封装(Day 5)、时间计算,完成限时输入的反应时间测量
  • 🤖 AI 应用场景:了解如何用 random 模拟 AI 编曲生成节奏谱,并通过scratch代码学习如何对接真正的 AI 大模型生成游戏节奏

  • 2. 专业名词通俗释义

    名词通俗解释生活类比
    time 模块 Python 自带的"时间工具箱",里面有很多跟时间有关的函数 就像你手机上的"时钟"App,里面有秒表、闹钟、世界时钟
    time.time() 返回从 1970 年 1 月 1 日到现在经过了多少秒 就像秒表上的数字,按下时记录"当前是第几秒"
    时间戳 time.time() 返回的那个大数字(如 1700000000.5) 就像快递单号——一个唯一的编号,标记某个特定时刻
    time.sleep() 让程序暂停指定的秒数,然后再继续执行 就像 Scratch 里的"等待 1 秒"积木,也像你妈喊你"等5分钟再吃蛋糕"
    毫秒 1 秒 = 1000 毫秒,是比秒更小的时间单位 就像 1 元 = 100 分,毫秒是时间的"零钱"
    事件驱动 程序的执行流程由"事件"触发(比如用户按下键盘) 就像门铃——你不按,门铃不响;你一按,它就响。程序也是等用户"按门铃"才行动
    主循环 while True 让程序不断重复运行,等待用户操作 就像旋转木马——一圈又一圈地转,直到你说"停"才下来
    反应时间 从看到提示到做出反应所花费的时间 就像赛跑时从听到枪响到迈出第一步的时间

    3. 分模块双向对照知识点

    💡 知识串联:本模块用到的 while True 循环来自 Day 3,函数封装 def 来自 Day 5。 今天我们在它们的基础上加入"时间"这个新维度!


    模块1:计时基础(time.time() 获取当前时间戳)

    🔷 Scratch 积木逻辑

    在 Scratch 中,我们用"计时器"积木来获取时间:

    • 计时器积木:返回从绿旗点击后经过的秒数 在这里插入图片描述

    • 重置计时器积木:将计时器归零 在这里插入图片描述

    典型用法:记录一个起始时间 → 执行某些操作 → 再读取一次计时器 → 两次相减 = 经过的秒数。 在这里插入图片描述

    🐍 Python 源码

    import time

    # 【Scratch积木】点击绿旗时(程序开始)
    print("👉 程序开始!")

    # 【Scratch积木】将 [start_time] 设为 (计时器)
    start_time = time.time()
    print(f"📌 开始时间戳:{start_time:.2f}")

    # 【Scratch积木】等待 (1) 秒
    print("⏳ 等待1秒中…")
    time.sleep(1)

    # 【Scratch积木】将 [end_time] 设为 (计时器)
    end_time = time.time()
    print(f"📌 结束时间戳:{end_time:.2f}")

    # 【Scratch积木】将 [elapsed] 设为 ([end_time] – [start_time])
    elapsed = end_time start_time
    print(f"\\n✅ 经过的时间 = {end_time:.2f}{start_time:.2f} = {elapsed:.2f} 秒")

    📺 运行结果

    👉 程序开始!
    📌 开始时间戳:1700000000.00
    ⏳ 等待1秒中…
    📌 结束时间戳:1700000001.00

    ✅ 经过的时间 = 1700000001.00 – 1700000000.00 = 1.00 秒

    ⚠️ 核心易错说明
  • 时间戳很大是正常的:time.time() 返回的是从 1970 年 1 月 1 日到现在的秒数,数字可能像 1700000000.5,不要害怕!
  • Scratch 计时器 vs Python time.time():Scratch 的计时器从绿旗点击开始算,Python 从 1970 年开始算,但相减求差值的思路完全一样。
  • 保留小数:用 :.2f 可以只显示两位小数,否则数字会很长很难读。

  • 模块2:延时控制(time.sleep() 暂停程序)

    🔷 Scratch 积木逻辑

    Scratch 中的"等待()秒"积木,让程序暂停指定时间:

    • 等待 (1) 秒:程序暂停 1 秒后继续执行下面的积木 在这里插入图片描述 在这里插入图片描述
    🐍 Python 源码

    import time

    # 模拟红绿灯🚦

    # 【Scratch积木】说 [红灯亮了!] 持续 (1) 秒
    print("🔴 红灯亮了!")
    # 【Scratch积木】等待 (2) 秒
    time.sleep(2)

    # 【Scratch积木】说 [黄灯亮了!] 持续 (1) 秒
    print("🟡 黄灯亮了!")
    # 【Scratch积木】等待 (1) 秒
    time.sleep(1)

    # 【Scratch积木】说 [绿灯亮了!] 持续 (1) 秒
    print("🟢 绿灯亮了!可以通行!")

    # 倒计时小演示
    # 【Scratch积木】重复执行 [3] 次
    for i in range(3, 0, 1):
    # 【Scratch积木】说 (连接 [倒计时:] 和 (i))
    print(f" ⏰ {i}…")
    # 【Scratch积木】等待 (1) 秒
    time.sleep(1)
    print(" 🎉 时间到!")

    📺 运行结果

    🔴 红灯亮了!
    (等待2秒)
    🟡 黄灯亮了!
    (等待1秒)
    🟢 绿灯亮了!可以通行!

    再来一个倒计时小演示:
    ⏰ 3…
    (等待1秒)
    ⏰ 2…
    (等待1秒)
    ⏰ 1…
    (等待1秒)
    🎉 时间到!

    ⚠️ 核心易错说明
  • 秒数可以是小数:time.sleep(0.5) 表示暂停 0.5 秒,不一定是整数。
  • 完全对应:time.sleep(秒数) 和 Scratch 的"等待()秒"积木是一对一的映射关系,是最容易理解的对照。
  • sleep 期间程序什么也不做:就像 Scratch 等待时角色也不会动一样,Python 在 sleep 期间也不会执行任何代码。

  • 模块3:限时输入(计算反应时间)

    🔷 Scratch 积木逻辑

    在 Scratch 中实现"限时输入"需要组合多个积木:

    • 询问()并等待:等待用户输入回答 在这里插入图片描述

    • 计时器:同时记录经过的时间 在这里插入图片描述

    • 如果 <计时器 > 3> 那么:判断是否超时 在这里插入图片描述

    🐍 Python 源码

    import time

    # 【Scratch积木】等待 (2) 秒
    print("3秒后开始…")
    time.sleep(1)
    print("2…")
    time.sleep(1)
    print("1…")
    time.sleep(1)

    # 【Scratch积木】将 [target] 设为 [g]
    target = "g"
    # 【Scratch积木】说 (连接 [请快速输入:] 和 [target])
    print(f"\\n👉 请快速输入字母:{target}")

    # 【Scratch积木】将 [start_time] 设为 (计时器)
    start_time = time.time()
    # 【Scratch积木】询问 (请输入) 并等待
    answer = input("请输入:").strip().lower()
    # 【Scratch积木】将 [end_time] 设为 (计时器)
    end_time = time.time()

    # 【Scratch积木】将 [reaction] 设为 ([end_time] – [start_time])
    reaction = end_time start_time

    print(f"\\n📊 你的反应时间:{reaction:.2f} 秒")

    # 【Scratch积木】如果 <(回答) = [target]> 那么
    if answer == target:
    # 【Scratch积木】如果 <[reaction] < [1]> 那么
    if reaction < 1.0:
    print("🚀 闪电手!反应超快!")
    # 【Scratch积木】否则
    else:
    print("👍 不错!继续练习会更快!")
    # 【Scratch积木】否则
    else:
    print(f"😅 输入错了,应该是 '{target}'")

    📺 运行结果

    3秒后开始…
    2…
    1…

    👉 请快速输入字母:g
    请输入:g

    📊 你的反应时间:0.45 秒
    🚀 闪电手!反应超快!

    ⚠️ 核心易错说明
  • input() 会阻塞程序:input() 和 Scratch 的"询问()并等待"一样,程序会停在这里等用户输入,这就是"事件驱动"的体现。
  • 计时要在 input 前后:start_time 必须在 input() 之前记录,end_time 必须在 input() 之后记录,顺序不能错!
  • strip() 和 lower() 很重要:strip() 去掉首尾空格,lower() 转小写,这样用户输入 "G " 或 “g” 都能正确匹配。
  • 串联 Day 3:这里用 if/else 判断和嵌套条件,跟 Day 3 学的条件判断完全一致!

  • 4. 综合实战项目:节奏敲击机完整游戏

    🎯 把模块 1-3 的知识全部串起来,加上 Day 3 的 while True 循环和 Day 5 的函数封装,做一个完整的游戏!

    🎮 游戏设计

    要素说明
    按键 W / A / S / D 四个键
    AI 编曲 用 random.choice() 随机生成按键(模拟 AI 生成节奏谱)
    限时 第 1 轮 3.0 秒,之后每轮减少 0.2 秒,最低 1.0 秒
    计分 基础分 10 + 速度奖励(剩余时间 × 10)+ 连击奖励(连击数 × 2)
    连击 连续答对累积,答错或超时清零
    退出 输入 q 随时退出

    scratch积木代码 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

    🐍 完整可运行代码

    import time
    import random

    def rhythm_tap_machine():
    """🎵 节奏敲击机完整游戏 🎵"""

    print("=" * 50)
    print(" 🎵 节奏敲击机 Rhythm Tap Machine 🎵")
    print("=" * 50)
    print("📖 游戏规则:")
    print(" · 屏幕会显示一个字母(W/A/S/D)")
    print(" · 你需要尽快输入对应的字母")
    print(" · 反应越快,得分越高!")
    print(" · 随着轮次增加,时间会越来越短!")
    print(" · 输入 'q' 可以随时退出")
    print("=" * 50)

    # 【Scratch积木】将 [score] 设为 [0]
    score = 0
    # 【Scratch积木】将 [round_num] 设为 [0]
    round_num = 0
    # 【Scratch积木】将 [combo] 设为 [0]
    combo = 0
    # 【Scratch积木】将 [best_combo] 设为 [0]
    best_combo = 0

    # 可选按键列表
    keys = ['w', 'a', 's', 'd']

    # 准备阶段
    input("\\n按回车键开始游戏…")
    print("\\n🎮 游戏开始!\\n")

    # 【Scratch积木】重复执行直到 <回答 = "q">
    while True:
    # 【Scratch积木】将 [round_num] 增加 (1)
    round_num += 1

    # AI生成节奏谱(用random模拟AI编曲)
    # 【Scratch积木】将 [target_key] 设为 (在 [keys] 中取随机一个)
    target_key = random.choice(keys)

    # 时间限制随轮次减少(节奏越来越快)
    # 【Scratch积木】将 [time_limit] 设为 ([3.0] – (([round_num] – [1]) * [0.2]))
    time_limit = max(1.0, 3.0 (round_num 1) * 0.2)

    # 【Scratch积木】说 (连接 [第] 和 ([round_num]) 和 [轮])
    print(f"━━━ 第 {round_num} 轮 ━━━")
    print(f"⏱️ 时间限制:{time_limit:.1f} 秒")
    print(f"👉 请按:【 {target_key.upper()} 】")

    # 记录开始时间
    # 【Scratch积木】将 [start_time] 设为 (计时器)
    start_time = time.time()

    # 【Scratch积木】询问 (请输入) 并等待
    answer = input(">>> ").strip().lower()

    # 记录结束时间
    # 【Scratch积木】将 [end_time] 设为 (计时器)
    end_time = time.time()

    # 计算反应时间
    # 【Scratch积木】将 [reaction] 设为 ([end_time] – [start_time])
    reaction = end_time start_time

    # 退出游戏
    # 【Scratch积木】如果 <(回答) = [q]> 那么 停止该脚本
    if answer == 'q':
    break

    # 判断是否超时
    # 【Scratch积木】如果 <[reaction] > [time_limit]> 那么
    if reaction > time_limit:
    print(f"⏰ 超时!反应时间 {reaction:.2f}s > 限制 {time_limit:.1f}s")
    print("❌ 本轮不得分,连击中断!")
    # 【Scratch积木】将 [combo] 设为 [0]
    combo = 0

    # 判断是否按对
    # 【Scratch积木】如果 <(回答) 不 = [target_key]> 那么
    elif answer != target_key:
    print(f"❌ 按错了!应该是 {target_key.upper()}")
    print("❌ 本轮不得分,连击中断!")
    # 【Scratch积木】将 [combo] 设为 [0]
    combo = 0

    # 答对且未超时
    # 【Scratch积木】否则
    else:
    # 计算得分:越快得分越高
    # 【Scratch积木】将 [speed_bonus] 设为 (取整 ([time_limit] – [reaction]) * [10])
    speed_bonus = int((time_limit reaction) * 10)
    # 基础分10分
    base_score = 10
    # 【Scratch积木】将 [combo] 增加 (1)
    combo += 1
    # 连击奖励:每连击+2分
    # 【Scratch积木】将 [combo_bonus] 设为 ([combo] * [2])
    combo_bonus = combo * 2
    # 本轮总分
    # 【Scratch积木】将 [total] 设为 ([base_score] + [speed_bonus] + [combo_bonus])
    total = base_score + speed_bonus + combo_bonus
    # 【Scratch积木】将 [score] 增加 [total]
    score += total

    # 更新最高连击
    # 【Scratch积木】如果 <[combo] > [best_combo]> 那么
    if combo > best_combo:
    # 【Scratch积木】将 [best_combo] 设为 [combo]
    best_combo = combo

    print(f"✅ 正确!反应时间 {reaction:.2f}s")
    print(f"🎯 得分:+{total}(基础{base_score} + 速度{speed_bonus} + 连击{combo_bonus})")
    print(f"🔥 连击:{combo} | 🏆 总分:{score}")

    # 短暂停顿
    # 【Scratch积木】等待 (0.5) 秒
    time.sleep(0.5)
    print()

    # 游戏结束统计
    print("=" * 50)
    print("🎮 游戏结束!")
    print(f"📊 完成轮数:{round_num 1}")
    print(f"🏆 总得分:{score}")
    print(f"🔥 最高连击:{best_combo}")
    print("=" * 50)

    # 启动游戏
    rhythm_tap_machine()

    🧩 游戏代码拆解

    代码区块对应知识点串联来源
    while True 主循环 无限循环 + break 退出 Day 3 循环
    def rhythm_tap_machine() 函数封装游戏逻辑 Day 5 函数
    time.time() 计时 获取时间戳,计算反应时间 Day 8 新知识
    time.sleep(0.5) 延时 轮次间短暂停顿 Day 8 新知识
    random.choice(keys) AI 模拟生成节奏 Day 8 AI 实战
    if/elif/else 条件判断超时/按错/按对 Day 3 条件判断
    input() 事件驱动,等待用户输入 Day 1 输入输出

    5. 高频易错点总结

    ❌ 易错点1:计时顺序搞反

    # ❌ 错误:先 input 再记开始时间,反应时间永远是 0
    answer = input("请输入:")
    start_time = time.time() # 错!
    end_time = time.time()
    reaction = end_time start_time # 永远约等于 0

    # ✅ 正确:先记开始时间,再 input,最后记结束时间
    start_time = time.time()
    answer = input("请输入:")
    end_time = time.time()
    reaction = end_time start_time # 这才是真实反应时间

    ❌ 易错点2:忘记 import time

    # ❌ 错误:直接用 time.time() 但没有导入
    start = time.time() # 报错:NameError: name 'time' is not defined

    # ✅ 正确:文件开头先导入
    import time
    start = time.time() # 正常运行

    ❌ 易错点3:time.sleep() 的参数单位搞混

    # ❌ 错误:以为参数是毫秒
    time.sleep(1000) # 实际暂停 1000 秒(约16分钟)!

    # ✅ 正确:参数是秒,1秒就写 1
    time.sleep(1) # 暂停 1 秒
    time.sleep(0.5) # 暂停 0.5 秒(500毫秒)

    ❌ 易错点4:忘记 strip() 和 lower() 导致匹配失败

    # ❌ 错误:用户输入 "W "(带空格大写),无法匹配 "w"
    answer = input("请输入:")
    if answer == "w": # "W " != "w",匹配失败!

    # ✅ 正确:strip() 去空格 + lower() 转小写
    answer = input("请输入:").strip().lower()
    if answer == "w": # "W " → "w",匹配成功!

    ❌ 易错点5:while True 忘记写退出条件

    # ❌ 错误:没有 break,死循环永远停不下来
    while True:
    answer = input("请输入:")
    print(answer)
    # 只能按 Ctrl+C 强制停止,很不友好

    # ✅ 正确:加上退出条件
    while True:
    answer = input("请输入:")
    if answer == "q":
    break # 输入 q 就退出
    print(answer)



    6. 💡 学习提示

    💡 学习提示 为鼓励大家动手练习、吃透编程逻辑,本篇不提供Scratch成品源码,请对照截图亲手搭建积木完成复刻! 配套Python代码可直接复制运行学习。


    7. 往期历史笔记

  • 编程启蒙|Scratch 转 Python 系列第 1 天:变量、数字运算积木双向对照(AI 基础数值计算实战)

  • 编程启蒙|Scratch 转 Python 系列第 2 天:分支判断 if 积木双向对照(AI 指令条件过滤实战)

  • 编程启蒙|Scratch 转 Python 系列第 3 天:循环重复积木双向对照(AI 批量循环处理,已收录 AI Agent 技术社区)

  • 编程启蒙|Scratch 转 Python 系列第 4 天:字符串文本积木双向对照(AI 提示词拼接、文本清洗实战)

  • 编程启蒙|Scratch 转 Python 系列第 5 天:自定义积木 / 函数双向对照(AI 工具封装、重复指令简化实战)

  • 编程启蒙|Scratch 转 Python 系列第 6 天:列表、数组积木双向对照(AI 底层语法 / AI 批量数据处理实战)

  • 编程启蒙|Scratch 转 Python 系列第 7 天:猜数字大挑战·升级版实战(AI 出题 + 二分查找最优解 + 完整命令行游戏)

  • 📌 知识串联提醒:

    • 本篇的 while True 主循环来自 Day 3 的循环结构,游戏中用 break 退出
    • 本篇的 def rhythm_tap_machine() 函数封装来自 Day 5 的函数知识,把整个游戏逻辑打包成一个函数
    • 建议如果对循环或函数还不熟练的同学,先回顾 Day 3 和 Day 5 再来看本篇!

    9. 下一章预告

    📅 Day 9:字典/哈希表积木双向对照,AI大模型参数配置表实战

    明天我们将学习 Python 中非常重要的数据结构——字典(dict)!

    • 🔑 字典就像"标签收纳盒",用键(key)找值(value)
    • 🔄 对照 Scratch 中的列表和变量组合使用
    • 🤖 AI 实战:用字典管理 AI 大模型的参数配置表(模型名称、温度、最大token数等)
    • 🎮 动手做一个"AI 模型参数调试器"

    敬请期待!🎉


    10. 原创声明

    本文为 梅雅达编程笔记 原创内容,系列课程持续更新中。

    📢 禁止搬运:本文所有文字、代码、图片均为原创,未经授权禁止转载、复制、摘编或以其他方式使用。

    📧 如需授权,请联系作者。

    © 梅雅达编程笔记 · Scratch 转 Python 系列 · Day 8


    每节课都配套课后练习题与完整源码。代码报错、看不懂知识点,可在评论区粘贴问题,逐一解答! 欢迎关注梅雅达编程笔记,持续分享Python零基础学习内容

    赞(0)
    未经允许不得转载:171主机测评 » 编程启蒙|Scratch 转 Python 系列第8天:节奏敲击机游戏实战(AI节奏谱生成实战)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址