Mảng bổ trợ cho người mới: 10 bài rèn phản xạ
Mỗi bài một kỹ năng nhỏ, đi nhanh theo 4 bước: đề nói gì, ý tưởng, code mổ 1–2 dòng chốt, bẫy. Hết 10 bài là đủ phản xạ vòng lặp + mảng đi thi.
Bài 1. BinhPhuong — tách hàm con
Nhập 10, in Binh phuong cua 10 la: 100.
Bài đầu tiên dạy tách hàm: binhPhuong(x) lo tính (return x * x),
main lo gọi và in. Hàm static nên gọi thẳng tên không cần object.
Tự luyện: thêm lapPhuong(x).
Bài 2. BoiSoCua5 — vòng lặp sinh dãy
In 5 10 ... 50: 5 * i với i từ 1 đến 10.
Muốn bội của k thì thay 5 bằng k; muốn n số thì thay 10 bằng n.
Chú ý System.out.print (không xuống dòng) + cách ở cuối mỗi số,
in xong một println() trắng để xuống dòng.
Bẫy: i bắt đầu từ 0 thì số đầu ra 0. Tự luyện: in bội của 7 tới 70.
Bài 3. MuoiNguyenTo — while khi chưa biết số lần lặp
Đếm đủ 10 số nguyên tố thì dừng, ra 2 3 5 7 11 13 17 19 23 29.
for dùng khi biết trước số lần, while (dem < 10) dùng khi
chưa biết phải xét tới số mấy (ở đây tới 29).
Hai biến chạy song song: so xét tiếp, dem đếm đã đủ.
Dùng lại hàm laNguyenTo Lab 01 — đừng viết lại.
Bẫy: quên so++ là vòng lặp vô hạn, máy treo.
Tự luyện: in 10 số nguyên tố đầu tiên lớn hơn 100.
Bài 4. NhapTen — đọc cả dòng
sc.nextLine() đọc cả dòng kể cả dấu cách.
Bẫy kinh điển: sau nextInt() mà gọi nextLine() ngay thì nó hứng
phím Enter thừa, ra chuỗi rỗng. Cách chữa: gọi một nextLine() trắng
nuốt Enter rồi mới đọc thật. sc.next() chỉ đọc 1 từ (dừng ở cách) —
đọc tên người phải nextLine.
Tự luyện: nhập họ và tên riêng rồi in Ten: <tên>, Ho: <họ>.
Bài 5. ThuTrongTuan — switch nhiều nhánh
Số 1–7 thành Monday–Sunday, số khác default báo Khong hop le.
Nhập 8 → default. Mỗi case vẫn phải break (xem bài DocSo).
switch hợp khi mỗi giá trị một việc; nhiều việc phức tạp thì if-else rõ hơn.
Tự luyện: số 1–12 thành tháng January–December.
Bài 6. ChanLe — chia dư và số âm
n % 2 == 0 là chẵn, còn lại lẻ. Nhớ: 0 là chẵn;
số âm vẫn đúng (-3 % 2 bằng -1, khác 0 nên lẻ).
Nhập 7 → 7 la so le, 0 → 0 la so chan, -3 → -3 la so le.
Bẫy: n % 2 == 1 để bắt số lẻ — số âm lẻ cho dư -1, lọt lưới.
Luôn so chẵn (== 0), còn lại là lẻ.
Tự luyện: đếm chẵn lẻ trong n số nhập vào.
Bài 7. NguyenAm — gom nhiều case một nhánh
s.charAt(0) lấy ký tự đầu chuỗi, Character.toLowerCase
đổi thường để bắt cả E. Năm case a/e/i/o/u xếp chồng không
break giữa để cùng rơi vào một nhánh in — lần hiếm hoi rơi nhánh
có chủ đích (bài DocSo đã dặn luôn break, đây là ngoại lệ).
e → You have input, Vowel, b → This is not a Vowel.
Bẫy: quên break ở nhánh Vowel thì in cả 2 dòng.
Tự luyện: thêm y là nguyên âm khi có cờ --y-la-nguyen-am? Không —
hãy đếm số nguyên âm trong cả một câu nhập vào.
Bài 8. CapBangNhau — so phần tử kề
Đếm cặp a[i] == a[i+1]. Vòng chạy tới n - 2 để a[i+1]
không vượt mảng — giống hệt lý do n - 1 - i ở nổi bọt.
Dãy 1 1 2 2 2 3 4 4: cặp ở vị trí (0,1), (1,2)? Không:
a[1]=1, a[2]=2 khác nhau. Các cặp đúng: (0,1), (2,3), (3,4), (6,7)
→ 4 cặp. Khớp output mẫu. Ít hơn 2 phần tử thì báo ngay từ đầu.
Bẫy: vòng tới n - 1 rồi so a[i+1] là tràn mảng ở cuối.
Tự luyện: đếm bộ ba bằng nhau liên tiếp.
Bài 9. KhongNhoHonTruoc — giữ max đã thấy
In các số >= mọi số trước nó. Giữ maxTruoc, gặp số không nhỏ hơn
thì in và cập nhật max. Số đầu tiên luôn được in (chưa có ai trước nó).
Dãy 3 1 4 1 5 9 2 6: 3 (in) → 1 (bỏ) → 4 ≥ 3 (in) → 1 (bỏ) →
5 (in) → 9 (in) → 2, 6 (bỏ) → 3 4 5 9. Khớp output mẫu.
Dấu >= (không phải >) nên số bằng max vẫn được in.
n phải trong 2..50, ngoài thì báo (bài này chặn 2 đầu).
Tự luyện: in các số nhỏ hơn mọi số trước nó (giữ min).
Bài 10. MaTranDonVi — vòng lặp lồng nhau
Ma trận là mảng 2 chiều int[n][n]: hàng i, cột j.
Nhập và xét đều bằng vòng lặp lồng nhau (ngoài hàng, trong cột).
Cờ ok bắt đầu true, gặp ô khác 0/1 thì hạ cờ + break thoát vòng trong;
điều kiện vòng ngoài i < n && ok để thoát luôn vòng ngoài
(hai tầng break phối hợp). n <= 0 báo lỗi trước khi cấp phát.
Ma trận 1 0 / 0 2 có số 2 → Khong phai ma tran 0/1;
n = 0 → n phai > 0. Khớp các ca test.
Bẫy: break một mình chỉ thoát vòng trong, vòng ngoài vẫn chạy —
muốn dừng hẳn phải thêm cờ vào điều kiện vòng ngoài như code mẫu.
Tự luyện: kiểm tra ma trận đơn vị thật (chéo chính bằng 1, còn lại 0).
Phụ lục OOP: khi nào static là đủ, khi nào cần object
10 bài này toàn static — vì sao vẫn đúng
Mọi hàm ở đây (binhPhuong, laNguyenTo) đều static:
nhận vào, trả ra, không nhớ gì giữa các lần gọi.
Dữ liệu (mảng, số) nằm ở main, hàm chỉ mượn dùng.
Kiểu code này gọi là thủ tục — đơn giản, dễ đúng,
và là đáp án đúng cho bài nhỏ.
Dấu hiệu phải lên object
- Dữ liệu đi cùng nhau mọi lúc: tử luôn đi với mẫu (→ lớp
PS), tên-sinh-nhật-điểm luôn đi cùng nhau (→ lớpSV). - Luật gắn với dữ liệu: "mẫu không được 0", "điểm 0..10" phải theo sát dữ liệu đi khắp chương trình (→ setter gác cổng).
- Nhiều loại chung một danh sách: Thư lẫn Bưu kiện (→ đa hình).
Viết lại 1 bài mảng theo OOP để cảm nhận
Bài cặp bằng nhau viết thủ tục đã xong, nhưng gói thành lớp thì dùng lại được:
public class DaySo {
private int[] a; // dữ liệu sống cùng luật
public DaySo(int[] a) { this.a = a; }
public int demCapBangNhau() { ... } // việc của dãy số
public int demNguyenTo() { ... } // thêm việc mới không sửa main
}
main khi đó chỉ còn: đúc DaySo, gọi 2 hàm, in.
So với 10 bài static: thêm 1 lớp, đổi lại mỗi kỹ năng mới
là một phương thức thêm vào, main không phình.
Đó chính là con đường từ Lab 01 (static) tới Lab 02–05 (object).