Neu bei Rust: Hangman-Spiel
Ich beschloss, mich an einem Hangman-Spiel zu versuchen, um mich ein wenig mit der Sprache vertraut zu machen.
use std::io::{stdin, stdout, Write};
fn main() {
let stdin = stdin();
let mut stdout = stdout();
let to_guess = String::from("BENEDICT");
let mut letters: u128 = 0;
loop {
// Replace unguessed letters of to_guess by underscores
let current = to_guess.chars().map(|x| {
if x <= 127 as char && letters & (1 << x as u8) > 0 {
x
} else {
'_'
}
});
// Add spaces between letters
let current = current
.map(|x| x.to_string() + &' '.to_string())
.collect::<Vec<String>>()
.join(" ");
println!("Current word: {}", current.trim_end());
if !current.contains('_') {
println!("Congratulations!");
break;
}
print!("Enter new letter: ");
stdout.flush().unwrap();
let mut letter = String::new();
stdin.read_line(&mut letter).expect("Invalid letter");
if letter.trim().len() != 1 {
println!("Use only one ASCII letter");
continue;
}
let letter = letter.to_uppercase().chars().next().unwrap();
letters |= 1 << letter as u8
}
}
Das to_guessWort ist fest codiert und es gibt eine unbegrenzte Anzahl von Vermutungen.
Um bereits erratene Buchstaben zu speichern, verwende ich ein u128und markiere das entsprechende Bit. Es sollte in Ordnung sein, da alle ASCII-Buchstaben durch u8<128 dargestellt werden.
Können Sie mir helfen, den Code zu überprüfen? Gibt es "Rust" -Dinge, die ich verpasst habe?
Antworten
Willkommen bei Rust. Hier sind einige Vorschläge, um Ihnen den Einstieg zu erleichtern:
Erstellen idiomatischer Verwendungserklärungen
In Rust ist es nicht üblich, eine Funktion direkt über eine Verwendungserklärung in den Geltungsbereich zu bringen. Stattdessen io::stdinund io::stdoutwerden bevorzugt. Weitere Informationen finden Sie im Abschnitt Erstellen idiomatischer Verwendungspfade im Buch.
Verwenden von Strukturen zum Selbstdokumentieren von Code
Sie haben diesen Satz in Ihre Erklärung des Codes aufgenommen:
Um bereits erratene Buchstaben zu speichern, verwende ich ein
u128und markiere das entsprechende Bit. Es sollte in Ordnung sein, da alle ASCII-Buchstaben durchu8<128 dargestellt werden.
Es ist vorzuziehen, diese Informationen in den Code selbst aufzunehmen. In diesem Fall können wir Folgendes einführen struct:
#[derive(Clone, Copy, Debug, Default)]
struct AsciiSet {
flag: u128,
}
impl AsciiSet {
fn new() -> Self {
Self { flag: 0 }
}
fn push(&mut self, letter: u8) {
self.flag |= (1 << letter);
}
fn contains(&self, letter: u8) -> bool {
(self.flag & (1 << letter)) != 0
}
}
und ändern Sie den Code entsprechend:
let mut letters = AsciiSet::new();
loop {
// ...
if letters.contains(letter) { /* ... /* }
// ...
letters.push(letter);
}
Auf ASCII prüfen
letter as u8schneidet das Zeichen ab, wenn !letter.is_ascii(). Überprüfen Sie diesen Fall und fordern Sie den Benutzer entsprechend auf.