Quick actions

cmd+k|ctrl+k

Navigation

Languages

Wordle

Snippet info

Language

Rust

Visibility

public

Author

jack98765.2007

Created

2025-01-22T09:38:46.471433Z

Updated

2025-01-22T09:38:46.471433Z

use rand::seq::IteratorRandom;
use std::io;
use std::io::Read;
use std::io::Write;


#[derive(PartialEq)]
enum Color {
    GREY,
    YELLOW,
    GREEN,
}

struct GuessChecker {
    res: Vec<(char, Color)>,
}

impl GuessChecker {
    fn new(guess: String, answer: &String) -> Result<Self, &str> {
        let mut obj = GuessChecker { res: Vec::new() };
        if guess.len() != answer.len() {
            return Err("Guess and answer must have the same length");
        }
        for (i, c) in guess.chars().enumerate() {
            let res;
            if c == answer.chars().nth(i).unwrap() {
                res = Color::GREEN;
            } else if answer.contains(c) {
                res = Color::YELLOW;
            } else {
                res = Color::GREY;
            }
            obj.res.push((c, res));
        }
        Ok(obj)
    }

    fn print(&self) {
        for (c, res) in self.res.iter() {
            match res {
                Color::GREY => print!("{}", c),
                Color::YELLOW => print!("\x1b[33m{}\x1b[m", c),
                Color::GREEN => print!("\x1b[32m{}\x1b[m", c),
            }
        }
        println!();
    }

    fn remove_redundant(&self, letters: &mut Vec<char>) {
        let removed_letters = self.res.iter()
            .filter(|(_, color)| *color == Color::GREY)
            .map(|(letter, _)| *letter)
            .collect::<Vec<char>>();
        letters.retain(|c| !removed_letters.contains(c));
    }

    fn is_win(&self) -> bool {
        self.res.iter().all(|(_, color)| *color == Color::GREEN)
    }
}

fn main() {
    let mut words: Vec<String> = Vec::new();
    {
        let mut f = std::fs::File::open("words.txt").unwrap();
        let mut buf = String::new();
        f.read_to_string(&mut buf).unwrap();
        for word in buf.split(' ') {
            words.push(word.to_string());
        }
    }

    let mut rng = rand::thread_rng();

    println!(
        "wordle game
\x1b[32mgreen\x1b[m = Correct letter, correct position
\x1b[33myellow\x1b[m = Correct letter, incorrect position
");

    loop {
        let answer = words.iter().choose(&mut rng).unwrap();
        let mut letters: Vec<char> = ('a'..'z').collect();
        loop {
            print!("\x1b[91mLetters: ");
            for letter in letters.iter() {
                print!("{} ", letter);
            }
            print!("\x1b[m\n> ");
            io::stdout().flush().unwrap();

            let mut buf = String::new();
            io::stdin().read_line(&mut buf).unwrap();
            let guess = buf.trim().to_string();

            let checker = GuessChecker::new(guess, answer).unwrap();
            checker.remove_redundant(&mut letters);
            checker.print();
            if checker.is_win() {
                println!("You win!");
                break;
            }
        }

        loop {
            print!("Play again? (y/n): ");
            io::stdout().flush().unwrap();
            let mut buf = String::new();
            io::stdin().read_line(&mut buf).unwrap();
            let ans = buf.trim().to_lowercase();
            match ans.as_str() {
                "y" => break,
                "n" => return,
                _ => continue,
            }
        }
    }
}
INFO