第2章 2.5 综合实战:猜数字游戏 + 九九乘法表

🎯 开场 3 分钟:为什么要学这个?

上一章我们学会了 for 循环和 range(),可以用代码重复做事了——比如让计算机帮你念 100 遍 "我爱你"。

但你有没有想过:光会重复还不够,我们还得会「见机行事」

举个例子,你玩猜数字游戏时,计算机心里想一个 1-100 的数,你猜一次,它只会说 "太大了"、"太小了" 或 "恭喜你"。这个「根据不同情况说不同话」的能力,if 判断已经教过你了。

但如果我想让计算机自己出一个随机数呢? 自己设计一个「作弊版」猜数字游戏,让它每次都能赢你呢?

再比如学九九乘法表——小时候我们抄过 1x1=1, 1x2=2...,现在用 Python 怎么让它自动打印出来?

这一章,我们把 for 循环、range()if 判断 三个技能组合起来,做两个经典练手项目。学完你就能写第一个「有点智能」的程序了。


🧱 基础 25 分钟:核心概念

1. 随机数:计算机的 "摇色子"

是什么:随机数就是计算机从一堆数里随机挑一个出来。

生活类比:就像你摇骰子,摇到几就是几,计算机也可以「摇」出一个数。

为什么用:做游戏需要随机敌人位置、随机题目、随机奖励……没有随机数,游戏就固定死了。

怎么用

import random

# 从 1 到 100 里随机挑一个数(像摇骰子)
number = random.randint(1, 100)
print(number)  # 每次运行结果都不一样

解释:第 1 行告诉 Python "我要用随机数工具",第 2 行的 randint(1, 100) 就是从 1-100 里随机选一个(两端都包含)。


2. while 循环:不知道要循环几次时用

是什么:一个「满足条件就一直跑」的循环。

和 for 的区别

  • for:你知道要跑几次,比如打印 5 遍
  • while:你不知道要跑几次,跑到某个条件满足为止

生活类比
- for = 广播体操,做完 8 节就结束(固定次数)
- while = 等公交车,车来了才停止等待(条件驱动)

怎么用

count = 0
while count < 3:
print("还在等公交车...")
count += 1  # 每次等一分钟
print("车来了,上车!")

解释while count < 3 的意思是「只要 count 还小于 3,就一直跑循环体」。当 count 变成 3 时,条件不满足,退出循环。


3. break 和 continue:循环的 "紧急开关"

break = 提前下班:满足某个条件时,立刻跳出整个循环

continue = 请假早退:满足某个条件时,跳过本次循环,直接进入下一次

# break 示例:找到第一个偶数就停止
for i in range(1, 10):
if i % 2 == 0:  # 如果是偶数
    print(f"找到偶数 {i},不找了!")
    break
print(f"{i} 不是偶数,继续...")
# continue 示例:跳过所有奇数
for i in range(1, 6):
if i % 2 == 1:  # 如果是奇数
    continue  # 跳过本次,直接下一个
print(f"{i} 是偶数,打印它")

输出

2 是偶数,打印它
4 是偶数,打印它

4. 嵌套循环:循环里的循环

是什么:在一个循环里再放一个循环。

生活类比:想象你有 3 个班级,每个班有 5 个学生。你要一个个点名——先点完班 1 的 5 个人,再点班 2 的 5 个人……这就是嵌套循环。

怎么用

for i in range(1, 4):      # 外层:3 个班级
for j in range(1, 6):  # 内层:每个班 5 个人
    print(f"班级 {i} 的第 {j} 个学生")

配图1 - 配图1

关键点:外层循环跑 1 次,内层循环要跑完所有次数。所以一共会执行 3 × 5 = 15 次。


🔥 实战 35 分钟:3 个递进的小项目

项目 1(5 分钟):猜数字游戏 - 基础版

场景:计算器想一个 1-100 的随机数,你来猜,它告诉你「太大」或「太小」,看几次能猜对。

import random

# 计算机选一个神秘数字
secret = random.randint(1, 100)
print("我想好了一个 1-100 的数字,你来猜!")

guess = 0           # 初始化猜的次数
while guess != secret:
user_input = input("请输入你的猜测:")
guess = int(user_input)  # 转成整数

if guess > secret:
    print("太大了,再小一点!")
elif guess < secret:
    print("太小了,再大一点!")
else:
    print(f"恭喜你!猜对了!一共猜了 {guess} 次")

预期输出

我想好了一个 1-100 的数字,你来猜!
请输入你的猜测:50
太小了,再大一点!
请输入你的猜测:75
太大了,再小一点!
请输入你的猜测:63
恭喜你!猜对了!一共猜了 63 次

一句话解释:用 while True 不断让用户输入,直到猜对为止,每次根据结果给出提示。


项目 2(15 分钟):九九乘法表

场景:用嵌套循环打印九九乘法表,像小时候作业本上那样。

for i in range(1, 10):        # 外层:被乘数从 1 到 9
for j in range(1, i + 1): # 内层:乘数从 1 到 当前行数
    result = i * j
    print(f"{i} × {j} = {result}", end="\t")
print()  # 换行

预期输出

1 × 1 = 1   
2 × 1 = 2   2 × 2 = 4   
3 × 1 = 3   3 × 2 = 6   3 × 3 = 9   
4 × 1 = 4   4 × 2 = 8   4 × 3 = 12  4 × 4 = 16  
5 × 1 = 5   5 × 2 = 10  5 × 3 = 15  5 × 4 = 20  5 × 5 = 25  
6 × 1 = 6   6 × 2 = 12  6 × 3 = 18  6 × 4 = 24  6 × 5 = 30  6 × 6 = 36  
7 × 1 = 7   7 × 2 = 14  7 × 3 = 21  7 × 4 = 28  7 × 5 = 35  7 × 6 = 42  7 × 7 = 49  
8 × 1 = 8   8 × 2 = 16  8 × 3 = 24  8 × 4 = 32  8 × 5 = 40  8 × 6 = 48  8 × 7 = 56  8 × 8 = 64  
9 × 1 = 9   9 × 2 = 18  9 × 3 = 27  9 × 4 = 36  9 × 5 = 45  9 × 6 = 54  9 × 7 = 63  9 × 8 = 72  9 × 9 = 81  

一句话解释end="\t" 让所有乘积打印在同一行,用 print() 空行来换下一天的行。

配图2 - 配图2


项目 3(15 分钟):带计分功能的猜数字游戏

场景:在基础版上加一个计分系统——猜的次数越少,分数越高。还加个「作弊模式」,显示正确答案。

import random

def guess_number_game():
secret = random.randint(1, 100)
attempts = 0
max_attempts = 10

print("=" * 40)
print("🎮 猜数字游戏 - 挑战模式")
print("=" * 40)
print(f"我有了一个 1-100 的神秘数字,你有 {max_attempts} 次机会!")

# 先问要不要看答案(作弊模式)
cheat = input("要不要我告诉你答案?(y/n):")
if cheat.lower() == 'y':
    print(f"🤫 答案是:{secret}(别说出去!)")

while attempts < max_attempts:
    remaining = max_attempts - attempts
    print(f"\n还剩 {remaining} 次机会")

    guess_str = input("请输入你的猜测:")

    # 防崩溃:输入不是数字时
    if not guess_str.isdigit():
        print("⚠️ 请输入一个有效的数字!")
        continue

    guess = int(guess_str)
    attempts += 1

    if guess > secret:
        print("📉 太大了!")
    elif guess < secret:
        print("📈太小了!")
    else:
        # 猜对了!算分数
        score = (max_attempts - attempts + 1) * 10
        print(f"🎉 恭喜你猜对了!")
        print(f"📊 你用了 {attempts} 次机会,得分:{score} 分")
        return

# 10 次都没猜对
print(f"\n😢 游戏结束!你用了太多次数。")
print(f"正确答案其实是:{secret}")

# 运行游戏
guess_number_game()

预期输出

========================================
🎮 猜数字游戏 - 挑战模式
========================================
我有了一个 1-100 的神秘数字,你有 10 次机会!
要不要我告诉你答案?(y/n):n

还剩 10 次机会
请输入你的猜测:50
📈太小了!

还剩 9 次机会
请输入你的猜测:75
📉 太大了!
...
🎉 恭喜你猜对了!
📊 你用了 7 次机会,得分:40 分

一句话解释is_valid_digit() 检查输入是否是有效数字,防止程序崩溃;分数 = 剩余机会 × 10,鼓励玩家少次数猜中。


💪 进阶 20 分钟:常见坑 + 性能小贴士

坑 1:while 循环忘了加退出条件 = 死循环

# ❌ 错误示例:永远退不出的循环
count = 0
while count < 10:
print(count)
# 忘了 count += 1,电脑会卡死
# ✅ 正确示例:记得更新计数器
count = 0
while count < 10:
print(count)
count += 1  # 每次+1,最终会退出

避坑:写 while 循环时,先把退出条件写在注释里,确保每次循环都有逼近退出条件的操作。


坑 2:break 和 continue 位置放错

# ❌ 错误示例:continue 在判断后面,但没处理好边界
for i in range(1, 10):
if i % 2 == 0:
    continue
print(i)
# 如果 continue 后还有代码,会被跳过
# ✅ 正确示例:continue 只跳过当前迭代的后续代码
for i in range(1, 10):
if i % 2 == 0:
    continue  # 跳过偶数,直接下一个
print(f"{i} 是奇数")

坑 3:input() 返回的是字符串,不是数字

# ❌ 错误示例:直接比较字符串和整数
age = input("请输入年龄:")
if age > 18:  # 字符串和整数比不了,会报错
print("成年人")
# ✅ 正确示例:先转成整数
age = int(input("请输入年龄:"))
if age > 18:
print("成年人")

坑 4:嵌套循环的缩进看错了

# ❌ 错误示例:内层和外层缩进一样,变成顺序执行
for i in range(3):
for j in range(3):
print(i, j)  # 这行不属于任何循环
# ✅ 正确示例:内层循环要再多缩进一级
for i in range(3):
for j in range(3):
    print(i, j)  # 缩进在内层循环里

性能小贴士:字符串拼接用 join() 而不是 +

# ❌ 慢:每次拼接都创建新字符串
result = ""
for i in range(1000):
result += str(i)

# ✅ 快:先收集再一次性拼接
parts = []
for i in range(1000):
parts.append(str(i))
result = "".join(parts)

原因:+ 拼接每次都重新分配内存,join() 只分配一次。


调试技巧:print 大法

# 不知道循环跑到哪了?加个 print
for i in range(10):
print(f"DEBUG: i = {i}, 条件 = {i < 5}")
if i < 5:
    print("还在范围内...")

技巧:调试完后,用 # 注释掉或删掉这些 print,别留在正式代码里。


✏️ 练习题 + 作业题

练习题(5 道,10 分钟内完成)

练习 1(1 分钟):改改猜数字的范围
- 输入:把 random.randint(1, 100) 改成 random.randint(1, 50)
- 预期输出:游戏变成猜 1-50 的数
- 提示:改一个数字就行

练习 2(2 分钟):加一个「再猜一次」提示
- 输入:在用户猜错后,加一句「请再试一次」
- 预期输出:每次猜错都显示这句话
- 提示:在 if/elif/else 里加一行 print

练习 3(2 分钟):把九九乘法表倒着打印
- 输入:改成 range(9, 0, -1)(从 9 到 1,倒着来)
- 预期输出:9×1=9 在第一行,1×1=1 在最后一行
- 提示:外层循环改成倒序

练习 4(3 分钟):只打印奇数行乘法表
- 输入:在九九乘法表里加一个 if 判断
- 预期输出:只显示 1、3、5、7、9 行的乘法表
- 提示:if i % 2 == 1 判断奇数行

练习 5(2 分钟):分析这个报错
- 输入:运行下面代码后报错

for i in range(5):
if i == 3:
    break
print(i)
print("最后 i =", i)
  • 预期输出:0 1 2 "最后 i = 3"
  • 提示:break 跳出了循环,但 i 还是等于 3

作业题:做一个「1A2B 猜数字」游戏

需求描述:实现一个「1A2B」类猜数字游戏(也叫「羊驼游戏」)——计算机生成一个不重复的 4 位数字(如 1234),你来猜,计算机反馈「XAYB」格式:

  • A = 数字对且位置对(叫 "Bulls")
  • B = 数字对但位置错(叫 "Cows")

功能点
1. 计算机随机生成 4 个不重复的 0-9 数字
2. 用户输入猜测,支持输入验证(非数字、重复数字、位数不对)
3. 每次猜测后给出 "XAYB" 反馈,直到猜对为止
4. 显示猜了多少次,并给出评价(如"太笨了"/"还不错"/"天才!")

加分项
1. 支持输入 "hint" 显示提示(随机揭示一个正确位置的数字)
2. 支持输入 "history" 查看历史猜测记录

验收标准
- 能跑起来,不崩溃
- 输入正确时输出正确
- 代码有适当注释(每段代码干啥的)

提交方式:评论区贴代码或 GitHub 链接


📚 总结 + 资源

本文学到的 3 个核心点

  1. 随机数 random.randint() 让程序有了「不确定性」,是做游戏的基础
  2. while 循环 适合「不知道要跑多少次」的场景,比如猜数字
  3. 嵌套循环 可以处理二维数据,比如打印九九乘法表

延伸学习资源


互动钩子:你在玩猜数字游戏时,最多猜了几次才猜对?有没有什么独门技巧?评论区聊聊,老粉优先回复!


💡 下章预告:学会了循环和判断,我们可以做很多事情了。但你有没有发现——每次要重复用一段代码时,我们只能复制粘贴?如果能给一段代码起个名字,下次直接调用就好了……下一章我们就来解决这个问题!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。