← 返回列表

命令行猜数字游戏

一个经典的交互式脚本,利用 Random 模块生成随机数,并通过 While 循环判断用户输入。该案例展示了基本的逻辑控制、输入输出交互以及异常处理。

快速预览:

import random
target = random.randint(1, 100)
while True:
    guess = int(input("请输入你猜测的数字: "))
    if guess == target:
        print("恭喜你,猜对了!")
        break
    print("太大了" if guess > target else "太小了")

应用场景与价值

虽然猜数字游戏看似简单,但它包含了程序设计的核心要素,是学习编程的绝佳入门案例:

  • 编程教学: 适合初学者理解循环、条件判断、用户输入等基础概念
  • 逻辑思维训练: 培养二分查找的思维方式,提升问题解决能力
  • 交互式应用: 展示如何创建用户友好的命令行界面
  • 游戏开发基础: 为开发更复杂的游戏打下基础(状态管理、用户反馈)
  • 算法实践: 可扩展为 AI 自动猜数字,学习二分查找算法

这个简单的游戏蕴含了丰富的编程知识,是从"学习代码"到"用代码解决问题"的重要跨越。

基础知识

random 模块

random 模块提供了生成随机数的功能,是 Python 标准库的一部分。

import random

# 生成随机整数
random.randint(1, 100)      # 1到100之间的随机整数(包含1和100)
random.randrange(0, 100, 5) # 0到100之间,步长为5的随机数

# 生成随机浮点数
random.random()             # 0到1之间的随机浮点数
random.uniform(1.5, 5.5)    # 1.5到5.5之间的随机浮点数

# 序列操作
random.choice([1, 2, 3])    # 从列表中随机选择一个元素
random.shuffle(my_list)     # 随机打乱列表顺序

while 循环

while 循环在条件为真时持续执行代码块:

while 条件:
    # 循环体
    # 如果条件始终为真,将无限循环
    break    # 跳出循环
    continue # 跳过本次循环,继续下一次

用户输入

input() 函数用于获取用户输入,返回字符串类型:

name = input("请输入你的名字: ")  # 返回字符串
age = int(input("请输入年龄: "))   # 转换为整数

条件表达式(三元运算符)

Python 的简洁写法:

# 传统写法
if guess > target:
    message = "太大了"
else:
    message = "太小了"

# 条件表达式
message = "太大了" if guess > target else "太小了"

代码详解

让我们逐步分析猜数字游戏的实现逻辑:

import random

导入 random 模块,用于生成随机目标数字。

target = random.randint(1, 100)

生成1到100之间的随机整数作为目标数字。这个数字对玩家保密,是游戏的核心。

while True:

创建无限循环。游戏将持续进行,直到玩家猜对数字(通过 break 退出循环)。

    guess = int(input("请输入你猜测的数字: "))

获取用户输入并转换为整数。注意:input() 返回的是字符串,必须用 int() 转换。

    if guess == target:
        print("恭喜你,猜对了!")
        break

判断用户猜测是否正确。如果相等,显示祝贺信息并用 break 退出循环,游戏结束。

    print("太大了" if guess > target else "太小了")

给出提示:如果猜测的数字大于目标数字,提示"太大了";否则提示"太小了"。使用条件表达式简化代码。

完整代码

基础版本:带计数和输入验证

import random

def guess_number_game():
    """猜数字游戏 - 基础版本"""
    print("=" * 50)
    print("     欢迎来到猜数字游戏!")
    print("=" * 50)
    print("我已经想好了一个1到100之间的数字,")
    print("请你来猜猜看是多少吧!\n")

    target = random.randint(1, 100)
    attempts = 0
    max_attempts = 10

    while attempts < max_attempts:
        try:
            guess = int(input(f"第 {attempts + 1} 次猜测,请输入数字 (1-100): "))

            # 输入验证
            if guess < 1 or guess > 100:
                print("⚠️  请输入1到100之间的数字!\n")
                continue

            attempts += 1

            if guess == target:
                print(f"\n🎉 恭喜你!猜对了!")
                print(f"答案就是 {target},你用了 {attempts} 次猜测。")

                # 评价
                if attempts <= 3:
                    print("💯 太厉害了!你是猜数字高手!")
                elif attempts <= 6:
                    print("👍 不错哦!")
                else:
                    print("✅ 完成挑战!")
                break

            elif guess > target:
                print(f"📉 太大了!还剩 {max_attempts - attempts} 次机会\n")
            else:
                print(f"📈 太小了!还剩 {max_attempts - attempts} 次机会\n")

        except ValueError:
            print("❌ 输入无效,请输入一个数字!\n")

    else:
        # 循环正常结束(未被 break 打断)
        print(f"\n💔 游戏结束!你已用完所有机会。")
        print(f"正确答案是: {target}")


# 运行游戏
if __name__ == "__main__":
    guess_number_game()

    # 询问是否再玩一次
    while input("\n是否再玩一次?(y/n): ").lower() == 'y':
        print("\n" + "-" * 50 + "\n")
        guess_number_game()

    print("\n感谢游玩!再见!👋")

进阶版本:难度选择和游戏历史

import random
from datetime import datetime

class NumberGuessingGame:
    """猜数字游戏类"""

    DIFFICULTY_LEVELS = {
        '1': {'name': '简单', 'range': (1, 50), 'attempts': 10},
        '2': {'name': '中等', 'range': (1, 100), 'attempts': 8},
        '3': {'name': '困难', 'range': (1, 200), 'attempts': 10},
        '4': {'name': '专家', 'range': (1, 1000), 'attempts': 15}
    }

    def __init__(self):
        self.game_history = []

    def select_difficulty(self):
        """选择难度"""
        print("\n请选择难度:")
        for key, level in self.DIFFICULTY_LEVELS.items():
            range_info = level['range']
            print(f"{key}. {level['name']} - 范围: {range_info[0]}-{range_info[1]}, 机会: {level['attempts']}次")

        while True:
            choice = input("\n请输入难度 (1-4): ").strip()
            if choice in self.DIFFICULTY_LEVELS:
                return self.DIFFICULTY_LEVELS[choice]
            print("无效选择,请重新输入")

    def play_round(self, difficulty):
        """进行一局游戏"""
        min_num, max_num = difficulty['range']
        max_attempts = difficulty['attempts']

        target = random.randint(min_num, max_num)
        attempts = 0
        guesses = []

        print(f"\n开始游戏!数字范围: {min_num}-{max_num}")
        print(f"你有 {max_attempts} 次猜测机会\n")

        start_time = datetime.now()

        while attempts < max_attempts:
            try:
                guess = int(input(f"[{attempts + 1}/{max_attempts}] 请输入你的猜测: "))

                if guess < min_num or guess > max_num:
                    print(f"⚠️  请输入 {min_num}-{max_num} 之间的数字!\n")
                    continue

                attempts += 1
                guesses.append(guess)

                if guess == target:
                    end_time = datetime.now()
                    time_spent = (end_time - start_time).total_seconds()

                    print(f"\n🎉 恭喜!猜对了!")
                    print(f"答案: {target}")
                    print(f"用时: {time_spent:.1f}秒")
                    print(f"猜测次数: {attempts}")
                    print(f"猜测历史: {guesses}")

                    # 记录游戏历史
                    self.game_history.append({
                        'difficulty': difficulty['name'],
                        'attempts': attempts,
                        'time': time_spent,
                        'success': True
                    })

                    return True

                # 提供更智能的提示
                diff = abs(guess - target)
                if diff <= 5:
                    hint = "🔥 非常接近!"
                elif diff <= 10:
                    hint = "🌡️  很接近了"
                elif diff <= 20:
                    hint = "🌤️  有点接近"
                else:
                    hint = "❄️  还很远"

                direction = "太大了" if guess > target else "太小了"
                print(f"{direction} {hint}\n")

            except ValueError:
                print("❌ 请输入有效数字!\n")

        # 游戏失败
        print(f"\n💔 游戏结束!正确答案是: {target}")
        self.game_history.append({
            'difficulty': difficulty['name'],
            'attempts': max_attempts,
            'time': (datetime.now() - start_time).total_seconds(),
            'success': False
        })
        return False

    def show_statistics(self):
        """显示游戏统计"""
        if not self.game_history:
            print("\n暂无游戏记录")
            return

        print("\n" + "=" * 50)
        print("     游戏统计")
        print("=" * 50)

        total_games = len(self.game_history)
        wins = sum(1 for game in self.game_history if game['success'])
        win_rate = (wins / total_games) * 100

        print(f"总游戏局数: {total_games}")
        print(f"胜利次数: {wins}")
        print(f"胜率: {win_rate:.1f}%")

        if wins > 0:
            avg_attempts = sum(g['attempts'] for g in self.game_history if g['success']) / wins
            avg_time = sum(g['time'] for g in self.game_history if g['success']) / wins
            print(f"平均猜测次数: {avg_attempts:.1f}")
            print(f"平均用时: {avg_time:.1f}秒")

        print("=" * 50)

    def run(self):
        """运行游戏主循环"""
        print("=" * 50)
        print("     猜数字游戏 v2.0")
        print("=" * 50)

        while True:
            print("\n请选择操作:")
            print("1. 开始游戏")
            print("2. 查看统计")
            print("3. 退出")

            choice = input("\n请输入选项 (1-3): ").strip()

            if choice == '1':
                difficulty = self.select_difficulty()
                self.play_round(difficulty)

            elif choice == '2':
                self.show_statistics()

            elif choice == '3':
                print("\n感谢游玩!再见!👋")
                break

            else:
                print("无效选项,请重新输入")


# 运行游戏
if __name__ == "__main__":
    game = NumberGuessingGame()
    game.run()

高级版本:AI 自动猜测(二分查找演示)

import random
import time

def ai_guess_number(min_num=1, max_num=100, show_process=True):
    """
    AI 使用二分查找算法猜数字

    参数:
        min_num: 最小值
        max_num: 最大值
        show_process: 是否显示猜测过程
    """
    target = random.randint(min_num, max_num)
    attempts = 0
    low = min_num
    high = max_num

    print(f"\nAI 开始猜测 {min_num}-{max_num} 之间的数字...")
    print(f"(答案是 {target},但 AI 不知道)\n")

    if show_process:
        time.sleep(1)

    while low <= high:
        attempts += 1

        # 二分查找:取中间值
        guess = (low + high) // 2

        if show_process:
            print(f"第 {attempts} 次猜测: {guess} (范围: {low}-{high})")
            time.sleep(0.5)

        if guess == target:
            print(f"\n✅ AI 猜对了!答案是 {target}")
            print(f"用了 {attempts} 次猜测")
            print(f"理论最少次数: {(max_num - min_num).bit_length()} 次")
            return attempts

        elif guess > target:
            if show_process:
                print(f"   → 太大了,缩小范围到 {low}-{guess - 1}\n")
            high = guess - 1

        else:
            if show_process:
                print(f"   → 太小了,缩小范围到 {guess + 1}-{high}\n")
            low = guess + 1

    return attempts


def compare_strategies(min_num=1, max_num=100, rounds=100):
    """
    对比随机猜测和二分查找的效率

    参数:
        rounds: 测试轮数
    """
    print(f"\n对比测试: 随机猜测 vs 二分查找")
    print(f"范围: {min_num}-{max_num}, 测试轮数: {rounds}\n")

    random_attempts = []
    binary_attempts = []

    for i in range(rounds):
        target = random.randint(min_num, max_num)

        # 随机猜测策略
        attempts = 0
        available = list(range(min_num, max_num + 1))
        while True:
            attempts += 1
            guess = random.choice(available)
            available.remove(guess)
            if guess == target:
                random_attempts.append(attempts)
                break

        # 二分查找策略
        attempts = 0
        low, high = min_num, max_num
        while low <= high:
            attempts += 1
            guess = (low + high) // 2
            if guess == target:
                binary_attempts.append(attempts)
                break
            elif guess > target:
                high = guess - 1
            else:
                low = guess + 1

    # 输出结果
    print("结果统计:")
    print(f"随机猜测 - 平均: {sum(random_attempts) / len(random_attempts):.2f} 次")
    print(f"二分查找 - 平均: {sum(binary_attempts) / len(binary_attempts):.2f} 次")
    print(f"\n效率提升: {(1 - sum(binary_attempts) / sum(random_attempts)) * 100:.1f}%")


# 演示 AI 猜数字
ai_guess_number(1, 100, show_process=True)

# 策略对比
compare_strategies(1, 100, rounds=100)

运行示例

基础版本

uv run main.py

预期输出

==================================================
     欢迎来到猜数字游戏!
==================================================
我已经想好了一个1到100之间的数字,
请你来猜猜看是多少吧!

第 1 次猜测,请输入数字 (1-100): 50
📈 太小了!还剩 9 次机会

第 2 次猜测,请输入数字 (1-100): 75
📉 太大了!还剩 8 次机会

第 3 次猜测,请输入数字 (1-100): 62
📈 太小了!还剩 7 次机会

第 4 次猜测,请输入数字 (1-100): 68
📉 太大了!还剩 6 次机会

第 5 次猜测,请输入数字 (1-100): 65

🎉 恭喜你!猜对了!
答案就是 65,你用了 5 次猜测。
👍 不错哦!

是否再玩一次?(y/n):

扩展思路

1. 多人对战模式

def multiplayer_mode():
    """两个玩家轮流猜测,看谁先猜对"""
    target = random.randint(1, 100)
    players = ['玩家1', '玩家2']
    turn = 0

    while True:
        current_player = players[turn % 2]
        guess = int(input(f"{current_player} 的回合,请输入猜测: "))

        if guess == target:
            print(f"🏆 {current_player} 获胜!")
            break
        else:
            print("太大了" if guess > target else "太小了")
            turn += 1

2. 反向模式:玩家想数字,AI 猜

def reverse_mode():
    """玩家想一个数字,AI 来猜"""
    print("请在心里想一个1到100之间的数字,不要告诉我")
    input("准备好了请按回车...")

    low, high = 1, 100
    attempts = 0

    while low <= high:
        attempts += 1
        guess = (low + high) // 2

        print(f"\n我猜是: {guess}")
        feedback = input("(h=太大, l=太小, c=猜对了): ").lower()

        if feedback == 'c':
            print(f"太好了!我用了 {attempts} 次猜对了!")
            break
        elif feedback == 'h':
            high = guess - 1
        elif feedback == 'l':
            low = guess + 1

3. 添加提示系统

hints = {
    'even': lambda x: "是偶数" if x % 2 == 0 else "是奇数",
    'divisible': lambda x: f"能被 {random.choice([3, 5, 7])} 整除" if x % 3 == 0 else "不能被3整除",
    'digit_sum': lambda x: f"各位数字之和是 {sum(int(d) for d in str(x))}"
}

def get_hint(target, hint_type):
    """获取提示"""
    return hints[hint_type](target)

4. 成就系统

achievements = {
    '一击必中': lambda attempts: attempts == 1,
    '三猜之内': lambda attempts: attempts <= 3,
    '完美策略': lambda guesses, target: all(g < target for g in guesses[:-1][:len(guesses)//2]),
}

def check_achievements(attempts, guesses, target):
    """检查获得的成就"""
    unlocked = []
    for name, condition in achievements.items():
        if condition(attempts):
            unlocked.append(name)
    return unlocked

5. 排行榜系统

import json

def save_score(name, attempts, difficulty):
    """保存分数到排行榜"""
    try:
        with open('leaderboard.json', 'r') as f:
            leaderboard = json.load(f)
    except FileNotFoundError:
        leaderboard = []

    leaderboard.append({
        'name': name,
        'attempts': attempts,
        'difficulty': difficulty,
        'date': datetime.now().isoformat()
    })

    # 按尝试次数排序
    leaderboard.sort(key=lambda x: x['attempts'])

    with open('leaderboard.json', 'w') as f:
        json.dump(leaderboard[:10], f, indent=2)  # 只保留前10名

6. 图形界面版本

使用 tkinter 创建 GUI:

import tkinter as tk
from tkinter import messagebox

class GuessNumberGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("猜数字游戏")
        self.target = random.randint(1, 100)
        self.attempts = 0

        # 创建界面元素
        self.label = tk.Label(root, text="猜一个1到100之间的数字")
        self.label.pack()

        self.entry = tk.Entry(root)
        self.entry.pack()

        self.button = tk.Button(root, text="猜测", command=self.make_guess)
        self.button.pack()

    def make_guess(self):
        try:
            guess = int(self.entry.get())
            self.attempts += 1

            if guess == self.target:
                messagebox.showinfo("恭喜", f"猜对了!用了{self.attempts}次")
                self.reset_game()
            elif guess > self.target:
                self.label.config(text="太大了!")
            else:
                self.label.config(text="太小了!")

            self.entry.delete(0, tk.END)
        except ValueError:
            messagebox.showerror("错误", "请输入有效数字")

    def reset_game(self):
        self.target = random.randint(1, 100)
        self.attempts = 0
        self.label.config(text="猜一个1到100之间的数字")

root = tk.Root()
app = GuessNumberGUI(root)
root.mainloop()

学习要点

通过这个猜数字游戏,你可以掌握:

  1. 循环控制: while 循环的使用和退出条件
  2. 条件判断: if-elif-else 的逻辑组合
  3. 用户交互: input() 和 print() 的配合使用
  4. 异常处理: try-except 处理输入错误
  5. 数据验证: 检查用户输入的有效性
  6. 算法思维: 二分查找的实现和优化
  7. 面向对象: 用类组织游戏逻辑和数据
  8. 数据持久化: 保存游戏历史和排行榜

这些技能是编程的基础,掌握后可以应用到更复杂的项目中。猜数字游戏虽小,但五脏俱全,是学习编程的绝佳起点。