ใหม่สำหรับ Rust: เกม Hangman

Oct 11 2020

ฉันตัดสินใจลองเล่นเกมเพชฌฆาตเพื่อทำความคุ้นเคยกับภาษาเล็กน้อย

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

to_guessคำ hardcoded และมีไม่ จำกัด จำนวนของการคาดเดา

ในการจัดเก็บตัวอักษรที่เดาแล้วฉันใช้u128และตั้งค่าสถานะบิตที่เกี่ยวข้อง ควรจะโอเคเนื่องจากตัวอักษร ASCII ทั้งหมดแสดงด้วยu8<128

คุณช่วยตรวจสอบโค้ดได้ไหมมี "สนิม" ที่ฉันพลาดไปหรือไม่

คำตอบ

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

ยินดีต้อนรับสู่สนิม คำแนะนำบางประการในการเริ่มต้น:

การสร้างการประกาศการใช้สำนวน

เป็นเรื่องปกติใน Rust ที่จะนำฟังก์ชันเข้าสู่ขอบเขตโดยตรงผ่านการประกาศการใช้งาน แทนio::stdinและio::stdoutเป็นที่ต้องการ ดูส่วนการสร้าง Idiomatic use Pathsในหนังสือสำหรับข้อมูลเพิ่มเติม

การใช้โครงสร้างกับรหัสเอกสารตนเอง

คุณรวมประโยคนี้ไว้ในคำอธิบายรหัสของคุณ:

ในการจัดเก็บตัวอักษรที่เดาแล้วฉันใช้u128และตั้งค่าสถานะบิตที่เกี่ยวข้อง ควรจะโอเคเนื่องจากตัวอักษร ASCII ทั้งหมดแสดงด้วยu8<128

ควรรวมข้อมูลนี้ไว้ในโค้ดเอง ในกรณีนี้เราสามารถแนะนำ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
    }
}

และแก้ไขรหัสตาม:

let mut letters = AsciiSet::new();

loop {
    // ...
    if letters.contains(letter) { /* ... /* }

    // ...
    letters.push(letter);
}

กำลังตรวจสอบ ASCII

letter as u8!letter.is_ascii()ตัดทอนตัวอักษรถ้า ตรวจสอบกรณีนี้และแจ้งให้ผู้ใช้ทราบ