猜数字游戏是编程入门的"Hello World+"——它足够简单,几分钟就能跑通;又足够丰富,可以练习条件判断、循环、异常处理和用户交互。跟着本文完成这个项目,你的 Python 基础会更扎实。
目录
1. 项目目标与功能设计
基本功能
- 程序随机生成一个 1~100 之间的整数
- 玩家每次输入一个猜测数字
- 程序提示"太大了"或"太小了"
- 猜中后显示恭喜信息和猜测次数
- 支持"再玩一局"
扩展功能(增强版)
- 难度选择:简单(1
50, 10次)、普通(1100, 7次)、困难(1~200, 5次) - 输入验证:非数字输入友好提示,不计入次数
- 作弊模式:输入
hint可获得范围提示 - 排行榜:记录最少猜测次数
2. 核心知识点概览
在这个项目中,你将实践以下 Python 核心概念:
| 知识点 | 在猜数字中的应用 |
|---|---|
random.randint() | 生成随机目标数字 |
input() | 获取用户输入 |
int() | 字符串转整数 |
if / elif / else | 比较猜测与目标数字 |
while 循环 | 允许玩家反复猜测 |
try / except | 处理非数字输入的异常 |
函数定义 def | 代码模块化组织 |
字符串格式化 f-string | 友好的输出信息 |
3. 基础版实现
import random
def guess_number_game():
"""基础版猜数字游戏"""
secret = random.randint(1, 100)
attempts = 0
max_attempts = 7
print("=" * 40)
print("🎮 欢迎来到猜数字游戏!")
print("我已经想好了一个 1 到 100 之间的数字。")
print(f"你有 {max_attempts} 次机会猜中它。")
print("=" * 40)
while attempts < max_attempts:
attempts += 1
# 获取用户输入
guess_str = input(f"\n第 {attempts}/{max_attempts} 次猜测,请输入数字:")
# 验证输入
try:
guess = int(guess_str)
except ValueError:
print("⚠️ 请输入有效的整数!")
attempts -= 1 # 不计入次数
continue
# 检查范围
if guess < 1 or guess > 100:
print("⚠️ 数字必须在 1 到 100 之间!")
attempts -= 1
continue
# 判断结果
if guess == secret:
print(f"\n🎉 恭喜你!猜对了!")
print(f"🎯 目标数字就是 {secret}。")
print(f"🏆 你用了 {attempts} 次就猜中了!")
return True
elif guess < secret:
print("📈 太小了!再大一点。")
else:
print("📉 太大了!再小一点。")
# 提示剩余次数
remaining = max_attempts - attempts
if remaining > 0:
print(f"💡 还剩 {remaining} 次机会。")
# 次数用完
print(f"\n😢 很遗憾,次数用完了。")
print(f"🎯 正确答案是 {secret}。")
return False
if __name__ == "__main__":
while True:
guess_number_game()
play_again = input("\n是否再玩一局?(y/n): ").strip().lower()
if play_again != 'y':
print("👋 感谢游玩,再见!")
break
运行效果
========================================
🎮 欢迎来到猜数字游戏!
我已经想好了一个 1 到 100 之间的数字。
你有 7 次机会猜中它。
========================================
第 1/7 次猜测,请输入数字:50
📈 太小了!再大一点。
💡 还剩 6 次机会。
第 2/7 次猜测,请输入数字:75
📉 太大了!再小一点。
💡 还剩 5 次机会。
第 3/7 次猜测,请输入数字:62
📈 太小了!再大一点。
💡 还剩 4 次机会。
第 4/7 次猜测,请输入数字:68
🎉 恭喜你!猜对了!
🎯 目标数字就是 68。
🏆 你用了 4 次就猜中了!
是否再玩一局?(y/n): y
...
4. 增强版:加入难度选择
import random
import json
import os
from pathlib import Path
SAVE_FILE = Path.home() / ".guess_number_scores.json"
class GuessNumberGame:
"""增强版猜数字游戏"""
DIFFICULTIES = {
"easy": {"range": 50, "max_attempts": 10, "name": "简单"},
"normal": {"range": 100, "max_attempts": 7, "name": "普通"},
"hard": {"range": 200, "max_attempts": 5, "name": "困难"},
}
def __init__(self):
self.scores = self.load_scores()
def load_scores(self):
"""加载历史最高分"""
if SAVE_FILE.exists():
return json.loads(SAVE_FILE.read_text(encoding="utf-8"))
return {}
def save_scores(self):
"""保存最高分"""
SAVE_FILE.write_text(json.dumps(self.scores, ensure_ascii=False, indent=2), encoding="utf-8")
def select_difficulty(self):
"""选择难度"""
print("\n请选择难度:")
print(" 1. 简单 (1~50, 10次机会)")
print(" 2. 普通 (1~100, 7次机会)")
print(" 3. 困难 (1~200, 5次机会)")
while True:
choice = input("输入 1/2/3: ").strip()
mapping = {"1": "easy", "2": "normal", "3": "hard"}
if choice in mapping:
return mapping[choice]
print("⚠️ 请输入 1、2 或 3")
def get_hint(self, secret, min_guess, max_guess):
"""获取范围提示"""
range_size = max_guess - min_guess
if range_size <= 10:
return f"非常接近了!范围 {min_guess} ~ {max_guess}"
return f"当前范围:{min_guess} ~ {max_guess}"
def play_round(self):
"""进行一局游戏"""
difficulty = self.select_difficulty()
config = self.DIFFICULTIES[difficulty]
max_range = config["range"]
max_attempts = config["max_attempts"]
secret = random.randint(1, max_range)
# 记录当前搜索范围(用于 hint)
min_bound, max_bound = 1, max_range
print(f"\n{'='*50}")
print(f"🎮 难度:{config['name']} | 范围:1 ~ {max_range} | 机会:{max_attempts}")
print(f"{'='*50}")
for attempt in range(1, max_attempts + 1):
guess_str = input(f"\n第 {attempt}/{max_attempts} 次,输入数字(或 hint 提示):").strip().lower()
# hint 作弊模式
if guess_str == "hint":
print(f"💡 {self.get_hint(secret, min_bound, max_bound)}")
attempt -= 1
continue
# 输入验证
try:
guess = int(guess_str)
except ValueError:
print("⚠️ 请输入有效的整数!")
attempt -= 1
continue
# 范围检查
if guess < 1 or guess > max_range:
print(f"⚠️ 数字必须在 1 到 {max_range} 之间!")
attempt -= 1
continue
# 更新搜索范围
if guess < secret and guess > min_bound:
min_bound = guess
elif guess > secret and guess < max_bound:
max_bound = guess
# 判断
if guess == secret:
self.handle_win(difficulty, attempt, secret)
return True
elif guess < secret:
print("📈 太小了!")
else:
print("📉 太大了!")
remaining = max_attempts - attempt
if remaining > 0:
print(f"💡 还剩 {remaining} 次机会")
# 失败
print(f"\n😢 次数用尽!正确答案是 {secret}")
return False
def handle_win(self, difficulty, attempts, secret):
"""处理胜利"""
print(f"\n🎉 恭喜你!猜对了!")
print(f"🎯 数字就是 {secret}")
print(f"🏆 难度:{self.DIFFICULTIES[difficulty]['name']} | 用了 {attempts} 次")
# 更新最高分
key = f"best_{difficulty}"
prev_best = self.scores.get(key)
if prev_best is None or attempts < prev_best:
self.scores[key] = attempts
self.save_scores()
print("✨ 新纪录!")
else:
print(f"📊 历史最佳:{prev_best} 次")
def show_stats(self):
"""显示统计"""
if not self.scores:
print("\n暂无记录。")
return
print("\n📈 个人最佳记录:")
for key, value in self.scores.items():
diff_name = key.replace("best_", "")
print(f" {self.DIFFICULTIES[diff_name]['name']}模式: {value} 次")
def run(self):
"""主循环"""
print("="*50)
print("🎮 Python 猜数字游戏")
print("="*50)
while True:
print("\n1. 开始游戏")
print("2. 查看记录")
print("3. 退出")
choice = input("\n选择: ").strip()
if choice == "1":
self.play_round()
elif choice == "2":
self.show_stats()
elif choice == "3":
print("👋 再见!")
break
else:
print("⚠️ 无效选择")
if __name__ == "__main__":
game = GuessNumberGame()
game.run()
5. 代码详解:逐行解析
5.1 random.randint() 详解
import random
# randint(a, b) 生成 [a, b] 闭区间的整数
secret = random.randint(1, 100) # 可能是 1, 50, 100... 任意值
# 替代方案:
# randrange(1, 101) —— 半开区间 [1, 101),等价于 randint(1, 100)
# random.choice(range(1, 101)) —— 从序列中随机选择
# secrets.randbelow(100) + 1 —— 密码学安全随机(游戏不需要)
5.2 input() 与类型转换
# input() 始终返回字符串
user_input = input("输入:")
print(type(user_input)) # <class 'str'>
# 需要转为整数
try:
number = int(user_input)
except ValueError:
print("不是有效的数字!")
# 更好的做法:封装验证函数
def get_valid_number(prompt, min_val, max_val):
"""获取范围内的有效整数"""
while True:
try:
value = int(input(prompt))
if min_val <= value <= max_val:
return value
print(f"请输入 {min_val} 到 {max_val} 之间的数字")
except ValueError:
print("请输入有效的整数")
5.3 while 循环与条件判断
# 基础循环结构
attempts = 0
max_attempts = 7
while attempts < max_attempts:
attempts += 1
# ... 获取猜测 ...
if guess == secret:
print("赢了!")
break # 提前退出循环
elif guess < secret:
print("太小了")
else:
print("太大了")
else:
# while 正常结束(没有 break)时执行
print(f"次数用尽,答案是 {secret}")
5.4 文件持久化(JSON)
import json
from pathlib import Path
# 保存
scores = {"easy": 3, "normal": 5}
Path("scores.json").write_text(json.dumps(scores), encoding="utf-8")
# 加载
if Path("scores.json").exists():
scores = json.loads(Path("scores.json").read_text(encoding="utf-8"))
6. 常见错误与调试
错误 1:TypeError: ‘<’ not supported between ‘str’ and ‘int’
# ❌ 错误:忘了转换 input 的结果
guess = input("输入:")
if guess < secret: # TypeError!
# ✅ 正确
guess = int(input("输入:"))
错误 2:无限循环
# ❌ 错误:attempts 永远不会增加
attempts = 0
while attempts < 7:
if guess != secret:
print("错了") # 没有 attempts += 1
# ✅ 正确
while attempts < 7:
attempts += 1 # 确保计数器更新
错误 3:ValueError 未被捕获
# ❌ 错误:int() 转换在外层
num = int(input())
try:
if num < 1:
print("太小")
except ValueError: # 不会捕获到!int() 在上面已经抛出了
# ✅ 正确
try:
num = int(input())
except ValueError:
print("请输入数字")
7. 扩展挑战
完成基础版本后,尝试以下进阶挑战:
挑战 1:二分查找提示
让程序在每次猜测后提示"你现在的最优策略是猜 X",基于二分查找算法。
挑战 2:GUI 版本
使用 tkinter 制作图形界面:
import tkinter as tk
from tkinter import messagebox
class GuessNumberGUI:
def __init__(self):
self.root = tk.Tk()
self.root.title("猜数字游戏")
self.secret = random.randint(1, 100)
self.attempts = 0
tk.Label(self.root, text="输入你的猜测 (1-100):").pack()
self.entry = tk.Entry(self.root)
self.entry.pack()
tk.Button(self.root, text="猜测", command=self.check_guess).pack()
self.result_label = tk.Label(self.root, text="")
self.result_label.pack()
def check_guess(self):
try:
guess = int(self.entry.get())
# ... 判断逻辑 ...
except ValueError:
messagebox.showerror("错误", "请输入数字")
def run(self):
self.root.mainloop()
挑战 3:网络对战版
使用 Flask/FastAPI 制作 Web 版本,支持多人排行榜。参考 Python Web 框架指南。
挑战 4:AI 对手
写一个 AI 玩家,让它用二分查找策略自动玩游戏,并统计平均需要几次:
def ai_player(min_val, max_val, secret):
"""AI 用二分查找猜数字"""
attempts = 0
low, high = min_val, max_val
while True:
attempts += 1
guess = (low + high) // 2
if guess == secret:
return attempts
elif guess < secret:
low = guess + 1
else:
high = guess - 1
# 测试:1000 次游戏
results = [ai_player(1, 100, random.randint(1, 100)) for _ in range(1000)]
print(f"平均次数: {sum(results)/len(results):.2f}") # ≈ 5.5 次
print(f"最多次数: {max(results)}") # ≤ 7 次
8. 完整源码(可直接运行)
[见上方"增强版"代码块]
保存为 guess_number.py,然后运行:
python3 guess_number.py
9. 学习收获总结
完成这个项目后,你应该能:
| 技能 | 掌握程度 |
|---|---|
| random 模块使用 | ⭐⭐⭐⭐⭐ |
| 用户输入处理 | ⭐⭐⭐⭐⭐ |
| 条件判断(if/elif/else) | ⭐⭐⭐⭐⭐ |
| 循环控制(while/for) | ⭐⭐⭐⭐⭐ |
| 异常处理(try/except) | ⭐⭐⭐⭐⭐ |
| 函数定义与组织 | ⭐⭐⭐⭐⭐ |
| 文件读写(JSON序列化) | ⭐⭐⭐⭐ |
| 面向对象基础(class) | ⭐⭐⭐⭐ |
延伸阅读
- Python 10 分钟极速上手手册 —— 巩固基础语法
- Python 教程之倒计时猜数字 —— 为游戏添加计时功能
- Python 内置数据结构完全指南 —— 用 dict 和 list 优化排行榜
- Python 类型系统与 Pydantic V2 —— 给游戏加上类型注解
💡 最佳学习方法:不要只是复制粘贴代码。先理解每行代码的作用,然后尝试修改规则(比如范围改成 1~1000,或减少猜测次数),看看会发生什么。动手改代码,才是最好的学习。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。