Nguyễn Đình Cường
0 comment
09 Nov, 2026
Muốn biết mình đã hiểu vòng lặp và câu lệnh điều kiện chưa, hãy thử viết một trò chơi. Game đoán số là bài tập nhỏ nhưng "đủ vị": máy chọn ngẫu nhiên một số, người chơi đoán, máy gợi ý lớn hơn hay nhỏ hơn cho đến khi trúng.
Chương trình chọn bí mật một số nguyên từ 1 đến 100. Người chơi có tối đa 7 lượt. Sau mỗi lần đoán, chương trình báo "cao quá", "thấp quá" hoặc chúc mừng. Hết lượt mà chưa đoán đúng thì thua và hiện đáp án. Số 7 không phải ngẫu nhiên: với mỗi lần đoán chia đôi khoảng còn lại, 7 lượt là đủ để tìm ra mọi số từ 1 đến 100, đó chính là ý tưởng của tìm kiếm nhị phân.
Hãy bắt đầu bằng thứ chạy được, rồi cải tiến dần. Đây là phiên bản đầu tiên:
import random
secret = random.randint(1, 100)
max_tries = 7
print("Mình đang nghĩ một số từ 1 đến 100. Bạn có", max_tries, "lượt đoán.")
for attempt in range(1, max_tries + 1):
guess = int(input(f"Lượt {attempt}: "))
if guess == secret:
print("Chính xác! Bạn thắng sau", attempt, "lượt.")
break
elif guess < secret:
print("Số bạn đoán nhỏ quá.")
else:
print("Số bạn đoán lớn quá.")
else:
print("Hết lượt! Đáp án là", secret)Có hai điểm thú vị. Hàm random.randint(1, 100) chọn số nguyên ngẫu nhiên, bao gồm cả hai đầu mút. Khối else gắn với vòng for là một đặc điểm hay của Python: nó chỉ chạy khi vòng lặp kết thúc bình thường mà không gặp break, tức là người chơi chưa đoán trúng.
Thử gõ chữ "abc" vào chương trình trên, nó sẽ báo lỗi ValueError và dừng đột ngột. Chương trình thực tế không nên như vậy. Ta dùng try/except để bắt lỗi và cho nhập lại, đồng thời không tính lượt oan:
def read_number(prompt, low, high):
while True:
text = input(prompt)
try:
value = int(text)
except ValueError:
print("Vui lòng nhập một số nguyên.")
continue
if value < low or value > high:
print(f"Số phải nằm trong khoảng {low} đến {high}.")
continue
return valueHàm này lặp đến khi nhận được số hợp lệ. Việc tách thành hàm giúp code chính gọn hơn và dễ tái sử dụng.
import random
def read_number(prompt, low, high):
while True:
try:
value = int(input(prompt))
except ValueError:
print("Vui lòng nhập một số nguyên.")
continue
if low <= value <= high:
return value
print(f"Số phải nằm trong khoảng {low} đến {high}.")
def play(low=1, high=100, max_tries=7):
secret = random.randint(low, high)
print(f"Mình đang nghĩ một số từ {low} đến {high}. Bạn có {max_tries} lượt.")
for attempt in range(1, max_tries + 1):
guess = read_number(f"Lượt {attempt}/{max_tries}: ", low, high)
if guess == secret:
print(f"Chính xác! Bạn thắng sau {attempt} lượt.")
return True
print("Nhỏ quá." if guess < secret else "Lớn quá.")
print("Hết lượt! Đáp án là", secret)
return False
def main():
wins = games = 0
while True:
games += 1
wins += play()
print(f"Thắng {wins}/{games} ván.")
again = input("Chơi tiếp? (c/k): ").strip().lower()
if again != "c":
print("Hẹn gặp lại!")
break
if __name__ == "__main__":
main()Chú ý biểu thức low : Python cho phép so sánh liên tiếp rất tự nhiên. Và wins += play() hoạt động vì giá trị True tính như 1 còn False như 0, tuy nhiên nếu thấy khó đọc bạn có thể viết rõ ràng bằng if.
Giả sử số bí mật nằm trong khoảng 1 đến 100. Nếu bạn luôn đoán số ở giữa khoảng còn lại, mỗi câu trả lời "lớn quá" hoặc "nhỏ quá" loại bỏ đúng một nửa khả năng. Từ 100 khả năng, sau một lượt còn khoảng 50, rồi 25, 12, 6, 3, 2, 1. Vậy tối đa khoảng 7 lượt là tìm ra đáp án. Đó là ý tưởng của thuật toán tìm kiếm nhị phân, một thuật toán kinh điển trong khoa học máy tính. Bạn có thể tự viết hàm cho máy đoán số của người chơi theo đúng cách này: giữ hai biến low và high, đoán (low + high) // 2, rồi thu hẹp khoảng theo phản hồi. Thử đếm số lượt máy cần với nhiều số bí mật khác nhau để thấy thuật toán hoạt động hiệu quả thế nào.
Qua trò chơi nhỏ này, bạn đã dùng biến, for, while, if/elif/else, hàm, xử lý ngoại lệ và module random. Quan trọng hơn là thói quen làm từng bước: có bản chạy được trước, rồi mới xử lý lỗi, tách hàm và thêm tính năng.
Nếu bạn muốn học Python từ nền tảng đến các dự án lớn hơn, hãy xem các khóa học tại codebem.com.
Nguyễn Đình Cường
0 comment