Tải bản đầy đủ (.pdf) (14 trang)

HƯỚNG dẫn lập TRÌNH rắn săn mồi cơ bản BẰNG c++

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (877.79 KB, 14 trang )

HƯỚNG DẪN LẬP TRÌNH RẮN SĂN MỒI CƠ BẢN BẰNG C/C++
Người thực hiện: Nguyễn Quốc Vương
GVHD: Vũ Đình Bảo
Sinh viên năm 1 trường CĐ KT CT


 Để lập trình một trò chơi rắn săn mồi, trước tiên ta cần tự đặt ra vấn đề.Làm
sao để Rắn hiện ra màn hình ? Cách thức di chuyển? Làm sao để console phản hồi lại
tác động của người dùng khi bấm phím mà rắn chạy? Đó là những điều kiện cơ bản
khi muốn lập trình một game đơn giản.
 Đầu tiên là lập một dàn ý của vấn đề mà ta đang tìm hiểu. Cụ thể:
 Khởi tạo vật thể mà mình muốn xuất ra màn hình
 Hiện thị vật thể ra màn hình
 Cách thức để điều khiển vật thể chạy theo hướng của người bấm
 Xử lý các thuật toán khác
 Thắng hoặc thua, kết thúc trò chơi
Đây là những điều kiện cơ bản nhất mà chúng ta cần để thực thi một trò chơi
đơn giản. Khi có các mục tiêu cụ thể, ta đi sâu vào để tìm hiểu các hàm, lệnh để hỗ
trợ tốt nhất, qua mỗi dòng lệnh thực thi ta sẽ có thêm ý tưởng cũng như kinh nghiệm
để làm các bước tiếp theo.
Từ đó ta tiếp tục tìm hiểu thêm một số chức năng nâng cao mà qua đó ta học
hỏi thêm một số kinh nghiệm để ứng dụng khi cần thiết.
 Tránh đi quá lan man, tìm hiểu những vấn đề lớn không thực sự cần thiết cho
đề tìm hiểu gây tốn thời gian và mất phương hướng, nên gói gọn mục tiêu, làm tới
đâu note tới đó.
Yêu cầu phải học qua nhập môn lập trình, biết được các hàm, kiểu dữ liệu cơ
bản. Nếu không thì sẽ khó khăn hơn một chút là làm tới đâu sẽ phải tìm hiểu hàm tới
đó.


Chúng ta có thể sử dụng visual studio 2010 trở lên, nhưng theo tôi khuyến


cáo sử dụng visual 2013 hoặc 2015, có nhiều chức năng cũng như tự động căn
chỉnh dòng, lề làm cho code của mình nhìn trực quan hơn. Ở đây tôi xài phiên
bản 2015.
A. Tạo project



B. Coding
- Ta phải khai báo thư viện cần thiết, nếu dùng scanf, printf (của C) thì
sử dụng thư viện stdio.h, ngược lại cout, cin(của c++) thì sử dụng thư
viện iostream.
-

#include "iostream"
using namespace std;
int main()
{

- }
 Đầu tiên ta khởi tạo con rắn. Giả định con rắn có n đốt, mỗi đốt là một vị
trí (x,y) trên màn hình console. Khi đốt thứ nhất(mặc định là cái đầu) di
chuyển thì ta chỉ việc khởi tạo đốt mới. Còn ở thân rắn ta gán từng đốt
bằng với một giá trị tạm, có nghĩa là khi rắn di chuyển, đầu rắn sẽ nhận đốt
mới, đốt cũ của đầu rắn = đốt thứ i+1. Khi di chuyển thành công thì khai báo
xóa(cout <<” “) ở đốt cuối mà chúng ta đã gán giá trị tạm. (Bình tĩnh nhé, tôi sẽ
ví dụ bên dưới cho dễ hiểu hơn :D)

+ Khởi tạo hàm struct để định nghĩa tọa độ x,y và ox,oy( đây là 2 biến
tạm, tôi sẽ giải thích ở phần sau) . Sau đó khai báo mảng Snake[100] có
kiểu dữ liệu ToaDo.



+ Tạo hàm con, tạm gọi là khoiTaoRan,khởi tạo các đốt rắn khi xuất ra
màn hình. Mỗi đốt là một ví trí. Ở đây tôi cho 4 đốt

+ Ta thử xuất ra màn hình bằng những ký tự đặc biệt bằng cách ép kiểu.
Từ 1 tới 255 là mỗi ký tự đặc biệt, sử dụng hàm for để lấy ký tự mà mình muốn.
Tôi lấy ký tự 254(nó giống với từng đốt rắn nhất :D).

+ Để xuất hình ảnh ra các tọa độ nhất định ở màn hình ta cần sử dụng hàm
gotoXY(x,y) trong đó x là tọa độ trục hoành, y là trục tung(Hàm không có
trong thư viện mặc định của VS, sẽ chia sẽ ở cuối bài). Hàm này dùng để
đưa con trỏ tới những vị trí nào đó trong màn hình console, Ở màn hình
console mặc định tọa độ góc trái trên cùng là 0,0(x,y). khi trỏ tới tọa độ thì
ta xuất(cout/printf) ra màn hình hình ảnh rắn bằng một ký tự đặc biệt mà
ta muốn.


+ Add thư viện console(lấy hàm gotoXY) vào project

Khai báo thêm thư viện include “console.h” trong project.
+ Ở hàm main ta gọi hàm con khoiTaoRan(Snake) để tạo vị trí rắn ra màn
hình. Sau đó cho vòng for chạy tờ 0 tới n-1 đốt, gotoXY tới tọa độ của rắn mà ta
đã khởi tạo bên trên, xuất ký tự đặc biệt(Tạm gọi đốt rắn).


Thế là ta hoàn thành được phần hình ảnh rồi phải không nhỉ :D.
 Vấn đề tiếp theo là làm sao để cho rắn tự động di chuyển ? Như chúng ta
đã biết trò chơi rắn săn mồi khi bắt đầu là rắn sẽ tự động di chuyển về 1
hướng nào đó trên màn hình. Tôi sẽ hướng dẫn một cách dễ hiểu nhất có

thể.
+ Ta khai báo hàm enum với các thành phần LEN, XUONG, TRAI, PHAI.
hàm này giúp chúng ta lập trình nhìn trực quan dễ hiểu hơn thay vì dùng
các con số dễ gây nhầm lẫn. Đồng thời khai báo biến tạm gọi là “huong”
của kiểu dữ liệu HuongDiChuyen trong hàm struct.

+ Tiếp theo ta khai báo hàm con tạm gọi là chuyenDong để xử lý hướng
di chuyển cho rắn. Nếu rắn qua phải thì tọa độ x++, ngược lại qua trái x-, nếu di chuyển xuống thì tọa độ y++ ngược lại đi lên y--;


+ Ở hàm main, ngay đầu hàm khai báo hướng rắn mặc định khi bật game
là sẽ qua phải. Trong hàm while(1) sẽ xử lý các tác vụ liên tục, bao gồm
Hình ảnh rắn, rắn di chuyển. Bên cạnh đó ta phải sử dụng hàm Sleep(mili
giây) để có một khoảng thời gian delay(thời gian chờ) hay còn gọi là tốc
độ rắn khi thực hiện xong một vòng lặp. OK chạy thử thôi.

Hình như có gì đó sai sai phải không ạ ? Đúng là rắn sẽ di chuyển qua
phải nhưng càng di chuyển đuôi càng dài chứ không xóa các vị trí cũ !? Ta sẽ xử
lý tiếp phần này.
 Như tôi đã nói ở trên đầu rắn di chuyển thì tạo đốt mới, đồng thời xóa đốt
cũ ở cái đuôi rắn.
+ Ta sẽ khai báo 1 hàm con để xử lý vấn đề này, tạm gọi là hàm
xuLyHinhAnh. Khi đó vị trí ox,oy tạm = vị trí x,y của đầu rắn, sau đó vị
trí x,y đốt rắn thứ 1 trở đị = vị trí ox,oy tạm-1.


+ Tiếp theo khai báo hàm gotoXY tới vị trí ox,oy tạm thứ n-1 xóa đốt cuối
cùng khi đầu rắn lên 1 đơn vị, và PHẢI đặt trước vòng for xuất hình ảnh
rắn.


 Lý do bởi vì chương trình sẽ chạy từ trên xuống, trái qua phải. Theo
chương trình này thì hàm sẽ khởi tạo rắn -> Xóa đốt cuối(Nhưng lúc
này ox,oy, chưa có giá trị nào hết nên sẽ bỏ qua) -> xuất hình ảnh
rắn -> Xử lý hình ảnh bằng cách gán giá trị ox, oy tạm -> rắn chuyển
động(x,y++(--)) khi đó giá trị đầu rắn thay đổi -> quay lại vòng lặp
-> xóa đốt cuối, lúc này rắn chỉ có 3 đốt -> xuất hình ảnh rắn (lúc
này đầu rắn đã bằng vị trí mới, nên trên console sẽ hiện 4 đốt như
cũ, do máy xử lý quá nhanh nên mắt thường ko nhìn thấy) ->…. Lặp
đi lặp lại
OK ! Chạy thử và thấy điều kỳ diệu :D… Vậy là xong phần hình ảnh
và chuyển động, tiếp theo ta cần xử lý rắn di chuyển theo ý của mình
khi bấm các phím tương ứng.
 Khi chúng ta bấm một phím nào đó thì làm sao máy tính nhận và phản hồi
lại ? Ở đây ta có một hàm để phát hiện nút bấm là _kbhit() và hàm _getch()


để nhận giá trị từ nút bấm, cả 2 hàm đều trong thư viện conio.h. Tôi sẽ sử
dụng các key W = lên, S = xuống, A = Trái, D = phải.

+ Sau đó gọi hàm này ở hàm main đặt sau hàm xuLyHinhAnh

Chạy thử bấm các nút và Tada !!!
+ À có một vấn đề nhỏ mà ta cần giải quyết, ko thì sẽ rất phản khoa học =).
Đó là khi rắn qua trái mà ta bấm qua phải sẽ bình thường ko có chuyện gì
xảy ra, điều đó là ko đúng phải ko nhỉ ? Thế thì ta phải xử lý thêm một chút
ở hàm phát hiện nút bấm


 Di chuyển đầy đủ rồi giờ tới thức ăn cho rắn, điều ta cần làm là xuất ra màn
hình ký tự đặc biệt tượng trưng cho thức ăn của rắn. Khi đầu rắn chạm vào

thì thức ăn sẽ mất đồng thời đốt rắn dài thêm 1 đốt.
+ Trước tiên ta phải define kích thước ngang, dọc của màn hình console(đặt
ở phía trên hàm enum). Làm điều này đễ câu lệnh ta nhìn trực quan dễ hiểu
hơn.
#define consoleWidth 75
#define consoleHeight 24

+ Sau đó khởi tạo 1 hàm con tạm gọi là KhoiTaoThucAn có tham số đầu
vào là ToaDo Food[].
void KhoiTaoThucAn(ToaDo Food[])
{
gotoXY(Food[0].x, Food[0].y); // Xóa thức ăn
cout << " ";
Food[0].x = rand() % consoleWidth + 1; // Khởi tạo lại vị trí thức ăn
Food[0].y = rand() % consoleHeight + 1;
gotoXY(Food[0].x, Food[0].y); // Xuất thức ăn ở vị trí đã khởi tạo
cout << char(15);
}

***Vì thức ăn phải xuất hiện ngẫu nhiên ta dùng hàm rand(). rand()% a +
1 là hàm lấy giá trị ngẫu nhiên. Ta có công thức ngẫu nhiên từ a tới b là
rand() % (b – a + 1) + 1. Char(15) là ký tự đặc biệt


+ Sau khó khởi tạo thêm một hàm xử lý va chạm với thức ăn, tạm gọi
XuLyThucAn có tham số đầu vào là Snake[],Food[] và tham chiếu n(chiều
dài rắn).
void XuLyThucAn(ToaDo Snake[], ToaDo Food[], int &ChieuDaiRan)
{
//Thực hiện khi va chạm đầu rắn với thức ăn

if (Snake[0].x == Food[0].x && Snake[0].y == Food[0].y)
{
ChieuDaiRan++;
KhoiTaoThucAn(Food);
}
}

+ Ở hàm main khai báo mảng ToaDo Food[1], và khai báo hàm
KhoiTaoThucAn ở trước hàm while(1) để xuất hiện vị trí thức ăn đầu tiên
khi vào game. Trong hàm while(1) phia trên hàm XuLyHinhAnh ta khai
báo hàm XuLyThucAn.
int main()
{
ToaDo Snake[100], Food[1];
int n = 4; //Tạm cho rắn có 4 đốt
khoiTaoRan(Snake); //Khởi tạo rắn
KhoiTaoThucAn(Food); // Khởi tạo thức ăn
Snake[0].huong = PHAI; // Mặc định rắn sẽ di chuyển qua phải
while (1)
{
gotoXY(Snake[n - 1].ox, Snake[n - 1].oy); //Vị trí cuối cùng(đuôi rắn)
cout << " "; //Xóa đuôi rắn
for (int i = 0; i < n; i++)
{
gotoXY(Snake[i].x, Snake[i].y); // Tọa độ rắn
cout << char(254); // Hình ảnh con rắn
}
XuLyThucAn(Snake, Food, n);
xuLyHinhAnh(Snake,n);
phatHienNutBam(Snake);

chuyenDong(Snake);
Sleep(100);
}
return 0;
}

Chạy thử và thưởng thức nào \m/
 Hình như còn một vấn đề ko nhỏ nữa là rắn đi xuyên tương được !? Vậy là
ta phải xử lý thắng thua, chạm tường thì sẽ thua, hết .
+ Ta define các hằng số là 4 bức bức tường 4 bên màn hình console để xử
lý va chạm


#define
#define
#define
#define

TuongTrai
TuongPhai
TuongTren
TuongDuoi

80
0
0
25

+ Sau đó khởi tạo hàm con tạm gọi XuLyThua có đầu vào là ToaDo
Snake[]. Ta xét điều kiện nếu đầu rắn ở hoành dộ chạm tường trái hoặc

phải. Đầu rắn ở tung độ chạm tường trên hoặc dưới thì thua. Giá trị trả về
cho hàm là -1.
int XuLyThua(ToaDo Snake[])
{
if (Snake[0].x == TuongTrai || Snake[0].x == TuongPhai ||
Snake[0].y == TuongTren || Snake[0].y == TuongDuoi
)
return -1;
}

+ Tiếp theo ở hàm main gọi hàm XuLyThua vào hàm while, đặt ở dưới
cùng. Nếu Hàm XuLyThua = -1 thì break, kết thúc vòng lặp, ra ngoài vòng
lặp while và xuất bảng thông báo Thua.
while (1)
{
gotoXY(Snake[n - 1].ox, Snake[n - 1].oy); //Vị trí cuối cùng(đuôi rắn)
cout << " "; //Xóa đuôi rắn
for (int i = 0; i < n; i++)
{
gotoXY(Snake[i].x, Snake[i].y); // Tọa độ rắn
cout << char(254); // Hình ảnh con rắn
}
XuLyThucAn(Snake, Food, n);
xuLyHinhAnh(Snake,n);
phatHienNutBam(Snake);
chuyenDong(Snake);
if (XuLyThua(Snake) == -1)
break;
Sleep(100);
}

gotoXY(consoleWidth / 2, consoleHeight / 2);
cout << " YOU LOSE";

 Phew. Vậy là hoàn thành được trò chơi rắn săn mồi cơ bản nhất rồi
, ngoài ra còn có một số chức năng khác như menu, điểm số khi
ăn mồi, chế độ chơi, vẽ khung giới hạn v..v.. trong qua trình làm, khi
bạn đã hiểu được cốt lõi thì những vấn đề này không khó khăn nữa,
chỉ sử dụng kiến thức như trên là làm được tương tự hết . Chúc các
bạn may mắn và đạt được mục đích của mình !



×