摘要
本篇是 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 源码
importtime# 【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_timeprint(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 源码
importtime# 模拟红绿灯🚦# 【Scratch积木】说 [红灯亮了!] 持续 (1) 秒print("🔴 红灯亮了!")# 【Scratch积木】等待 (2) 秒time.sleep(2)# 【Scratch积木】说 [黄灯亮了!] 持续 (1) 秒print("🟡 黄灯亮了!")# 【Scratch积木】等待 (1) 秒time.sleep(1)# 【Scratch积木】说 [绿灯亮了!] 持续 (1) 秒print("🟢 绿灯亮了!可以通行!")# 倒计时小演示# 【Scratch积木】重复执行 [3] 次foriinrange(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 源码
importtime# 【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_timeprint(f"\n📊 你的反应时间:{reaction:.2f}秒")# 【Scratch积木】如果 <(回答) = [target]> 那么ifanswer==target:# 【Scratch积木】如果 <[reaction] < [1]> 那么ifreaction<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积木代码
🐍 完整可运行代码
importtimeimportrandomdefrhythm_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">whileTrue:# 【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]> 那么 停止该脚本ifanswer=='q':break# 判断是否超时# 【Scratch积木】如果 <[reaction] > [time_limit]> 那么ifreaction>time_limit:print(f"⏰ 超时!反应时间{reaction:.2f}s > 限制{time_limit:.1f}s")print("❌ 本轮不得分,连击中断!")# 【Scratch积木】将 [combo] 设为 [0]combo=0# 判断是否按对# 【Scratch积木】如果 <(回答) 不 = [target_key]> 那么elifanswer!=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]> 那么ifcombo>best_combo:# 【Scratch积木】将 [best_combo] 设为 [combo]best_combo=comboprint(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 再记开始时间,反应时间永远是 0answer=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# ✅ 正确:文件开头先导入importtime start=time.time()# 正常运行❌ 易错点3:time.sleep() 的参数单位搞混
# ❌ 错误:以为参数是毫秒time.sleep(1000)# 实际暂停 1000 秒(约16分钟)!# ✅ 正确:参数是秒,1秒就写 1time.sleep(1)# 暂停 1 秒time.sleep(0.5)# 暂停 0.5 秒(500毫秒)❌ 易错点4:忘记 strip() 和 lower() 导致匹配失败
# ❌ 错误:用户输入 "W "(带空格大写),无法匹配 "w"answer=input("请输入:")ifanswer=="w":# "W " != "w",匹配失败!# ✅ 正确:strip() 去空格 + lower() 转小写answer=input("请输入:").strip().lower()ifanswer=="w":# "W " → "w",匹配成功!❌ 易错点5:while True 忘记写退出条件
# ❌ 错误:没有 break,死循环永远停不下来whileTrue:answer=input("请输入:")print(answer)# 只能按 Ctrl+C 强制停止,很不友好# ✅ 正确:加上退出条件whileTrue:answer=input("请输入:")ifanswer=="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零基础学习内容