Rust Beginner: แบนแมตช์ที่ซ้อนกัน
นี่คือวิธีที่ฉันใช้เกมทายใจ - บทที่ 2 ของหนังสือ Rust: https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html
use std::io;
use std::io::Error;
use std::cmp::Ordering;
use std::num::ParseIntError;
use rand::Rng;
enum MyReadLineError {
FailReadLine(Error)
}
#[derive(Debug)]
enum MyReadU32Line {
FailReadLine(Error),
FailParse(ParseIntError)
}
fn my_read_line() -> Result<String, MyReadLineError> {
let mut input = String::new();
let result = io::stdin().read_line(&mut input);
match result {
Ok(_) => Ok(input),
Err(error ) => Err(MyReadLineError::FailReadLine(error)),
}
}
fn my_read_u32_line() -> Result<u32, MyReadU32Line> {
match my_read_line() {
Result::Ok(line) =>
match line.trim().parse::<u32>() {
Ok(value) => Ok(value),
Err(error) => Err(MyReadU32Line::FailParse(error)),
}
Result::Err(MyReadLineError::FailReadLine(error)) => Err(MyReadU32Line::FailReadLine(error)),
}
}
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
loop {
println!("Please input your guess.");
let guess = my_read_u32_line();
match guess {
Ok (value) => match value.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
},
}
Err (_) => println!("Sorry I couldn't read a u32 from your input! Please try again."),
}
}
}
สิ่งนี้ได้ผลตามที่คาดไว้ แต่ฉันต้องการทำให้การแข่งขันเรียบเพื่อไม่ให้ดูละเอียดเป็นไปได้ นอกจากนี้ยังมีวิธีอื่นใดที่จะทำให้โค้ดนั้นดูดีขึ้นอ่านง่ายขึ้น
คำตอบ
ยินดีต้อนรับสู่ Rust!
การจัดรูปแบบรหัส
มีบางอย่างที่ไม่สอดคล้องกันในการจัดรูปแบบของคุณ - ฉันได้เรียกใช้cargo fmtเพื่อกำจัดสิ่งเหล่านี้
การตั้งชื่อ
ไม่จำเป็นต้องใส่คำนำหน้าทุกอย่างด้วยMyหรือmy_- ใน Rust ชื่อของคุณจะไม่ขัดแย้งกับชื่อที่มีอยู่อย่างง่ายดายเช่นเดียวกับในภาษาอื่น ๆ
การจัดการข้อผิดพลาด
สำหรับแอปพลิเคชันฉันขอแนะนำให้ใช้anyhowลังเพื่อจัดการข้อผิดพลาดซึ่งจะช่วยลดจำนวนสำเร็จรูปได้มาก เพียงแค่เพิ่ม
anyhow = "1.0"
ไปที่[dependencies]ส่วนของCargo.tomlไฟล์.
ฟังก์ชันตัวช่วย
my_read_lineฟังก์ชั่นได้ง่ายกับ?ผู้ประกอบการ:
use anyhow::Result;
fn read_line() -> Result<String> {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(input)
}
my_read_u32_line สามารถทำให้ง่ายขึ้นในทำนองเดียวกัน:
fn read_u32() -> Result<u32> {
Ok(read_line()?.trim().parse()?)
}
ตัวเลขมหัศจรรย์
เราสามารถกำหนดค่าคงที่สำหรับช่วงของตัวเลข:
const MIN: u32 = 1;
const MAX: u32 = 100;
// later
let secret_number = rand::thread_rng().gen_range(MIN, MAX + 1);
องค์กร
ฉันอาจจัดระเบียบmainฟังก์ชันใหม่เพื่อลดการเยื้อง:
loop {
println!("Please input your guess.");
let guess = match read_u32() {
Ok(guess) => guess,
Err(_) => {
println!(
"Sorry I couldn't read a u32 from your input! \
Please try again."
);
continue;
}
};
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
};
}
ผลลัพธ์สุดท้าย
use anyhow::Result;
use rand::Rng;
use std::cmp::Ordering;
use std::io;
const MIN: u32 = 1;
const MAX: u32 = 100;
fn read_line() -> Result<String> {
let mut input = String::new();
io::stdin().read_line(&mut input)?;
Ok(input)
}
fn read_u32() -> Result<u32> {
Ok(read_line()?.trim().parse()?)
}
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(MIN, MAX + 1);
loop {
println!("Please input your guess.");
let guess = match read_u32() {
Ok(guess) => guess,
Err(_) => {
println!(
"Sorry I couldn't read a u32 from your input! \
Please try again."
);
continue;
}
};
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
};
}
}