🔄 Lặp Linh Hoạt - While Loops
Chào mừng đến với bài học về While Loops - lặp theo điều kiện trong Café Âu!
🎯 Món Ăn Hôm Nay
Tưởng tượng bạn là barista phục vụ khách:
- Pha cà phê cho đến khi hết khách → Không biết trước số khách
- Kiểm tra nhiệt độ nước → Đun cho đến khi đủ nóng (85°C)
- Phục vụ khách đến khi đóng cửa → Điều kiện: còn giờ làm việc
Đó chính là While Loop - lặp theo điều kiện, không cần biết trước số lần!
☕ While Loop Là Gì?
While Loop = Lặp khi còn điều kiện (làm đến khi hết việc)
// Pha cà phê cho đến khi hết khách
int khachDangCho = 10;
while (khachDangCho > 0) {
System.out.println("☕ Pha cho khách thứ " + khachDangCho);
khachDangCho--; // Giảm số khách chờ
}
Cấu trúc:
while (điều_kiện) {
// Công việc lặp lại
// Phải cập nhật điều kiện!
}
☕ Ẩn Dụ Café:
- while = "Trong khi còn..."
- điều_kiện = Còn khách chờ? Còn nguyên liệu? Còn giờ làm?
- {...} = Công việc phải làm
- Cập nhật điều kiện = Giảm khách chờ, dùng hết nguyên liệu
👨🍳 Câu Chuyện Trong Quán
Sáng nay, quán café đông khách bất ngờ:
Tình huống 1: Phục vụ hết khách chờ
int khachCho = 8;
System.out.println("🎯 Có " + khachCho + " khách đang chờ\n");
while (khachCho > 0) {
System.out.println("☕ Đang phục vụ khách...");
System.out.println(" Còn lại: " + (khachCho - 1) + " khách");
khachCho--;
}
System.out.println("\n✅ Đã phục vụ xong tất cả!");
Tình huống 2: Đun nước đến nhiệt độ phù hợp
int nhietDo = 20; // °C
int nhietDoMucTieu = 85;
System.out.println("🔥 Đang đun nước...\n");
while (nhietDo < nhietDoMucTieu) {
nhietDo += 5; // Tăng 5°C mỗi lần
System.out.printf("🌡️ Nhiệt độ hiện tại: %d°C\n", nhietDo);
}
System.out.println("\n✅ Nước đã đủ nóng!");
🎉 Kết quả: While loop giúp xử lý công việc linh hoạt theo điều kiện!
📝 Công Thức Nấu (Code Examples)
Ví Dụ 1: While Loop Cơ Bản
public class PhucVuKhach {
public static void main(String[] args) {
int soKhach = 5;
int khachDaPhucVu = 0;
System.out.println("☕ BẮT ĐẦU PHỤC VỤ:\n");
while (khachDaPhucVu < soKhach) {
khachDaPhucVu++;
System.out.println("✅ Khách " + khachDaPhucVu + ": Hoàn thành");
}
System.out.println("\n🎉 Đã phục vụ xong " + soKhach + " khách!");
}
}
Output:
☕ BẮT ĐẦU PHỤC VỤ:
✅ Khách 1: Hoàn thành
✅ Khách 2: Hoàn thành
✅ Khách 3: Hoàn thành
✅ Khách 4: Hoàn thành
✅ Khách 5: Hoàn thành
🎉 Đã phục vụ xong 5 khách!
Ví Dụ 2: Kiểm Tra Nguyên Liệu
public class KiemTraKho {
public static void main(String[] args) {
int caPhe = 500; // gram
int caPheMotLy = 18; // gram/ly
int lyDaPha = 0;
System.out.println("📦 Bắt đầu pha với " + caPhe + "g cà phê\n");
while (caPhe >= caPheMotLy) {
lyDaPha++;
caPhe -= caPheMotLy;
System.out.printf("☕ Ly %d: Pha xong (Còn %dg)\n",
lyDaPha, caPhe);
}
System.out.println("\n📊 TỔNG KẾT:");
System.out.println("✅ Đã pha: " + lyDaPha + " ly");
System.out.println("📦 Còn lại: " + caPhe + "g (không đủ)");
}
}
Output:
📦 Bắt đầu pha với 500g cà phê
☕ Ly 1: Pha xong (Còn 482g)
☕ Ly 2: Pha xong (Còn 464g)
☕ Ly 3: Pha xong (Còn 446g)
... (tiếp tục đến ly 27)
☕ Ly 27: Pha xong (Còn 14g)
📊 TỔNG KẾT:
✅ Đã pha: 27 ly
📦 Còn lại: 14g (không đủ)
Ví Dụ 3: Menu Tương Tác
import java.util.Scanner;
public class MenuQuanCafe {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
boolean dangMoCua = true;
int soLyDaBan = 0;
while (dangMoCua) {
System.out.println("\n☕ MENU QUÁN CAFÉ:");
System.out.println("1. Pha Latte");
System.out.println("2. Pha Cappuccino");
System.out.println("3. Xem thống kê");
System.out.println("4. Đóng cửa");
System.out.print("\nChọn (1-4): ");
int chon = scanner.nextInt();
switch (chon) {
case 1:
System.out.println("✅ Đã pha 1 ly Latte");
soLyDaBan++;
break;
case 2:
System.out.println("✅ Đã pha 1 ly Cappuccino");
soLyDaBan++;
break;
case 3:
System.out.println("📊 Số ly đã bán: " + soLyDaBan);
break;
case 4:
dangMoCua = false;
System.out.println("\n🔒 Đóng cửa quán!");
System.out.println("📊 Tổng cộng đã bán: " + soLyDaBan + " ly");
break;
default:
System.out.println("❌ Lựa chọn không hợp lệ!");
}
}
scanner.close();
}
}
Ví Dụ 4: Tìm Ước Số Chung Lớn Nhất (Euclidean)
public class TinhUSCLN {
public static void main(String[] args) {
// Ví dụ: Tính tỷ lệ cà phê/sữa chuẩn nhất
int caPhe = 48; // ml
int sua = 18; // ml
System.out.printf("🧮 Tìm tỷ lệ chuẩn cho %dml cà phê và %dml sữa\n\n",
caPhe, sua);
int a = caPhe;
int b = sua;
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
System.out.printf(" a=%d, b=%d\n", a, b);
}
System.out.println("\n✅ Ước số chung lớn nhất: " + a);
System.out.printf("📐 Tỷ lệ chuẩn: %d:%d (cà phê:sữa)\n",
caPhe / a, sua / a);
}
}
Output:
🧮 Tìm tỷ lệ chuẩn cho 48ml cà phê và 18ml sữa
a=18, b=12
a=12, b=6
a=6, b=0
✅ Ước số chung lớn nhất: 6
📐 Tỷ lệ chuẩn: 8:3 (cà phê:sữa)
Ví Dụ 5: Đếm Ngược Giờ Nghỉ
public class DemNguocGioNghi {
public static void main(String[] args) throws InterruptedException {
int gioNghi = 5; // phút
System.out.println("☕ Giờ nghỉ giải lao!\n");
while (gioNghi > 0) {
System.out.printf("⏰ Còn %d phút...\n", gioNghi);
Thread.sleep(1000); // Đợi 1 giây (giả lập)
gioNghi--;
}
System.out.println("\n🔔 Hết giờ nghỉ! Quay lại làm việc!");
}
}
🔥 Thực Hành Trong Quán
Bài Tập 1: Nhập Đơn Hàng Đến Khi Xong
import java.util.Scanner;
public class NhapDonHang {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int tongTien = 0;
int soLy = 0;
boolean tiepTuc = true;
System.out.println("☕ NHẬP ĐỐN HÀNG (Nhập 0 để kết thúc)\n");
while (tiepTuc) {
System.out.print("Giá 1 ly (VND): ");
int gia = scanner.nextInt();
if (gia == 0) {
tiepTuc = false;
} else {
tongTien += gia;
soLy++;
System.out.printf(" → Tạm tính: %,d VND (%d ly)\n\n",
tongTien, soLy);
}
}
System.out.println("━━━━━━━━━━━━━━━━━━━━━━");
System.out.printf("✅ Tổng cộng: %,d VND (%d ly)\n", tongTien, soLy);
scanner.close();
}
}
Bài Tập 2: Tìm Số Fibonacci
public class SoFibonacci {
public static void main(String[] args) {
// Ví dụ: Quy luật tăng giá theo tháng
int n = 10; // 10 tháng
int a = 0, b = 1;
int count = 0;
System.out.println("📈 QUY LUẬT TĂNG GIÁ (Fibonacci):\n");
while (count < n) {
System.out.printf("Tháng %2d: +%d VND\n", count + 1, a);
int next = a + b;
a = b;
b = next;
count++;
}
}
}
Bài Tập 3: Đảo Ngược Số
public class DaoNguocSo {
public static void main(String[] args) {
int soHoaDon = 12345;
int daoNguoc = 0;
System.out.println("🔢 Số hóa đơn gốc: " + soHoaDon);
System.out.println("🔄 Đang đảo ngược...\n");
int temp = soHoaDon;
while (temp > 0) {
int chuSo = temp % 10;
daoNguoc = daoNguoc * 10 + chuSo;
temp /= 10;
System.out.printf(" Bước: daoNguoc=%d, temp=%d\n",
daoNguoc, temp);
}
System.out.println("\n✅ Số đảo ngược: " + daoNguoc);
}
}
Output:
🔢 Số hóa đơn gốc: 12345
🔄 Đang đảo ngược...
Bước: daoNguoc=5, temp=1234
Bước: daoNguoc=54, temp=123
Bước: daoNguoc=543, temp=12
Bước: daoNguoc=5432, temp=1
Bước: daoNguoc=54321, temp=0
✅ Số đảo ngược: 54321
Bài Tập 4: Kiểm Tra Số Nguyên Tố
public class KiemTraSoNguyenTo {
public static void main(String[] args) {
int soKhach = 29; // Kiểm tra số khách
System.out.println("🔍 Kiểm tra " + soKhach + " có phải số nguyên tố?\n");
boolean laSoNguyenTo = true;
int i = 2;
while (i <= Math.sqrt(soKhach)) {
if (soKhach % i == 0) {
laSoNguyenTo = false;
System.out.println("❌ Chia hết cho " + i);
break;
}
i++;
}
if (laSoNguyenTo && soKhach > 1) {
System.out.println("✅ " + soKhach + " là số nguyên tố!");
} else {
System.out.println("❌ " + soKhach + " không phải số nguyên tố");
}
}
}
⚠️ Những Lỗi Barista Thường Gặp
Lỗi 1: Vòng Lặp Vô Hạn
// ❌ SAI: Quên cập nhật điều kiện
int khach = 10;
while (khach > 0) {
System.out.println("Phục vụ khách");
// Quên khach--; → Lặp vô hạn!
}
// ✅ ĐÚNG: Phải cập nhật điều kiện
int khach = 10;
while (khach > 0) {
System.out.println("Phục vụ khách");
khach--; // Giảm số khách
}
Lỗi 2: Điều Kiện Ban Đầu Sai
// ❌ SAI: Điều kiện đã sai từ đầu
int khach = 0;
while (khach > 0) { // 0 > 0 là false → không chạy!
System.out.println("Phục vụ");
khach--;
}
// ✅ ĐÚNG: Kiểm tra điều kiện ban đầu
int khach = 5;
while (khach > 0) { // 5 > 0 là true → chạy được
System.out.println("Phục vụ");
khach--;
}
Lỗi 3: Thay Đổi Biến Điều Kiện Sai Hướng
// ❌ SAI: Tăng thay vì giảm
int khach = 10;
while (khach > 0) {
System.out.println("Phục vụ");
khach++; // Sai! khach càng lúc càng lớn
}
// ✅ ĐÚNG: Giảm đúng hướng
int khach = 10;
while (khach > 0) {
System.out.println("Phục vụ");
khach--; // Đúng! Giảm dần về 0
}
Lỗi 4: Điều Kiện Phức Tạp Sai Logic
// ❌ SAI: Logic sai
int caPhe = 100;
int sua = 50;
while (caPhe > 0 || sua < 0) { // sua < 0 luôn false!
System.out.println("Pha");
caPhe -= 18;
}
// ✅ ĐÚNG: Logic đúng
int caPhe = 100;
int sua = 50;
while (caPhe >= 18 && sua >= 100) { // Cả 2 đều đủ
System.out.println("Pha Latte");
caPhe -= 18;
sua -= 100;
}
💡 Bí Quyết Của Barista
- Luôn có điều kiện dừng: Tránh vòng lặp vô hạn
- Cập nhật biến điều kiện: Đảm bảo điều kiện thay đổi
- Kiểm tra điều kiện ban đầu: Có thể không chạy lần nào
- Dùng while khi không biết số lần: For khi biết trước
- Break để thoát sớm: Khi gặp điều kiện đặc biệt
🎓 Bạn Đã Học Được
- ✅ While loop = Lặp theo điều kiện (không biết trước số lần)
- ✅ while (điều_kiện) = Kiểm tra trước mỗi lần lặp
- ✅ Phải cập nhật điều kiện = Tránh vòng lặp vô hạn
- ✅ Dùng khi: Không biết số lần, có điều kiện dừng
- ✅ Khác for: For biết trước số lần, while linh hoạt hơn
☕ Món Tiếp Theo
Đã biết lặp theo điều kiện! Giờ học lặp ít nhất 1 lần:
👉 Lặp Sau Kiểm Tra - Do-While Loops
💡 Lời Khuyên Cuối: While loop giống phục vụ khách - làm đến khi hết việc, không cần đếm! Luôn nhớ cập nhật điều kiện để không bị lặp vô hạn!