Hoàn thiện game Đoán số với Rust: Sử dụng Loop, Break và xử lý lỗi
Trong phần cuối cùng của series hướng dẫn Rust, chúng ta sẽ hoàn thiện trò chơi đoán số bằng cách thêm vòng lặp vô tận, điều kiện thoát khi chiến thắng và xử lý các đầu vào không hợp lệ một cách mượt mà.

Chào mừng bạn đến với phần cuối của loạt bài hướng dẫn xây dựng trò chơi đoán số với ngôn ngữ lập trình Rust. Trong bài viết này, chúng ta sẽ tập trung vào các khái niệm điều khiển luồng quan trọng để biến chương trình đơn lẻ thành một vòng lặp game hoàn chỉnh.
Dưới đây là những điểm kiến thức cốt lõi mà chúng ta sẽ khám phá:
- Vòng lặp vô tận với
loop - Thoát vòng lặp với
break - Bỏ qua lần lặp hiện tại với
continue - Ứng dụng linh hoạt của
match - Cách xử lý kiểu liệt kê (enum) và lỗi đầu vào
Mục tiêu của trò chơi
Trước khi đi vào chi tiết mã nguồn, hãy nhắc lại các yêu cầu mà game cần đạt được:
- Tạo ngẫu nhiên một số từ 1 đến 100.
- Nhắc người chơi nhập vào một con số để đoán.
- Sau khi người chơi đoán, chương trình sẽ thông báo số đó lớn hơn hay nhỏ hơn số bí mật.
- Quan trọng nhất: Tiếp tục yêu cầu người chơi đoán cho đến khi đúng. Nếu đoán đúng, in lời chúc mừng và thoát chương trình.
Triển khai mã nguồn
Bước 1: Thêm vòng lặp (Loop)
Ở phần trước, mã nguồn của chúng ta chỉ thực hiện quá trình đoán đúng một lần. Để game có thể chơi lại nhiều lần, chúng ta cần lặp lại các bước từ việc yêu cầu nhập, so sánh cho đến khi in ra kết quả.
Đoạn mã cần được thực hiện lặp lại bao gồm:
println!("Guess a number");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("Could not read the line");
let guess:u32 = guess.trim().parse().expect("Please enter a number");
println!("The number you guessed is:{}", guess);
match guess.cmp(&range_number){
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => println!("You win"),
}
Rust cung cấp từ khóa loop để tạo ra một vòng lặp vô tận. Cấu trúc của nó rất đơn giản:
loop {
// Mã lệnh bạn muốn lặp đi lặp lại mãi mãi
}
Bây giờ, hãy đặt toàn bộ logic xử lý đoán số vào bên trong khối loop này:
loop {
println!("Guess a number");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("Could not read the line");
let guess:u32 = guess.trim().parse().expect("Please enter a number");
println!("The number you guessed is:{}", guess);
match guess.cmp(&range_number){
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => println!("You win"),
}
}
Bước 2: Điều kiện thoát chương trình
Tuy nhiên, đoạn mã trên có một vấn đề lớn: nó sẽ yêu cầu người chơi nhập liệu mãi mãi và không bao giờ dừng lại. Về mặt logic, sau khi người chơi đoán đúng và chương trình in ra thông báo "You win", nó nên dừng lại.
Đây là lúc chúng ta cần đến từ khóa break, được dùng để thoát khỏi vòng lặp. Hãy thêm nó vào nhánh Ordering::Equal.
Lưu ý: Nếu bạn muốn thực thi nhiều dòng lệnh trong một nhánh của
match, bạn cần bọc chúng trong một cặp dấu ngoặc nhọn{}.
match guess.cmp(&range_number){
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => {
println!("You win");
break;
}
}
Bước 3: Xử lý đầu vào không hợp lệ
Vẫn còn một thiếu sót trong mã nguồn: nếu người chơi nhập một ký tự không phải là số (ví dụ: "abc"), hàm .parse() sẽ trả về lỗi Err. Khi .expect() nhận được lỗi này, toàn bộ chương trình sẽ sụp đổ (crash) ngay lập tức.
Logic đúng đắn ở đây应该是: nếu nhập sai, hãy in thông báo lỗi và yêu cầu người chơi nhập lại, chứ không dừng game.
Để làm điều này, chúng ta cần hiểu rằng .parse() trả về một enum type. Nếu chuyển đổi thành công, nó trả về Ok chứa nội dung đã chuyển đổi; nếu thất bại, nó trả về Err chứa lý do lỗi.
Chúng ta đã từng làm việc với enum Ordering ở bài trước và dùng match để xử lý các trường hợp. Tại đây, ta cũng dùng match để xử lý kết quả của .parse(): nếu thành công thì tiếp tục, nếu thất bại thì bỏ qua đoạn code dưới và chuyển sang lần lặp tiếp theo. Trong Rust, từ khóa để bỏ qua vòng lặp hiện tại là continue.
Hãy thay thế dòng code:
let guess:u32 = guess.trim().parse().expect("Please enter a number");
Bằng đoạn code sử dụng match sau:
let guess:u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
Giải thích chi tiết:
Ok(num) => num: Nhánh này xử lý khi chuyển đổi thành công.Oklà một biến thể của enum. Bên trong dấu ngoặc()sauOklà nội dung số đã chuyển đổi (u32). Việc viếtnumở đây có nghĩa là chúng ta gán nội dung đó cho biếnnum. Giá trị củanumsẽ được trả về làm kết quả của biểu thứcmatchvà gán choguess.Err(_) => continue: Nhánh này xử lý khi chuyển đổi thất bại.Errlà một biến thể khác. Dấu gạch dưới_bên trong()có nghĩa là chúng ta không quan tâm đến thông điệp lỗi cụ thể là gì, chỉ cần biết là có lỗi là đủ. Khi đó,continuesẽ được gọi để bắt đầu vòng lặp mới.
Việc sử dụng match thay vì .expect() để xử lý lỗi là một phương pháp rất phổ biến và idiomatically trong Rust.
Kết quả mã nguồn hoàn chỉnh
Dưới đây là toàn bộ mã nguồn của trò chơi sau khi đã hoàn thiện:
use std::io;
use rand::Rng;
use std::cmp::Ordering;
fn main() {
let range_number = rand::thread_rng().gen_range(1..101);
println!("Number Guessing Game");
loop {
println!("Guess a number");
let mut guess = String::new();
io::stdin().read_line(&mut guess).expect("Could not read the line");
let guess:u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("The number you guessed is:{}", guess);
match guess.cmp(&range_number){
Ordering::Less => println!("Too small"),
Ordering::Greater => println!("Too big"),
Ordering::Equal => {
println!("You win");
break;
},
}
}
println!("The secret number is: {}", range_number);
}
Khi chạy chương trình, bạn sẽ thấy game hoạt động trơn tru, cho phép đoán lại cho đến khi thắng và bỏ qua các đầu vào không phải là số.
Kết quả chạy chương trình
Chúc mừng bạn đã hoàn thành xong trò chơi đoán số cơ bản với Rust!
Bài viết liên quan

Phần mềm
Anthropic ra mắt Claude Opus 4.7: Nâng cấp mạnh mẽ cho lập trình nhưng vẫn thua Mythos Preview
16 tháng 4, 2026

Công nghệ
Qwen3.6-35B-A3B: Quyền năng Lập trình Agentic, Nay Đã Mở Cửa Cho Tất Cả
16 tháng 4, 2026

Công nghệ
Spotify thắng kiện 322 triệu USD từ nhóm pirate Anna's Archive nhưng đối mặt với bài toán thu hồi
16 tháng 4, 2026
