编程启蒙|Scratch 转 Python 系列第 7 天:猜数字大挑战·升级版实战(AI 出题 + 二分查找最优解 + 完整命令行游戏)
阶段 B 游戏实战开篇之作。
还记得第 3 天我们用 if/else 做过一个最简单的猜数字吗?今天我们要把它做成一个完整、耐玩、还带最优解法的真游戏——这是"从写代码"到"做产品"的第一步。
一、本节课学习目标
- 复习并串联
input()、random、while、if/elif/else四大知识点,做一个真正可反复玩的猜数字游戏。 - 引入
while True+break的主循环设计,理解"程序菜单"的通用架构。 - 掌握二分查找思维——从"随便猜"进化到"7 次必中 1-100"的最优策略。
- 用 AI 提示词框架改造出题环节,理解"AI 当出题者 + Python 当引擎 + 玩家当求解者"的AI Agent 交互三角。
二、从第 3 天到第 7 天:一张对比图看懂"成长"
| 版本 | 第 3 天基础版 | 第 7 天升级版(今天) |
|---|---|---|
| 出题 | 固定一个数 | AI 随机出题(每局都不一样) |
| 猜测次数 | 无限次 | 限制 7 次(对应二分查找上限) |
| 反馈 | 大了 / 小了 | 大了 / 小了 / 剩余次数 |
| 解法 | 随便猜 | 教二分查找最优策略 |
| 战绩 | 无 | 列表记录 → 最佳 / 平均 / 局数全统计 |
| 结束 | 猜到就完 | 询问是否再来一局 → 主循环重开 |
| 代码量 | 10 行 | 60+ 行 |
编程本身就是这样——一个简单原型,慢慢长出功能、长出优化、长出细节,最后就成了一个真产品。
三、Scratch 积木逻辑(升级版)
核心积木流程
- 定义变量
secret(AI 秘密数字)、guess(玩家猜测)、attempts(剩余次数)、total(本局用了几次) secret= 在 1 到 100 之间随机选一个数attempts= 7- 重复执行直到
guess = secret或attempts = 0:- 询问"请猜一个 1-100 的数字"并等待
- 如果
guess > secret→ 说"猜大了" - 否则如果
guess < secret→ 说"猜小了" - 否则 → 说"🎉 猜中了"
attempts减 1,total增加 1
- 如果
attempts = 0且没猜中 → 说"游戏失败,答案是 secret"
scratch 积木代码
## 四、Python 完整可运行源码
import random
def one_round():
"""一局猜数字游戏,猜中返回本局次数,未猜中返回 None"""
secret = random.randint(1, 100) # AI 秘密出题
max_attempts = 7 # 二分查找的理论上限
total = 0 # 本局猜了几次
print("\n" + "=" * 40)
print("🎯 AI 已经想好了一个 1-100 的秘密数字")
print(f"你有 {max_attempts} 次机会,来挑战吧!")
print("=" * 40)
for attempt in range(max_attempts):
remaining = max_attempts - attempt
guess_str = input(f"\n👉 第 {attempt + 1} 次猜测(还剩 {remaining} 次):")
# 防止玩家输入错误
if not guess_str.isdigit():
print("⚠️ 请输入 1-100 的数字")
continue
guess = int(guess_str)
total += 1
if guess > secret:
print("📉 猜大了")
elif guess < secret:
print("📈 猜小了")
else:
print(f"\n🎉 恭喜!你用 {total} 次猜中了,答案就是 {secret}")
return total # 猜中返回本局用了几次
# 循环走完还没猜中
print(f"\n💔 挑战失败,正确答案是 {secret}")
return None
def main():
"""游戏主循环"""
history = [] # 👈 第 6 天列表现学现用:记录每局胜利用的次数
total_rounds = 0 # 总局数(含输的)
print("=" * 40)
print(" 🎮 猜数字大挑战 · AI 出题版")
print("=" * 40)
while True:
total_rounds += 1
result = one_round()
if result is not None:
history.append(result) # 用列表 append 记录本局
# 战绩统计(列表全家桶:len / max / min / sum)
if history:
avg = sum(history) / len(history)
print(f"\n📊 战绩:{total_rounds} 局 {len(history)} 胜 | "
f"最少 {min(history)} 次 | 最多 {max(history)} 次 | 平均 {avg:.1f} 次")
else:
print(f"\n📊 战绩:{total_rounds} 局 0 胜,别灰心,再来!")
again = input("\n是否再来一局?(y/n):")
if again.lower() != "y":
if history:
print(f"\n👋 再见!{total_rounds} 局 {len(history)} 胜,"
f"最佳成绩 {min(history)} 次猜中 🏆")
else:
print(f"\n👋 再见!下次继续加油")
break
if __name__ == "__main__":
main()
运行方式:
- 保存为
guess_number_v2.py - 命令行
python guess_number_v2.py - 按提示输入数字,每局结束选择是否继续
💡 顺便复习第 6 天列表:主循环里的
history = []+history.append(total)+min/max/sum/len(history)—— 这就是列表最经典的四大用法。第 6 天学的列表,今天真正派上了用场:记录、统计、找极值、算平均,一套下来,一个真正"有记忆"的游戏就有了。
五、AI 主题升级:让 AI 真正当"出题者"
上面的代码里,random.randint(1, 100) 只是模拟 AI 出题。真实场景可以对接大模型 API,让 AI 每局都用一段自然语言介绍这个数字:
# 代码演示:真正对接 AI 大模型
def ai_generate_riddle():
prompt = "请随机想一个 1-100 的整数,并给一个不透露答案的谜面提示"
response = call_llm(prompt) # 调用大模型
return response["secret"], response["hint"]
secret, hint = ai_generate_riddle()
print(f"🤖 AI 出题提示:{hint}")
# 例如:"这个数是两位数,是 3 的倍数,个位比十位大"
这就是 AI Agent 应用的标准架构:
- AI 负责:生成内容、给出提示、动态调整难度
- Python 负责:控制流程、判断输入、维护状态
- 玩家负责:交互、决策、反馈
孩子今天写的这 50 行代码,就是所有 AI 智能应用的骨架。
六、思维进阶:二分查找 —— 7 次必中 1-100 的秘密
为什么 max_attempts = 7?
因为 2⁷ = 128 > 100,用二分查找猜 1-100 的数字,最多 7 次一定能猜中:
| 次数 | 猜测策略 | 举例(假设答案是 73) |
|---|---|---|
| 第 1 次 | 猜 50(中间值) | 猜小了 → 答案在 51-100 |
| 第 2 次 | 猜 75 | 猜大了 → 答案在 51-74 |
| 第 3 次 | 猜 62 | 猜小了 → 答案在 63-74 |
| 第 4 次 | 猜 68 | 猜小了 → 答案在 69-74 |
| 第 5 次 | 猜 71 | 猜小了 → 答案在 72-74 |
| 第 6 次 | 猜 73 | ✅ 猜中! |
核心口诀:每次都猜"当前可能范围的中间值"。
scratch积木代码
Python 实现二分查找猜数字(把玩家换成 AI 求解者):
def ai_solver(secret):
"""AI 用二分查找猜数字"""
low, high = 1, 100
attempts = 0
while low <= high:
guess = (low + high) // 2 # 中间值(整除)
attempts += 1
print(f"AI 第 {attempts} 次猜:{guess}")
if guess == secret:
print(f"✅ AI 用 {attempts} 次猜中!")
return
elif guess < secret:
low = guess + 1 # 答案在右半区
else:
high = guess - 1 # 答案在左半区
这个思想是所有算法课的第一课——孩子在小学阶段就能理解"折半查找",比大学生入门还早。
七、Scratch 积木 ↔ Python 代码对照表
| Scratch 积木 | Python 代码 | 作用 |
|---|---|---|
| 在 1 到 100 之间随机选一个数 | random.randint(1, 100) |
出题 |
| 询问 () 并等待 | input(...) |
获取输入 |
| 回答 | 变量接收 input() 返回值 |
存输入 |
| 重复执行直到 () | while True: ... break 或 for 循环 |
主循环 |
| 如果 A > B | if guess > secret: |
猜大判断 |
| 否则如果 A < B | elif guess < secret: |
猜小判断 |
| 将 attempts 增加 1 | attempts += 1 |
计数 |
| 建立一个空列表 | history = [] |
存战绩 |
| 将 () 加入列表 | history.append(total) |
记录本局 |
| 列表长度 / 最大 / 最小 / 求和 | len / max / min / sum(history) |
战绩统计 |
关键差异:
- Scratch 的"回答"变量自动接收输入;Python 需要用变量赋值
guess = input(...) - Python
input()拿到的永远是字符串,比大小必须先int()转数字 - Python 主循环用
while True + break,比 Scratch 的"重复直到"更灵活
八、本节课高频易错点总结
1. 忘了转数字类型
input() 返回字符串,"50" > 30 会直接报错——必须 int(input(...))。
2. random.randint(1, 100) 是闭区间
Python 里 randint(1, 100) 包含 100,但列表切片 [1:100] 不包含 100——Python 的"闭区间/开区间"混用是新手大坑。
3. while True 忘写 break
无限循环忘写退出条件 → 程序卡死,只能 Ctrl+C 强制关闭。
4. 输入非法字符崩溃
用户输错(比如输入"abc")时 int("abc") 会报错——加一句 if not guess_str.isdigit(): continue 就能兜住。
九、往期历史笔记
- 编程启蒙|Scratch 转 Python 系列第 1 天:变量、数字运算积木双向对照(AI 基础数值计算实战)
- 编程启蒙|Scratch 转 Python 系列第 2 天:分支判断 if 积木双向对照(AI 指令条件过滤实战)
- 编程启蒙|Scratch 转 Python 系列第 3 天:循环重复积木双向对照(AI 批量循环处理,已收录 AI Agent 技术社区)
- 编程启蒙|Scratch 转 Python 系列第 4 天:字符串文本积木双向对照(AI 提示词拼接、文本清洗实战)
- 编程启蒙|Scratch 转 Python 系列第 5 天:自定义积木 / 函数双向对照(AI 工具封装、重复指令简化实战)
6. 编程启蒙|Scratch 转 Python 系列第 6 天:列表、数组积木双向对照(AI 底层语法 / AI 批量数据处理实战)
十一、下一章预告
Scratch 转 Python 第 8 天:节奏敲击机实战——AI 生成节奏谱,Python 自动播放(音频事件驱动)
十二、原创声明
本文为**「梅雅达编程笔记」**原创启蒙教程,禁止私自搬运、二次转载,转发请标注来源。
想要系统学完整套 Scratch 转 Python 课程,欢迎订阅下方专栏持续追更。
更多推荐


所有评论(0)