[Đồ án] Hướng dẫn code game rắn săn mồi trong C

Làm Game Rắn Săn Mồi
Làm Game Rắn Săn Mồi

Để tổng kết cho khóa học lập trình C mang tên “Học C Bá Đạo” của Lập trình không khó, hôm nay mình sẽ cùng các bạn thực hành một bài tập tổng hợp cũng là bài tập lớn kết thúc khóa học này. Mình sẽ cùng các bạn làm game rắn săn mồi trên màn hình console sử dụng ngôn ngữ lập trình C. Kết quả của sản phẩm hoàn thiện trông như thế này đây

Lưu ý: Video demo của game rắn săn mồi này chưa có tính năng dùng chuột điều khiển, lỗi xuất hiện trong video đã được xử lý triệt để.

Đây là source code bài tập lớn môn Đồ họa máy tính thời sinh viên của mình. Do là thời sinh viên nên code chưa được tối ưu nhưng đó không phải vấn đề lớn. Mục tiêu của bài này là mình giúp được các bạn nắm được ý tưởng, các thức để xây dựng và vận hành một trò chơi đơn giản. Chúng ta cùng vào bài nhé.

Các kiến thức yêu cầu của bài học

Để hoàn thành trò chơi rắn săn mồi này, chúng ta cần rất nhiều các kiến thức. Tuy nhiên bạn không cần bắt buộc phải nắm được các kiến thức dưới đây mà chỉ cần hoàn thành khóa học lập trình C của mình là có thể lao vào chiến đấu được rồi. Khi gặp kiến thức mới các bạn cần tự tìm hiểu bổ sung nhé. Dưới đây là các kiến thức cần có mình liệt kê ra để các bạn chuẩn bị trước, hoặc khi dùng tới nó thì tìm hiểu:

  • Kiến thức lập trình C & từ duy lập trình cơ bản – và khóa học C của mình đã cho bạn điều đó.
  • Kiến thức lập trình đồ họa trong C, thư viện graphics.h/ winbgim.h (xem Chương 9 tài liệu lập Kỹ thuật lập trình C thầy Ất, mình để ở tài liệu tham khảo ở bài 1)
  • Kỹ thuật đọc ghi file
  • Thao tác với bàn phím và chuột sử dụng ngôn ngữ C

Giới thiệu về game rắn săn mồi

Trò chơi rắn săn mồi quá quen thuộc với các bạn rồi, mình sẽ không trình bày đó là trò chơi gì. Nhưng mình cần trình bày lại trò chơi này cho các bạn ở khía cạnh kỹ thuật, để từ đó ta tìm ra giải pháp xây dựng trò chơi:

Từng bước mô hình hóa game rắn săn mồi

Game Rắn Săn Mồi 3
Hướng của trục tọa độ trong màn hình Console, trục Oy có chiều hướng xuống dưới.

Con rắn thực tế và rắn trong game

Con rắn săn mồi của chúng ta sẽ là một chuỗi các hình tròn nhỏ (các đốt của con rắn) nối lại với nhau (số hình tròn nhỏ chính là độ dài của con rắn). Khởi tạo trò chơi, chúng ta có thể đặt độ dài ban đầu của nó là 3 chẳng hạn. Trong quá trình trò chơi diễn ra, ta phải lưu vết được tọa độ của từng hình tròn đó.

Game rắn săn mồi
Game rắn săn mồi – đối tượng con rắn có thể mô phỏng là chuỗi các hình tròn nhỏ (các chấm xanh liên tiếp trong ảnh chính là đối tượng rắn của chúng ta).

Tại mỗi bước dịch chuyển của rắn, mỗi đốt thân của rắn sẽ dịch chuyển đi 1 đơn vị độ dài bằng nhau. Trong đó, đốt thân đầu tiên (đầu của rắn) sẽ tiến lên theo hướng dịch chuyển, các  đốt thân phía sau di chuyển đến vị trí cũ của đốt thân phía trước nó. Ví dụ:

Giả sử con rắn có 3 đốt và tọa độ của nó hiện tại là: x1(3,0) – đầu, x2(2,0) và x3(1,0) và đang đi theo hướng trục Ox. Bây giờ rắn đổi hướng di chuyển sang bên trái. Khi đó tọa độ mới của từng đốt là: x1(3,-1), x2 sẽ là tọa độ của x1 cũ (3, 0) và x3 chuyển sang vị trí của x2 cũ là (2, 0).

Đưa các đối tượng của game lên ngôn ngữ lập trình

Như vậy, ta sẽ xây dựng một đối tượng Điểm. Đối tượng này giúp ta lưu được tọa độ của một điểm trên trục tọa độ 2 chiều Oxy. Ta có cấu trúc Điểm như sau:

Khi đó:

  • Một con rắn sẽ là 1 mảng các đối tượng Point tương ứng với các đốt của rắn. Tại mỗi đốt, cặp tọa độ (x,y) sẽ lưu vị trí đốt hiện tại và cặp tọa độ (x0,y0) sẽ lưu ví trí trước đó của đốt hiện tại để các đốt sau đó của con rắn có thể sử dụng.
  • Mỗi đối tượng thức ăn sẽ là 1 đối tượng Point. Ta chỉ cần sử dụng cặp biến (x, y) để lưu 1 đối tượng thức ăn. Tại một thời điểm trên màn hình chỉ có 1 thức ăn, và thức ăn đó xuất hiện ở 1 vị trí ngẫu nhiên bất kỳ.
  • Để rắn di chuyển được trên màn hình thì ta cần thêm một biến lưu hướng đi của nó. Ta sẽ tận dụng luôn đối tượng Point để xác định hướng theo tọa độ (x,y). Ví dụ nếu rắn đang di chuyển theo hướng trái sang phải, như vậy đối tượng direction của ta sẽ là (10, 0). Tức là ở mỗi bước đi, tọa độ x sẽ tăng thêm 10 đơn vị và tọa độ y không đổi. Khi ta thay đổi hướng đi, ta chỉ cần thay đổi giá trị (x, y) của đối tượng direction như hình dưới đây:
Game Rắn Săn Mồi 2
Mô phỏng hướng đi của rắn, tại mỗi bước đi ta sẽ cho Point đầu của rắn cộng thêm với Point hướng đi của nó. Các bạn lưu ý rằng trục Oy trong Console của chúng ta hướng xuống dưới nhé (Tức là y tăng khi xuống dưới và giảm khi đi lên trên).

Mô hình hóa cách di chuyển của rắn

Giả sử rắn của chúng ta có chiều dài tối đa là 100 (chơi lên 100 chắc khủng lắm :v), ta sẽ khai báo mảng Point:

Vậy để di chuyển con rắn, ta cần di chuyển đầu của con rắn trước tiên:

Nhưng trước đó ta phải lưu lại tọa độ cũ của nó để đốt kế sau nó lần theo:

Vậy tổng quát, để di chuyển toàn bộ phần thân còn lại của rắn ta sẽ chạy một vòng lặp hết phần thân rắn và thực hiện:

Rắn sẽ ăn được thức ăn khi tọa độ đầu snake[0] trùng với tọa độ thức ăn food. Khi đó ta cần :

  1. Tăng chiều dài của rắn
  2. Khởi tạo ngẫu nhiên tọa độ thức ăn mới – Lưu ý không khởi tạo trùng vào các đốt thân của rắn.
  3. Tăng điểm số (game phải có điểm chứ)

Nếu đầu Rắn chạm tường hoặc chạm thân thì game kết thúc ( Chế độ chơi hiện đại) và chỉ chết khi chạm vào thân (chế độ chơi cổ điển)

Tính năng lưu điểm cao trong game

Để tăng tính hấp dẫn cho game rắn săn mồi, ta tạo thêm một đối tượng HighScore lưu thông tin Tên người chơiSố điểm đạt được nếu người chơi đó đạt điểm cao.

Thông tin điểm cao sẽ được ghi ra một file txt và lưu lại để so sánh với các người chơi sau đó. Nếu người chơi mới đạt điểm cao hơn trong danh sách đã lưu thì sẽ thay thế thành tích của người chơi cũ tương ứng bởi thành tích của người chơi mới.

Các hàm trong game rắn săn mồi

Mình sẽ không đi sâu vào giải thích từng dòng code cho các bạn được. Thay vào đó, mình chỉ cho các bạn các đối tượng của game rắn săn mồi này, các chức năng cần xây dựng của game và cách thức vận hành game. Thông qua đó bạn đọc cố gắng tìm hiểu thêm để hoàn thiện game dựa trên ý tưởng của mình. Các bạn cũng có thể tham khảo source code của mình (hiểu được thì càng tốt :v).

Các biến toàn cục trong trò chơi

Danh sách các hàm mình xây dựng cho trò chơi rắn săn mồi này:

Các hàm và vai trò của nó

void initGame ();

  • Vẽ khung của trò chơi
  • Khởi tạo tọa độ ban đầu cho Snake (Gồm 3 Point) và Food
  • Khởi tạo hướng đi ban đầu
  • Vẽ màu backgound và các đối tượng hiển thị không thay đổi vị trí.

bool checkPoint ();

Hàm này có chức năng kiểm tra trùng lặp khi tạo mới đối tượng Food. Kiểm tra chắc chắn rằng tọa độ thức ăn không trùng với thân Rắn

void drawPoint (int x,int y,int r);

Hàm này có chức năng vẽ một đối tượng Point (hình tròn) lên màn hình đồ họa có tọa độ tâm (x,y) và có bán kính r

void drawSnake ();

Hàm này gọi làm hàm drawPoint () có các chức năng :

  • Vẽ đối tượng Snake lên màn hình đồ họa.
  • Xóa bỏ đốt cuối cùng của thân rắn mỗi khi rắn di chuyển được thêm một bước.

void drawFood ();

Hàm này gọi lại hàm drawPoint () và hàm checkPoint (); để thực hiện nhiệm vụ hiển thị thức ăn lên màn hình đồ họa.

void drawGame ();

Hàm này gọi lại hai hàm drawSnake() và hàm drawFood() và thực hiện thêm công việc hiển thị điểm của người chơi lên màn hình.

void classic();

Hàm này thực hiện chức năng chơi cổ điển – Người chơi có thể đi xuyên tường.
Chức năng của hàm:

  • Di chuyển Rắn theo điều khiển hướng đi
  • Nếu Rắn đi ra ngoài mép tường – cho rắn xuất hiện lại ở phía bên kia
  • Kiểm tra rắn ăn mồi : tăng chiều dài, điểm số và random lại tọa độ thức ăn
  • Kiểm tra game kết thúc

void modern();

Hàm này tương tự hàm classic() nhưng thay vào đó rắn không thể đi xuyên tường và đó là một trong những điều kiện bổ sung vào kiểm tra game kết thúc của hàm này.

void changeDirecton (int x);

x là biến kiểu nguyên lưu giữ giá trị ASCII tương ứng của của phím ở kiểu int. Đây là hàm thực thi việc nhận lệnh điều khiển hướng đi của rắn từ bàn phím, cụ thể là các phím mũi tên điều hướng và phím ESC. Hàm sẽ nhận vào mã phím nhập từ bàn phím và thực hiện thay đổi hướng đi theo mã phím tương ứng. Nếu người dùng nhấn phím ESC – Game sẽ kết thúc.

void mainLoop (void (*gloop)());

Hàm này chính là hàm lặp cho phép game chạy và thực thi toàn bộ các hành động trong khi game chạy
Tại đây, mình sử dụng đệ quy để hàm gọi lại chính nó. Tham số truyền vào là một trong hai hàm classic() hoặc hàm modern() tùy theo lựa chọn của người chơi. Hàm này còn có chức năng Pause/Resum game khi đang chơi nếu người dùng ấn phím SPACE.

bool isEmpty();

Hàm này kiểm tra file lưu điểm cao. Nếu file là rỗng thì trả về giá trị true.

void initScore();

Hàm này kiểm tra file lưu điểm cao có rỗng hay không bằng cách gọi hàm isEmpty(). Nếu file rỗng thì hàm sẽ khởi tạo 5 giá trị mặc định có tên PLAYER và điểm cao là 0. Nếu hàm có chứa thông tin hàm sẽ đọc thông tin điểm cao lưu vào mảng kiểu HighScore.

void showHighScore();

Hàm này có chức năng đọc thông tin của file điểm cao và xuất ra thông tin lên màn hình đồ họa khi được gọi.

void getHighScore ();

Hàm này có chức năng ghi lại thông tin điểm cao của người chơi + lưu vào file.

Hàm checkHighScore (int _score)

Hàm này thực hiện nhiệm vụ nhận điểm cao của người chơi, lấy thông tin tên người chơi nếu người chơi đó đạt thành tích cao. Hàm sẽ lưu giá trị vào mảng kiểu HighScore và gọi lại hàm getHighScore() để lưu lại thông tin.

Ngoài ta chương trình còn có một số hàm nhỏ thực hiện một số chức năng nhất định, bao gồm:

  • Thêm tính năng click chuột thay cho nhấn bàn phím.
  • Thêm nhạc cho game trở nên sống động

Cài đặt mã nguồn game rắn săn mồi

Mã nguồn này được mình viết và chạy ở IDE Dev-C++ trên Windows, mình chưa test thử trên các IDE khác cũng như hệ điều hành khác (chắc méo chạy được đâu ^^). Các bạn có thể cài và chạy mã nguồn theo hướng dẫn có trong file README.md trên github của mình:

Toàn bộ source code bạn xem và tải về tại đây (file code chính là demo.cpp nhé): https://github.com/Hieunv1996/Snake

À hình như là khi mở source này bằng DevC thì các bạn vào File -> Open Project -> Chọn file .dev mà mở. Mình nhớ không nhầm là vậy (Nếu sai bạn đính chính giúp mình nhé, giờ mình dùng Ubuntu mất rồi).

Tóm lại, đây là một bài hướng dẫn game rắn săn mồi cơ bản giúp các bạn nắm bắt ý tưởng, tự xây dựng được các trò chơi cơ bản khác (caro, đua xe, bắn bóng, crazy math, …). Mình rất hi vọng các bạn có thể làm ra các sản phẩm xịn xò, cố gắng làm ra những siêu phẩm hơn mình. Nếu như vậy thì mình rất vui khi các bài chia sẻ của mình thực sự góp ích cho cồng động!

Lời cuối, xin trân thành và cảm ơn các bạn đã ủng hộ khóa học và ủng hộ Lập trình không khó!

avatar
  Subscribe  
newest oldest most voted
Notify of
Bé Còi
Guest
Bé Còi

Ad giúp e với !!!!
Số đẹp là số có tổng chữ số của nó chia hết cho số chữ số của nó . n <= 10^6
.TÌM SỐ ĐẸP THỨ N ….

HoaDQ1
Guest
HoaDQ1

khó thật. cộng đồng không làm được đâu

bang
Guest
bang

`#include using namespace std; int soChuSo(long long n) { // hàm này dùng để tính số chữ số của n int t = 0; while (n > 0) { t++; n = n / 10; } return t; } int tongChuSo(long long n) { // hàm này dùng để tính tổng chữ số của n int s = 0; while (n > 0) { s = s + n % 10; n = n / 10; } return s; } bool kiemTra(long long n) { // hàm này để kiểm tra xem n có là số đẹp không, nếu có… Read more »