DEV Community

Sammy Shear
Sammy Shear

Posted on

Thirty Days of Rust: Day Three*

I took a few days off from this challenge due to some personal things, but I came into today ready to go. Today I wanted to make a classic little hangman game in the command line, which was a lot harder than I thought to be honest with you. I definitely also went about this in the wrong way though, I just was too stubborn to start over. Today was also the day I switched from the official Rust Language Server to rust-analyzer, which I don't regret, thanks to this comment:

rustup is a bit more than "better maintained", it is an official project of Rust.

And rsvm? Well, never heard of it up to this moment...

Another thing, I would really recommend you to try rust-analyzer out. The Rust extension is very slow and laggy, while rust-analyzer is excellent. It is also semi-official and supposed to replace the Rust extension at some point in the future.

The official extension just compiles your whole project on every keystroke and decrypts a big ol' chunk of json the compiler gives back; rust-analyzer, on the other hand, incrementally parses & analyzes your code, and it is going rapidly better.

Anyway, I ran into some problems today, but I managed to finish the Hangman game nonetheless.

Code

// /src/main.rs

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

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("_");
        }
    }

    while current_guess != word_to_guess {
        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.chars().collect::<Vec<_>>().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];
                    current_guess = new_guess.iter().collect::<String>();
                } else {
                    continue;
                }
            }
        } else {
            println!("You already guessed that");
            continue;
        }
    }
    println!("You won! Guesses: {:?}", guessed_letters.len());
    println!("{}", current_guess);
}
Enter fullscreen mode Exit fullscreen mode

Problems

So I went into this thinking it would be easy, I've made a hangman game in the command line before. My first mistake was trying to use primitive strs instead of Strings because my instinct was to write out an empty string literal to make a new string variable instead of String::new(). That caused me to run into a lot of concatenation problems, which I tried using the str-concat crate for, causing my code to have multiple panic points. So I switched to using String variables, and it was much easier from there. Then I went ahead and tried to make the game logic itself, which failed spectacularly because I attempted to replace the occurrences of each char not equal to a correct guess with an underscore, instead of just replacing the underscores with the correct letters. So after I spent far too long tearing my hair out trying to get that to work, I moved to the other method. At first I tried a foreach loop, but unable to find a way to get the index of a char, and also because it made more sense, I switched to standard for loop, and that's about where I stopped.

Shortcomings

So something you'll notice if you read the code and/or run the code is that there's no way to lose. The simple reason for that is that I was running out of time, and didn't want to take another day off now that I was actually ready to come back, so I just ended it there. It might be that tomorrow's article is me adding in the loss logic though. That's about all from me for today, and thanks for reading.

Discussion (0)