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단어는 하드 코딩되어 있으며 추측 횟수에 제한이 없습니다.

이미 추측 한 문자를 저장하려면 u128해당 비트에 및 플래그를 사용합니다 . 모든 ASCII 문자는 u8<128 로 표시되므로 괜찮습니다 .

코드 검토를 도와 주실 수 있습니까? 제가 놓친 "녹"사항이 있습니까?

답변

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

Rust에 오신 것을 환영합니다. 시작하기위한 몇 가지 제안 사항은 다음과 같습니다.

관용적 사용 선언 만들기

Rust에서 use 선언을 통해 함수를 직접 범위로 가져 오는 것은 일반적이지 않습니다. 대신에, io::stdin그리고 io::stdout것이 바람직하다. 자세한 내용은 책의 관용적 사용 경로 만들기 섹션 을 참조하십시오.

구조체를 사용하여 코드 자체 문서화

코드 설명에 다음 문장을 포함했습니다.

이미 추측 한 문자를 저장하려면 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(). 이 경우를 확인하고 그에 따라 사용자에게 메시지를 표시합니다.