Tôi đã tạo Game of Life của Conway như thế nào
Conway’s Game of Life không phải một trò chơi theo nghĩa thông thường — không có người chơi, không có mục tiêu, không có điểm số. Nó là một mô phỏng tự động tế bào (cellular automaton) do nhà toán học John Horton Conway sáng tạo năm 1970. Chỉ với 4 quy tắc đơn giản, nó có thể tạo ra những cấu trúc phức tạp đến kinh ngạc — sống động như thật.
Ý tưởng cốt lõi
Hãy tưởng tượng một tờ giấy kẻ ô vuông vô hạn. Mỗi ô là một tế bào, và mỗi tế bào chỉ có hai trạng thái: sống hoặc chết. Mỗi “thế hệ”, toàn bộ lưới được cập nhật đồng thời theo đúng 4 quy tắc.
4 Quy tắc của Conway
Mỗi tế bào nhìn vào 8 hàng xóm xung quanh mình (kể cả đường chéo) rồi quyết định số phận của thế hệ tiếp theo:
- Cô đơn — Tế bào sống có ít hơn 2 hàng xóm sống → chết vì cô đơn
- Ổn định — Tế bào sống có 2 hoặc 3 hàng xóm sống → tiếp tục sống
- Quá đông — Tế bào sống có hơn 3 hàng xóm sống → chết vì thiếu tài nguyên
- Hồi sinh — Tế bào chết có đúng 3 hàng xóm sống → hồi sinh
Chỉ vậy thôi. Bốn dòng logic. Nhưng từ đó có thể xuất hiện những “sinh vật” di chuyển, những cấu trúc dao động, thậm chí những cỗ máy tính hoàn chỉnh.
Thuật toán
Phần khó nhất không phải là logic — mà là đảm bảo toàn bộ lưới được cập nhật đồng thời, chứ không phải từng ô một. Nếu bạn cập nhật ô A rồi dùng trạng thái mới của A để tính ô B, kết quả sẽ sai.
Giải pháp: dùng hai mảng — một mảng lưu trạng thái hiện tại, một mảng tính toán thế hệ tiếp theo, sau đó hoán đổi.
function step() {
const next = newEmptyGrid();
for (let r = 0; r < ROWS; r++) {
for (let c = 0; c < COLS; c++) {
const neighbors = countNeighbors(r, c); // đếm 8 hàng xóm
const alive = grid[r][c];
if (alive) {
next[r][c] = (neighbors === 2 || neighbors === 3) ? 1 : 0;
} else {
next[r][c] = (neighbors === 3) ? 1 : 0;
}
}
}
grid = next; // hoán đổi — không bao giờ chỉnh sửa grid gốc
}
Để đếm hàng xóm, dùng vòng lặp offset [-1, 0, 1] × [-1, 0, 1], bỏ qua (0, 0). Lưới được wrap tròn (toroidal) — hàng trên cùng nối với hàng dưới cùng — để tránh hiệu ứng biên.
Hiệu ứng màu sắc theo tuổi
Phiên bản tôi xây dựng thêm một lớp trực quan: tế bào thay đổi màu theo tuổi thọ. Mỗi tế bào có thêm một giá trị age từ 0.0 đến 1.0, tăng dần mỗi thế hệ nếu sống sót. Màu được nội suy tuyến tính (lerp) giữa màu mới sinh và màu già:
// Mới sinh: xanh sáng #39ff78
// Già: xanh đậm #00b43c
color = lerp(ALIVE_NEW, ALIVE_OLD, age[r][c]);
Khi một tế bào chết, nó không biến mất ngay — giá trị fade từ từ giảm về 0 qua nhiều thế hệ, tạo hiệu ứng “vừa chết” màu xanh rêu mờ dần.
Các mẫu nổi tiếng
- Glider — cấu trúc 5 tế bào di chuyển chéo qua lưới, lặp lại sau mỗi 4 thế hệ
- Pulsar — oscillator chu kỳ 3, đối xứng hoàn hảo, trông như tim đang đập
- Gosper Glider Gun — cấu trúc phức tạp liên tục “bắn” ra các Glider mới mãi không dừng
Xây dựng bằng HTML Canvas
Toàn bộ phiên bản này được viết bằng JavaScript thuần, không dùng thư viện. Canvas API vẽ từng tế bào bằng fillRect, vòng lặp game chạy qua requestAnimationFrame với kiểm soát FPS thủ công.
Kích thước lưới tự tính theo chiều rộng màn hình, hỗ trợ cảm ứng trên điện thoại qua touchstart và touchmove. Toàn bộ chưa đến 200 dòng code.
“The Game of Life is not just a mathematical curiosity — it’s a window into how complexity can arise from simplicity.”
— Martin Gardner, Scientific American, 1970

No Comment! Be the first one.