Thirty Days of Rust: Day Four

sammyshear

Sammy Shear

Posted on January 15, 2022

Thirty Days of Rust: Day Four

Today was more of a relaxed day for me, instead of putting together a whole new project I just added the ability to lose into my hangman game. This was way simpler than I thought it would be (I'm not really sure why, but I expected this to take a while), so I don't really have that much to share, but I will share it.

Final Code

// /src/main.rs

use rand::seq::SliceRandom;
use rand::thread_rng;
use std::io;

fn main() {
    let mut rng = thread_rng();

    let possible_words = [
        "Hangman",
        "Challenge",
        "Hello, World!",
        "Programming",
        "Rust",
        "Thirty Days",
        "Day Three",
    ];
    let word_to_guess = possible_words.choose(&mut rng).unwrap().to_string();

    let mut guessed_letters: Vec<char> = vec![];

    let mut current_guess = String::new();
    for i in 0..word_to_guess.chars().count() {
        if &word_to_guess.chars().nth(i).unwrap() == &' ' {
            current_guess.push_str(" ");
        } else {
            current_guess.push_str("_");
        }
    }

    let mut guesses_left: i32 = 8;

    while current_guess != word_to_guess && guesses_left > 0 {
        println!("{}", &current_guess);
        println!("Make a guess");
        println!("Guessed Letters: {:?}", guessed_letters);
        let mut guess = String::new();

        io::stdin().read_line(&mut guess).unwrap();

        if !guessed_letters.contains(&guess.chars().nth(0).unwrap()) {
            guessed_letters.push(guess.chars().nth(0).unwrap());

            let mut new_guess = current_guess.chars().collect::<Vec<_>>();

            for i in 0..word_to_guess.len() {
                if word_to_guess.chars().collect::<Vec<_>>()[i]
                    .eq_ignore_ascii_case(&guess.chars().nth(0).unwrap())
                {
                    new_guess[i] = word_to_guess.chars().collect::<Vec<_>>()[i];
                } else {
                    continue;
                }
            }

            if new_guess.iter().collect::<String>() == current_guess {
                guesses_left -= 1;
            }

            current_guess = new_guess.iter().collect::<String>();

            println!("Guesses left: {:?}", guesses_left);
        } else {
            println!("You already guessed that");
            continue;
        }
    }
    if current_guess == word_to_guess {
        println!("You won! Guesses: {:?}", guessed_letters.len());
        println!("{}", current_guess);
    } else {
        println!("You lose! Guesses: {:?}", guessed_letters.len())
    }
}
Enter fullscreen mode Exit fullscreen mode

It's basically the same as yesterday, but with a few things added. Notably, a variable to keep track of how many guesses are left, an extra condition for the while loop, and a way to check if the guess was wrong or not:

...
let mut guesses_left: i32 = 8;
...
while current_guess != word_to_guess && guesses_left > 0
...
if new_guess.iter().collect::<String>() == current_guess {
                guesses_left -= 1;
            }

            current_guess = new_guess.iter().collect::<String>();
...
Enter fullscreen mode Exit fullscreen mode

The last part is also a slight change to what I was doing before, which was to immediately assign the current_guess to the new_guess instead of waiting until I checked the validity of the guess.

Problem Solving

The first way I went about this was just by getting rid of the continue; in that else statement and replacing it with the guesses_left -= 1; line. The problem with this is that it runs each for loop iteration, so that was a no go. Not thinking too hard about it, I changed guesses_left to be dependant on the length of word_to_guess, which sort of solved one issue but raised another one. The line was still being called every iteration, so instead of only using up "one" guess if the guess was wrong, it used up one guess every time a letter wasn't every letter in the string, which was all the time. That's why I had to bring the logic out of the for loop, and instead of relying on that else statement, I just waited to reassign current_guess to the value of new_guess until after I had made a check to see if anything was correct.
That's about it for me today, and thanks for reading.

💖 💪 🙅 🚩
sammyshear
Sammy Shear

Posted on January 15, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Thirty Days of Rust: Day Four
30days Thirty Days of Rust: Day Four

January 15, 2022