Python – Module 8 – Dự án cuối khóa – Game phiêu lưu 🏆
Bạn đã vượt qua tất cả thử thách để đến được trùm cuối! Bạn đã học về Biến, If/Else, Vòng lặp, List, và Hàm. Giờ là lúc tháo bánh xe phụ và ghép tất cả mảnh ghép ấy lại với nhau.
Trong module này, bạn sẽ tự tay xây dựng Game Phiêu Lưu Văn Bản của riêng mình!
1. Game phiêu lưu văn bản là gì?
Game phiêu lưu văn bản (Text-Based Adventure hay “Choose Your Own Adventure”) là loại game mà máy tính mô tả khung cảnh, tình huống cho bạn bằng chữ, còn bạn thì gõ lệnh để tương tác với thế giới trong game.
Không có đồ họa. Toàn bộ câu chuyện diễn ra trong trí tưởng tượng của bạn – giống như đọc một cuốn truyện mà bạn là nhân vật chính!
Ví dụ một màn chơi:
Bạn tỉnh dậy trong một tòa lâu đài tối tăm, lạnh lẽo.
❤️ Máu: 100
🎒 Túi đồ: (trống)
Trước mặt bạn là hai cánh cửa:
▸ Cánh cửa GỖ bên TRÁI — có ánh sáng le lói
▸ Cánh cửa SẮT bên PHẢI — vọng ra tiếng gầm gừ
Bạn làm gì? (trái / phải)
> trái
✅ Bạn mở cánh cửa gỗ và tìm thấy một Rương Kho Báu!
🗝️ Bạn mở rương và nhận được: ⚔️ Kiếm Ma Thuật
⚔️ Kiếm Ma Thuật đã được thêm vào túi đồ!
2. Yêu cầu dự án
Để hoàn thành dự án này, code của bạn phải sử dụng ít nhất một lần mỗi khái niệm chính đã học trong toàn khóa. Đây là danh sách kiểm tra:
- ✅ Biến (Variables): Để theo dõi chỉ số người chơi. Tạo biến cho ten_nguoi_choi, mau, v.v. — tất cả đều phải có type hint!
- ✅ List: Làm túi đồ cho người chơi. Khởi tạo list rỗng: tui_do: list = []
- ✅ Vòng lặp while: Giữ game chạy liên tục cho đến khi người chơi thắng hoặc chết (máu ≤ 0).
- ✅ if / elif / else: Rẽ nhánh câu chuyện. Hỏi người chơi bằng input(), rồi kiểm tra họ gõ gì — “trái”, “phải”, “đánh”, “chạy”, v.v.
- ✅ Hàm (Functions): Tạo ít nhất ba hàm với đầy đủ type hints. Ví dụ: def game_over() -> None:, def tim_kho_bau(tui_do: list) -> list:, def tan_cong_quai(mau_nguoi_choi: int, mau_quai: int) -> int:
- ✅ Type hints: Mọi hàm phải có kiểu tham số và kiểu trả về. Mọi biến nên có type hint.
3. Hướng dẫn xây dựng từng bước
Bước 1: Khởi Tạo Game (Setup)
# --- BƯỚC 1: KHỞI TẠO GAME ---
print("=" * 40)
print("🏰 CHÀO MỪNG ĐẾN VỚI HẦM NGỤC BÓNG TỐI 🏰")
print("=" * 40)
ten_nguoi_choi: str = input("👤 Người chơi, tên bạn là gì? ")
mau: int = 100
tui_do: list = []
game_dang_chay: bool = True
so_phong_da_qua: int = 0
print(f"\n📜 {ten_nguoi_choi}, hãy cố gắng thoát khỏi hầm ngục!\n")
Bước 2: Viết Các Hàm Dùng Chung
Tạo các hàm để tái sử dụng xuyên suốt game. Nhớ type hints!
# --- BƯỚC 2: CÁC HÀM DÙNG CHUNG ---
def game_over(ten: str, tui: list) -> None:
"""Kết thúc game và in tóm tắt."""
print("\n" + "=" * 40)
print("💀 GAME OVER 💀")
print("=" * 40)
print(f"{ten} đã ngã xuống với {len(tui)} vật phẩm trong túi đồ:")
for vat_pham in tui:
print(f" ▸ {vat_pham}")
print("=" * 40)
def chien_thang(ten: str, tui: list) -> None:
"""Người chơi chiến thắng!"""
print("\n" + "=" * 40)
print("🏆 CHIẾN THẮNG! 🏆")
print("=" * 40)
print(f"🌟 {ten} đã thoát khỏi hầm ngục thành công!")
print(f"🎒 Với {len(tui)} vật phẩm quý giá:")
for vat_pham in tui:
print(f" ▸ {vat_pham}")
print("=" * 40)
def hien_thi_trang_thai(ten: str, mau_hien_tai: int, tui: list, phong: int) -> None:
"""In trạng thái hiện tại của người chơi."""
print("\n" + "-" * 30)
print(f"👤 {ten}")
print(f"❤️ Máu: {mau_hien_tai}/100")
print(f"🎒 Túi đồ: {tui if len(tui) > 0 else '(trống)'}")
print(f"🚪 Phòng đã qua: {phong}")
print("-" * 30)
def nhan_sat_thuong(mau_hien_tai: int, sat_thuong: int) -> int:
"""Trừ máu và trả về lượng máu mới."""
mau_moi: int = mau_hien_tai - sat_thuong
print(f"💔 Bạn nhận {sat_thuong} sát thương! (Máu còn: {mau_moi})")
return mau_moi
def hoi_mau(mau_hien_tai: int, luong_hoi: int) -> int:
"""Hồi máu và trả về lượng máu mới."""
mau_moi: int = mau_hien_tai + luong_hoi
if mau_moi > 100:
mau_moi = 100
print(f"💚 Bạn hồi {luong_hoi} máu! (Máu hiện tại: {mau_moi})")
return mau_moi
Bước 3: Vòng Lặp Chính Của Game
Đây là trái tim của game — nơi mọi thứ diễn ra!
# --- BƯỚC 3: VÒNG LẶP CHÍNH ---
while game_dang_chay:
hien_thi_trang_thai(ten_nguoi_choi, mau, tui_do, so_phong_da_qua)
# --- PHÒNG 1: Hành Lang Tối ---
if so_phong_da_qua == 0:
print("\n🌑 Bạn đang đứng trong một hành lang tối tăm.")
print("Có hai cánh cửa:")
print(" ▸ Cửa GỖ bên TRÁI — có ánh sáng le lói")
print(" ▸ Cửa SẮT bên PHẢI — vọng ra tiếng gầm gừ")
lua_chon: str = input("👉 Bạn chọn cửa nào? (trái / phải): ").strip().lower()
if lua_chon == "trái":
print("\n✅ Bạn mở cửa gỗ và tìm thấy một Rương Kho Báu!")
print("🗝️ Trong rương có một ⚔️ Kiếm Ma Thuật!")
tui_do.append("⚔️ Kiếm Ma Thuật")
so_phong_da_qua = 1
elif lua_chon == "phải":
print("\n⚠️ Bạn mở cửa sắt và đối mặt với một con SÓI HOANG!")
mau = nhan_sat_thuong(mau, 20)
if mau <= 0:
game_over(ten_nguoi_choi, tui_do)
game_dang_chay = False
else:
so_phong_da_qua = 1
else:
print("\n❓ Ta không hiểu lệnh đó. Hãy gõ 'trái' hoặc 'phải'.")
# --- PHÒNG 2: Căn Phòng Bí Ẩn ---
elif so_phong_da_qua == 1:
print("\n🔮 Bạn bước vào một căn phòng tròn, trên tường khắc đầy chữ rune.")
print("Giữa phòng có một BỆ ĐÁ với ba vật phẩm:")
print(" ▸ 🧪 Bình Máu")
print(" ▸ 🗝️ Chìa Khóa Bạc")
print(" ▸ 🛡️ Khiên Gỗ")
print("⚠️ Nhưng bạn chỉ được chọn MỘT!")
lua_chon = input("👉 Bạn chọn gì? (máu / khóa / khiên): ").strip().lower()
if lua_chon == "máu":
print("\n🧪 Bạn nhặt Bình Máu! (+25 máu)")
mau = hoi_mau(mau, 25)
tui_do.append("🧪 Bình Máu")
so_phong_da_qua = 2
elif lua_chon == "khóa":
print("\n🗝️ Bạn nhặt Chìa Khóa Bạc!")
tui_do.append("🗝️ Chìa Khóa Bạc")
so_phong_da_qua = 2
elif lua_chon == "khien":
print("\n🛡️ Bạn nhặt Khiên Gỗ!")
tui_do.append("🛡️ Khiên Gỗ")
so_phong_da_qua = 2
else:
print("\n❓ Vật phẩm không hợp lệ. Hãy chọn: máu / khóa / khiên.")
# --- PHÒNG 3: Cửa Khóa ---
elif so_phong_da_qua == 2:
print("\n🚪 Bạn đến trước một cánh cửa lớn bằng bạc, có ổ khóa lấp lánh.")
if "🗝️ Chìa Khóa Bạc" in tui_do:
print("🔑 Bạn tra chìa khóa bạc vào ổ... CÁNH CỬA MỞ RA!")
print("✨ Đằng sau cánh cửa là ÁNH SÁNG MẶT TRỜI!")
print("🏃 Bạn chạy thật nhanh về phía tự do...")
so_phong_da_qua = 3
else:
print("🔒 Cửa bị khóa! Bạn cần Chìa Khóa Bạc để mở.")
print("↩️ Bạn phải quay lại tìm chìa khóa...")
so_phong_da_qua = 1 # Quay lại phòng 2
# --- THOÁT KHỎI HẦM NGỤC ---
elif so_phong_da_qua == 3:
chien_thang(ten_nguoi_choi, tui_do)
game_dang_chay = False
# --- KIỂM TRA MÁU ---
if mau <= 0:
game_over(ten_nguoi_choi, tui_do)
game_dang_chay = False
4. Toàn bộ code mẫu hoàn chỉnh
Dưới đây là toàn bộ code ghép lại từ các bước trên. Hãy copy-paste vào file .py và chạy thử!
# ============================================================
# 🏰 GAME PHIÊU LƯU VĂN BẢN: HẦM NGỤC BÓNG TỐI
# Dự án cuối khóa Python
# ============================================================
# --- KHỞI TẠO ---
print("=" * 40)
print("🏰 CHÀO MỪNG ĐẾN VỚI HẦM NGỤC BÓNG TỐI 🏰")
print("=" * 40)
ten_nguoi_choi: str = input("👤 Người chơi, tên bạn là gì? ")
mau: int = 100
tui_do: list = []
game_dang_chay: bool = True
so_phong_da_qua: int = 0
print(f"\n📜 {ten_nguoi_choi}, hãy cố gắng thoát khỏi hầm ngục!\n")
# --- HÀM ---
def game_over(ten: str, tui: list) -> None:
"""Kết thúc game và in tóm tắt."""
print("\n" + "=" * 40)
print("💀 GAME OVER 💀")
print("=" * 40)
print(f"{ten} đã ngã xuống với {len(tui)} vật phẩm trong túi đồ:")
for vat_pham in tui:
print(f" ▸ {vat_pham}")
print("=" * 40)
def chien_thang(ten: str, tui: list) -> None:
"""Người chơi chiến thắng!"""
print("\n" + "=" * 40)
print("🏆 CHIẾN THẮNG! 🏆")
print("=" * 40)
print(f"🌟 {ten} đã thoát khỏi hầm ngục thành công!")
print(f"🎒 Với {len(tui)} vật phẩm quý giá:")
for vat_pham in tui:
print(f" ▸ {vat_pham}")
print("=" * 40)
def hien_thi_trang_thai(ten: str, mau_hien_tai: int, tui: list, phong: int) -> None:
"""In trạng thái hiện tại của người chơi."""
print("\n" + "-" * 30)
print(f"👤 {ten}")
print(f"❤️ Máu: {mau_hien_tai}/100")
print(f"🎒 Túi đồ: {tui if len(tui) > 0 else '(trống)'}")
print(f"🚪 Phòng đã qua: {phong}")
print("-" * 30)
def nhan_sat_thuong(mau_hien_tai: int, sat_thuong: int) -> int:
"""Trừ máu và trả về lượng máu mới."""
mau_moi: int = mau_hien_tai - sat_thuong
print(f"💔 Bạn nhận {sat_thuong} sát thương! (Máu còn: {mau_moi})")
return mau_moi
def hoi_mau(mau_hien_tai: int, luong_hoi: int) -> int:
"""Hồi máu và trả về lượng máu mới."""
mau_moi: int = mau_hien_tai + luong_hoi
if mau_moi > 100:
mau_moi = 100
print(f"💚 Bạn hồi {luong_hoi} máu! (Máu hiện tại: {mau_moi})")
return mau_moi
# --- VÒNG LẶP CHÍNH ---
while game_dang_chay:
hien_thi_trang_thai(ten_nguoi_choi, mau, tui_do, so_phong_da_qua)
# Phòng 0: Hành Lang Tối
if so_phong_da_qua == 0:
print("\n🌑 Bạn đang đứng trong một hành lang tối tăm.")
print("Có hai cánh cửa:")
print(" ▸ Cửa GỖ bên TRÁI — có ánh sáng le lói")
print(" ▸ Cửa SẮT bên PHẢI — vọng ra tiếng gầm gừ")
lua_chon: str = input("👉 Bạn chọn cửa nào? (trái / phải): ").strip().lower()
if lua_chon == "trái":
print("\n✅ Bạn mở cửa gỗ và tìm thấy một Rương Kho Báu!")
print("🗝️ Trong rương có một ⚔️ Kiếm Ma Thuật!")
tui_do.append("⚔️ Kiếm Ma Thuật")
so_phong_da_qua = 1
elif lua_chon == "phải":
print("\n⚠️ Bạn mở cửa sắt và đối mặt với một con SÓI HOANG!")
mau = nhan_sat_thuong(mau, 20)
if mau <= 0:
game_over(ten_nguoi_choi, tui_do)
game_dang_chay = False
else:
so_phong_da_qua = 1
else:
print("\n❓ Ta không hiểu lệnh đó. Hãy gõ 'trái' hoặc 'phải'.")
# Phòng 1: Căn Phòng Bí Ẩn
elif so_phong_da_qua == 1:
print("\n🔮 Bạn bước vào một căn phòng tròn, trên tường khắc đầy chữ rune.")
print("Giữa phòng có một BỆ ĐÁ với ba vật phẩm:")
print(" ▸ 🧪 Bình Máu")
print(" ▸ 🗝️ Chìa Khóa Bạc")
print(" ▸ 🛡️ Khiên Gỗ")
print("⚠️ Nhưng bạn chỉ được chọn MỘT!")
lua_chon = input("👉 Bạn chọn gì? (máu / khóa / khiên): ").strip().lower()
if lua_chon == "máu":
print("\n🧪 Bạn nhặt Bình Máu! (+25 máu)")
mau = hoi_mau(mau, 25)
tui_do.append("🧪 Bình Máu")
so_phong_da_qua = 2
elif lua_chon == "khóa":
print("\n🗝️ Bạn nhặt Chìa Khóa Bạc!")
tui_do.append("🗝️ Chìa Khóa Bạc")
so_phong_da_qua = 2
elif lua_chon == "khien":
print("\n🛡️ Bạn nhặt Khiên Gỗ!")
tui_do.append("🛡️ Khiên Gỗ")
so_phong_da_qua = 2
else:
print("\n❓ Vật phẩm không hợp lệ. Hãy chọn: máu / khóa / khiên.")
# Phòng 2: Cửa Khóa
elif so_phong_da_qua == 2:
print("\n🚪 Bạn đến trước một cánh cửa lớn bằng bạc, có ổ khóa lấp lánh.")
if "🗝️ Chìa Khóa Bạc" in tui_do:
print("🔑 Bạn tra chìa khóa bạc vào ổ... CÁNH CỬA MỞ RA!")
print("✨ Đằng sau cánh cửa là ÁNH SÁNG MẶT TRỜI!")
print("🏃 Bạn chạy thật nhanh về phía tự do...")
so_phong_da_qua = 3
else:
print("🔒 Cửa bị khóa! Bạn cần Chìa Khóa Bạc để mở.")
print("↩️ Bạn phải quay lại tìm chìa khóa...")
so_phong_da_qua = 1
# Phòng 3: Thoát!
elif so_phong_da_qua == 3:
chien_thang(ten_nguoi_choi, tui_do)
game_dang_chay = False
# Kiểm tra máu sau mỗi lượt
if mau <= 0:
game_over(ten_nguoi_choi, tui_do)
game_dang_chay = False
5. Mở rộng Thế Giới Game (Thử thách nâng cao)
Khi code mẫu đã chạy ổn định, hãy thử thêm những tính năng dưới đây để biến game thành của riêng bạn!
🔥 Thử thách 1: Trận Đánh Trùm
Tạo một phòng nơi người chơi phải đánh bại trùm bằng cách gõ “đánh” nhiều lần.
def danh_trum(mau_nguoi_choi: int, tui: list) -> int:
"""Trận đánh với trùm hầm ngục. Trả về máu còn lại."""
mau_trum: int = 50
co_khieng: bool = "🛡️ Khiên Gỗ" in tui
co_kiem: bool = "⚔️ Kiếm Ma Thuật" in tui
print("\n🐉 Một con RỒNG LỬA xuất hiện!")
print(f"❤️ Máu Rồng: {mau_trum}")
while mau_trum > 0 and mau_nguoi_choi > 0:
hanh_dong: str = input("👉 Bạn làm gì? (đánh / chạy): ").strip().lower()
if hanh_dong == "đánh":
# Sát thương cơ bản
sat_thuong_gay_ra: int = 10
# Nếu có kiếm, gây thêm sát thương
if co_kiem:
sat_thuong_gay_ra = sat_thuong_gay_ra + 10
print("⚔️ Kiếm Ma Thuật phát sáng!")
mau_trum = mau_trum - sat_thuong_gay_ra
print(f"💥 Bạn gây {sat_thuong_gay_ra} sát thương lên Rồng! (Máu Rồng: {mau_trum})")
# Rồng đánh trả
sat_thuong_nhan: int = 15
if co_khieng:
sat_thuong_nhan = sat_thuong_nhan - 5
print("🛡️ Khiên Gỗ đỡ bớt 5 sát thương!")
mau_nguoi_choi = mau_nguoi_choi - sat_thuong_nhan
print(f"🔥 Rồng phun lửa! Bạn nhận {sat_thuong_nhan} sát thương. (Máu: {mau_nguoi_choi})")
elif hanh_dong == "chạy":
print("🏃 Bạn bỏ chạy khỏi con Rồng!")
break
else:
print("❓ Gõ 'đánh' hoặc 'chạy'.")
if mau_trum <= 0:
print("\n🎉 Bạn đã đánh bại RỒNG LỬA!")
return mau_nguoi_choi
🧪 Thử thách 2: Sử Dụng Vật Phẩm Trong Túi Đồ
Cho phép người chơi gõ “dùng bình máu” để hồi máu.
def dung_vat_pham(tui: list, mau_hien_tai: int) -> tuple[list, int]:
"""Dùng một vật phẩm trong túi đồ. Trả về (túi đồ mới, máu mới)."""
vat_pham_muon_dung: str = input("👉 Bạn muốn dùng vật phẩm gì? ").strip()
for vat_pham in tui:
if vat_pham_muon_dung.lower() in vat_pham.lower():
if "Bình Máu" in vat_pham:
mau_hien_tai = hoi_mau(mau_hien_tai, 30)
tui.remove(vat_pham)
return tui, mau_hien_tai
print(f"❌ Bạn không có '{vat_pham_muon_dung}' trong túi đồ!")
return tui, mau_hien_tai
🎲 Thử thách 3: Yếu Tố Ngẫu Nhiên
Dùng thư viện random để tạo sự kiện bất ngờ!
import random
def su_kien_ngau_nhien(mau_ht: int, tui: list) -> tuple[int, list]:
"""Kích hoạt một sự kiện ngẫu nhiên."""
su_kien: int = random.randint(1, 4)
if su_kien == 1:
print("\n🦇 Một bầy DƠI bay qua và tấn công bạn!")
return nhan_sat_thuong(mau_ht, 10), tui
elif su_kien == 2:
print("\n💎 Bạn tìm thấy một viên ĐÁ QUÝ trên sàn!")
tui.append("💎 Đá Quý")
return mau_ht, tui
elif su_kien == 3:
print("\n🍗 Bạn thấy một ĐÙI GÀ bị bỏ lại trên bàn!")
tui.append("🍗 Đùi Gà")
return mau_ht, tui
else:
print("\n🍀 Bạn cảm thấy may mắn! (+5 máu)")
return hoi_mau(mau_ht, 5), tui
📜 Thử thách 4: Nhiều Kết Thúc Khác Nhau
Tạo ít nhất 3 cách khác nhau để kết thúc game:
- 🏆 Kết thúc TỐT: Đánh bại trùm và thoát khỏi hầm ngục
- 😔 Kết thúc BÌNH THƯỜNG: Thoát mà không đánh trùm
- 💀 Kết thúc XẤU: Chết trong hầm ngục
6. Mẹo gỡ lỗi (Debugging Tips) 🐛
Khi code không chạy như mong đợi, đây là những lỗi phổ biến và cách sửa:
| Triệu chứng | Nguyên nhân có thể | Cách sửa |
|---|---|---|
| Game chạy một lần rồi dừng | Thiếu vòng lặp while hoặc game_dang_chay = False sai chỗ | Kiểm tra điều kiện while |
| input() luôn vào else | So sánh sai chính tả (vd: “Trái” thay vì “trái”) | Dùng .lower() và .strip() |
| Máu không giảm | Quên gán mau = nhan_sat_thuong(mau, 20) | Luôn gán kết quả trả về |
| Game bị kẹt một phòng | Biến so_phong_da_qua không được tăng | Kiểm tra mọi nhánh if đều cập nhật phòng |
| NameError: name ‘…’ is not defined | Biến chưa được khai báo hoặc khai báo sai vị trí | Khai báo biến trước khi dùng |
| Type hint báo lỗi | Dùng sai kiểu dữ liệu | Kiểm tra lại kiểu tham số và giá trị trả về |
7. Tổng kết Module
| Thành phần | Vai trò trong game |
|---|---|
| Biến | Lưu máu, tên, trạng thái game |
| List | Túi đồ chứa vật phẩm |
| if/elif/else | Rẽ nhánh câu chuyện theo lựa chọn |
| while | Giữ game chạy cho đến khi thắng hoặc thua |
| Hàm | Tái sử dụng logic (hồi máu, nhận sát thương) |
| Type hints | Làm code rõ ràng, dễ đọc, dễ sửa |
🎉 Chúc Mừng!
Bạn đã hoàn thành toàn bộ khóa học Python! Từ một người chưa từng viết dòng code nào, giờ đây bạn đã có thể:
- ✅ Tạo biến và lưu trữ dữ liệu
- ✅ Dùng if/else để ra quyết định
- ✅ Dùng vòng lặp while để code chạy liên tục
- ✅ Dùng list để quản lý nhiều mục cùng lúc
- ✅ Tự xây hàm với type hints đầy đủ
- ✅ Ghép tất cả lại thành một game hoàn chỉnh!
Bạn chính thức là một Lập Trình Viên Python! Hãy tiếp tục xây dựng, tiếp tục phá vỡ mọi thứ (để sửa chúng), và không ngừng học hỏi! 🚀
(The End)

vuanhduc2685@gmail.com
hoanvtt99@gmail.com
