猜数字是经典入门游戏:程序随机生成 1~100 的秘密数字,不断猜测,程序提示"太大"或"太小",直到猜中。本文用面向对象实现——把状态装进类里,代码清晰易扩展,这正是 C++ 的核心思想。

玩法介绍

程序随机生成 1~100 的整数,你每次猜一个数,程序回答"太小/太大";猜中时打印全部猜测历史。二分最多 7 次猜中。

第 1 步:搭好骨架与主循环

先搭大框架:一个无限循环负责输入→判断→提示,逻辑稍后填入:

#include <iostream>

int main() {
    std::cout << "猜数字游戏开始!范围 1~100\n";
    int n;
    while (true) {
        std::cout << "请输入你的猜测: ";
        std::cin >> n;
        // 判断大小并提示(稍后实现)
    }
    return 0;
}

第 2 步:用类封装游戏状态

把秘密数字、范围、猜测历史这些状态,连同判断、记录等操作,一起装进一个 NumberGuesser 类。私有成员保证外部无法直接篡改秘密数字,只能通过公开接口与游戏交互——这就是封装:

class NumberGuesser {
private:
    int secret_ = 0;           // 秘密数字
    int max_ = 100;            // 范围上限
    std::vector<int> history_;  // 猜测历史

public:
    explicit NumberGuesser(int max) : max_(max) { reset(); }
    void reset();              // 重新生成秘密数字
    bool guess(int n);         // 记录猜测并判断
    int compare(int n) const;  // -1 太小 / 0 猜中 / 1 太大
    const std::vector<int>& history() const { return history_; }
};

第 3 步:生成真正的随机数

C 时代的 rand() 质量一般,现代 C++ 用 <random>:std::random_device 提供种子,std::mt19937 是梅森旋转引擎,uniform_int_distribution 生成均匀整数:

void NumberGuesser::reset() {
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<int> dist(1, max_);
    secret_ = dist(gen);
    history_.clear();
}

每次调用 reset(),秘密数字都不同,历史记录也在此清空。

第 4 步:记录猜测历史

std::vector 保存每次猜测——自动扩容、按下标访问。把"记录"和"判断"合并进 guess(),调用一次完成两件事:

bool NumberGuesser::guess(int n) {
    history_.push_back(n);
    return n == secret_;
}

int NumberGuesser::compare(int n) const {
    if (n < secret_) return -1;
    if (n > secret_) return 1;
    return 0;
}

第 5 步:完整代码与编译运行

拼成 guess.cpp 编译运行,猜中后打印完整猜测历史:

#include <iostream>
#include <random>
#include <vector>

class NumberGuesser {
private:
    int secret_ = 0;
    int max_ = 100;
    std::vector<int> history_;

public:
    explicit NumberGuesser(int max) : max_(max) { reset(); }

    void reset() {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<int> dist(1, max_);
        secret_ = dist(gen);
        history_.clear();
    }

    bool guess(int n) {
        history_.push_back(n);
        return n == secret_;
    }

    int compare(int n) const {
        if (n < secret_) return -1;
        if (n > secret_) return 1;
        return 0;
    }

    const std::vector<int>& history() const { return history_; }
};

int main() {
    NumberGuesser game(100);
    std::cout << "猜数字:1~100,开始吧!\n";
    int n;
    while (true) {
        std::cout << "> ";
        std::cin >> n;
        if (game.guess(n)) {
            std::cout << "恭喜!共猜了 " << game.history().size() << " 次。\n";
            break;
        }
        if (game.compare(n) < 0) std::cout << "太小了!\n";
        else std::cout << "太大了!\n";
    }
    std::cout << "猜测记录:";
    for (int h : game.history()) std::cout << " " << h;
    std::cout << "\n";
    return 0;
}
g++ -std=c++17 -o guess guess.cpp
./guess

把范围改成 1~1000 试试;再想想输入非数字时 std::cin 会怎样?这是你的第一个"健壮性"练习。

💡 改进方向:① 给 guess() 加输入合法性检查;② 统计平均猜中次数,对比二分最优解;③ 支持"你出题,电脑猜"的反向模式;④ 用 std::map 统计各数字被猜中次数。