Mới đối với trò chơi Rust: Hangman
Tôi quyết định thử sức mình với trò chơi Hangman để làm quen một chút với ngôn ngữ này.
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
}
}
Các to_guesstừ được hardcoded, và có vô số dự đoán.
Để lưu trữ các chữ cái đã đoán, tôi sử dụng dấu u128và gắn cờ cho bit tương ứng. Sẽ ổn vì tất cả các chữ cái ASCII đều được biểu diễn bằng u8<128.
Bạn có thể giúp tôi xem lại mã, có những thứ "Rust" mà tôi đã bỏ sót?
Trả lời
Chào mừng đến với Rust. Dưới đây là một số gợi ý để bạn bắt đầu:
Tạo khai báo sử dụng thành ngữ
Rust không phổ biến khi đưa một hàm vào phạm vi trực tiếp thông qua khai báo sử dụng. Thay vào đó, io::stdinvà io::stdoutđược ưu tiên. Xem phần Tạo đường dẫn sử dụng thành ngữ trong sách để biết thêm thông tin.
Sử dụng cấu trúc để tự lập tài liệu mã
Bạn đã đưa câu này vào phần giải thích mã của mình:
Để lưu trữ các chữ cái đã đoán, tôi sử dụng dấu
u128và gắn cờ cho bit tương ứng. Sẽ ổn vì tất cả các chữ cái ASCII đều được biểu diễn bằngu8<128.
Tốt hơn là bao gồm thông tin này trong chính mã. Trong trường hợp này, chúng tôi có thể giới thiệu 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
}
}
và sửa đổi mã cho phù hợp:
let mut letters = AsciiSet::new();
loop {
// ...
if letters.contains(letter) { /* ... /* }
// ...
letters.push(letter);
}
Kiểm tra ASCII
letter as u8cắt bớt ký tự nếu !letter.is_ascii(). Kiểm tra trường hợp này và nhắc người dùng tương ứng.