Neu bei Rust: Hangman-Spiel

Oct 11 2020

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

2 L.F. Oct 17 2020 at 10:06

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 durch u8<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.