摘要

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


1. 本节课学习目标

  1. ⏱️ 掌握 time.time() 获取当前时间戳,理解如何用两个时间点相减计算经过的时间
  2. 😴 掌握 time.sleep() 实现程序延时,理解它与 Scratch"等待()秒"积木的对应关系
  3. 🔄 能够综合运用 while True 循环(Day 3)、函数封装(Day 5)、时间计算,完成限时输入的反应时间测量
  4. 🤖 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 秒
⚠️ 核心易错说明
  1. 时间戳很大是正常的time.time() 返回的是从 1970 年 1 月 1 日到现在的秒数,数字可能像 1700000000.5,不要害怕!
  2. Scratch 计时器 vs Python time.time():Scratch 的计时器从绿旗点击开始算,Python 从 1970 年开始算,但相减求差值的思路完全一样。
  3. 保留小数:用 :.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秒)
  🎉 时间到!
⚠️ 核心易错说明
  1. 秒数可以是小数time.sleep(0.5) 表示暂停 0.5 秒,不一定是整数。
  2. 完全对应time.sleep(秒数) 和 Scratch 的"等待()秒"积木是一对一的映射关系,是最容易理解的对照。
  3. 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 秒
🚀 闪电手!反应超快!
⚠️ 核心易错说明
  1. input() 会阻塞程序input() 和 Scratch 的"询问()并等待"一样,程序会停在这里等用户输入,这就是"事件驱动"的体现。
  2. 计时要在 input 前后start_time 必须在 input() 之前记录,end_time 必须在 input() 之后记录,顺序不能错!
  3. strip() 和 lower() 很重要strip() 去掉首尾空格,lower() 转小写,这样用户输入 "G " 或 “g” 都能正确匹配。
  4. 串联 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. 往期历史笔记

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

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

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

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

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

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

  7. 编程启蒙|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零基础学习内容

更多推荐