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,
}
}
}
}