Thirty Days of Rust: Day Three*
Tags: challenge, rust, programming, 30days
Published: 2022-01-15 00:32:12

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:
{% comment 1l79g %}

Anyway, I ran into some problems today, but I managed to finish the Hangman game nonetheless.
## Code
```rust
// /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);
}
```
### 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 `str`s instead of `String`s 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.