Chuyển tới nội dung chính

🔄 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

  1. Luôn có điều kiện dừng: Tránh vòng lặp vô hạn
  2. Cập nhật biến điều kiện: Đảm bảo điều kiện thay đổi
  3. Kiểm tra điều kiện ban đầu: Có thể không chạy lần nào
  4. Dùng while khi không biết số lần: For khi biết trước
  5. 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!