Tracking State

Guess history, attempt limits, and a struct to hold it all.

Part 2 of 3Updated

A bare loop with local variables stops scaling the moment you have more than two pieces of state. Move it into a struct.

struct Game {
    secret: u32,
    guesses: Vec<u32>,
    max_attempts: usize,
}

impl Game {
    fn new(max_attempts: usize) -> Self {
        Self {
            secret: rand::rng().random_range(1..=100),
            guesses: Vec::new(),
            max_attempts,
        }
    }

    fn guess(&mut self, value: u32) -> Ordering {
        self.guesses.push(value);
        value.cmp(&self.secret)
    }

    fn out_of_attempts(&self) -> bool {
        self.guesses.len() >= self.max_attempts
    }
}

Notice the receiver types: &mut self when the method mutates, &self when it only reads. The compiler enforces that distinction, which means you can tell what a method does from its signature alone.