Dành cho người mới học VBA: Game VBA Rắn săn mồi

giaiphapvba

Administrator
Thành viên BQT
Bạn cần đăng nhập để thấy hình ảnh

Trò chơi này không mới, trên VBA cũng không mới. Tuy nhiên tôi muốn cùng các bạn lý giải từng công đoạn tạo ra Tool này, tìm hiểu rõ logic từng dòng code.
Mới thoạt nhìn, các bạn sẽ nghĩ, ôi phức tạp thế này, làm sao tôi có thể làm được. Thật ra không phức tạp như vậy đâu.
Chắc các bạn còn nhớ topic . Tất cả các chuyển động trên Excel dùng để tạo thành Game đều sử dụng hàm API Sleep quen thuộc.
Như vậy công cụ-phương tiện của chúng ta chỉ có Sleep thôi, rất dễ nhớ phải không nào.
Topic này sẽ được chúng tôi cập nhật hàng tuần. Các bạn đón đọc nhé!
 

Euler

Mod
Thành viên BQT
Step 1: Xây dựng giao diện
Các bạn xây dựng giao diện như sau:
Bạn cần đăng nhập để thấy đính kèm

Trong đó phần khoanh đỏ là vị trí các nút bấm tôi sẽ đặt vào đó.
Các bạn luyện tập và tự làm nhé.
Làm sao để kết quả như dưới đây:
Bạn cần đăng nhập để thấy đính kèm

Các bạn dán đoạn code sau vào Module 1:
Mã:
Public cnt As Integer
Dim i As Integer, j As Integer

Public Sub khoitao()
    cnt = 1 'So block lay duoc
'Khoi tao giao dien game
    For i = 1 To 20
        For j = 1 To 20
            Cells(i, j).Interior.ColorIndex = xlNone
        Next j
    Next i
'Lam moi tuoi tho khoi block
    For i = 19 To 35
        For j = 2 To 18
            Cells(i, j) = 0
        Next j
    Next i
End Sub
Tôi giải thích một chút, khi game hoạt động thì các cells sẽ bị tô màu để mô phỏng con rắn chạy.
Do đó khởi tạo game, là phải xóa sạch màu nếu có trong phạm vi 20 dòng và 20 cột đầu tiên.

Bạn cần đăng nhập để thấy hình ảnh


Bạn cần đăng nhập để thấy hình ảnh

Nhìn vào hình ảnh hai bức ảnh trên, các bạn đã thấy hình ảnh con rắn, ở vị trí tương ứng ta có tuổi thọ của các ô được viết bằng số 2,3,4,...
Tất nhiên phần tuổi thọ, ta cần lưu ở khu vực khác, không làm ảnh hưởng tới giao diện game.

Biến cnt để đếm số block cần thiết (có tuổi thọ > 0). Nếu không có biến này, thì hình ảnh con rắn trông sẽ như thế này:
Bạn cần đăng nhập để thấy hình ảnh

Hôm nay hoàn thành tới đây đã, các bạn lưu file lại nhé, nhớ để định dạng là .xlsm nhé.
 

Yukino Ichikawa

Thành viên
Step 2: Xây dựng code
Trên Module 1, các bạn khai báo các biến số toàn cục:
Mã:
Public X As Integer, Y As Integer, muki As Integer
Public play as Boolean, fin as Boolean
Và khai báo hàm :
Mã:
#If VBA7 And Win64 Then  'Office 64bit
    Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If
Hàm sleep này sẽ được dùng để tạo ra chuyển động cho con rắn.
Các bạn dán đoạn code dưới đây vào Module 1:
Mã:
Public Sub block()
    
    Do While fin = False
    
    'Khi block duoc hien thi, phat sinh di chuyen => tang tuoi tho cho cac o block
        For i = 19 To 35
            For j = 2 To 18
                If Cells(i, j) >= 1 Then
                    Cells(i, j) = Cells(i, j) + 1
                End If
            Next j
        Next i
        
    'So sanh "cnt" voi tuoi tho cua khoi block va xoa bo mau
        For i = 19 To 35
            For j = 2 To 18
                If cnt < Cells(i, j) Then
                    Cells(i - 17, j).Interior.ColorIndex = xlNone 'Clear color'
                    Cells(i, j) = 0
                End If
            Next j
        Next i
            
    'Phan doan huong di chuyen cua khoi Block
            Select Case muki
                Case 2
                    Y = Y + 1
                Case 4
                    X = X - 1
                Case 6
                    X = X + 1
                Case 8
                    Y = Y - 1
            End Select
            
    'Phan doan Game ket thuc
        If Y < 3 Or Y > 17 Or X < 3 Or X > 17 Or Cells(Y, X).Interior.ColorIndex = 5 Then
            fin = True
            play = False
            cnt = cnt - 1
        End If
            
    'Khi con ran di chuyen vao khoi block mau do (san moi) thi:
        If Cells(Y, X).Interior.ColorIndex = 3 Then
            cnt = cnt + 1
            
    'Hien thi khoi block mau do (moi) vao vi tri ngau nhien
            Dim flag As Boolean
            flag = False
            
            Do Until flag = True
            
                Randomize
            
                i = Int(Rnd * 15 + 1) + 2
                j = Int(Rnd * 15 + 1) + 2
                
                If Cells(i, j).Interior.ColorIndex = xlNone Then
                    Cells(i, j).Interior.ColorIndex = 3
                    flag = True
                End If
            Loop
        End If
            
        Cells(Y, X).Interior.ColorIndex = 5
        Cells(Y + 17, X) = 1 'Tuoi tho cua block
            
        DoEvents
        
        Sleep 90'Thoi gian cho-tao hieu ung ran di chuyen
    Loop
End Sub
(còn nữa)
 

thanhphong

Thành viên
Ta tìm hiểu kỹ hơn code của .
Đầu tiên, dòng code 5~12:
Mã:
    'Khi block duoc hien thi, phat sinh di chuyen => tang tuoi tho cho cac o block
        For i = 19 To 35
            For j = 2 To 18
                If Cells(i, j) >= 1 Then
                    Cells(i, j) = Cells(i, j) + 1
                End If
            Next j
        Next i
Bắt đầu tiến hành xử lý, tuổi thọ của các khối Block được lưu ở B20~R35.

Tiếp theo ở dòng code 65~66:
Mã:
        Cells(Y, X).Interior.ColorIndex = 5
        Cells(Y + 17, X) = 1 'Tuoi tho cua block
Những cells được tô màu xanh sẽ điền 1 vào đó.
Ở vòng lặp, dòng code 5~12, giá trị các cells đã được tăng lên 1.
Bằng xử lý như trên, từ lúc các khối block (cells) được tô màu xanh cho tới hiện tại đã trải qua bao nhiêu lần xử lý, ta hoàn toàn có thể hiểu được vì giá trị của cells được tăng lên 1 sau mỗi lần xử lý (vòng lặp).
Khi đã nắm được số lần xử lý (vòng lặp), ta có thể xóa các khối block (cells màu xanh) ở khoảng thời gian tùy ý theo ý muốn.

Tiếp theo hãy nhìn dòng code 14~22:
Mã:
    'So sanh "cnt" voi tuoi tho cua khoi block va xoa bo mau
        For i = 19 To 35
            For j = 2 To 18
                If cnt < Cells(i, j) Then
                    Cells(i - 17, j).Interior.ColorIndex = xlNone 'Clear color'
                    Cells(i, j) = 0
                End If
            Next j
        Next i
Ở đây có một biến số là cnt.
Biến số này đã được khai báo ngay quá trình .
Biến số cnt sẽ ghi số block màu đỏ mà rắn đã ăn được.
Chú ý, giá trị khởi tạo của nó không phải là 0, mà bắt đầu được thiết định là 1.

If cnt < Cells(i, j) Then : Hãy thử suy nghĩ điều kiện thực thi này.
Ngay khi game bắt đầu thì cnt đượcc gán là 1.

Ở dòng code 65~66: Những cells đã được tô màu xanh sẽ nạp vào đó giá trị là 1.
Tương ứng với cells C3, cells lưu trữ thông tin cho nó là cells C20 hay cells(20,3).

Ở vòng lặp dòng code 5~12: cells(20,3) + 1 nên giá trị sẽ là 2.


cnt < Cells(20, 3): Điều kiện được thỏa mãn cho nên Cells(20, 3) được gán là 0.
Ngoài ra ở Cells(20 - 17, 3), tức là cells C3, sẽ được làm trong suốt-không còn màu.

Đây là trạng thái trước khi con rắn ăn được cells màu đỏ.

Vậy, bây giờ hãy thử suy nghĩ trạng thái mà con rắn đã 3 lần ăn được khối màu đỏ.
Độ dài của con rắn sẽ là 4 khối (4 cells) màu xanh.

Chúng ta hãy tạo xử lý đối với cnt khi con rắn đã ăn được khối màu đỏ.

Hãy nhìn dòng code 43~45:
Mã:
    'Khi con ran di chuyen vao khoi block mau do (san moi) thi:
        If Cells(Y, X).Interior.ColorIndex = 3 Then
            cnt = cnt + 1
Đây là xử lý khi con rắn đã ăn được mồi (khối màu đỏ).
Tọa độ của con rắn sau khi đi ra khối màu đỏ, lúc này cnt tăng lên 1: cnt = cnt + 1.
Dòng code 65 thực hiện việc tô đè màu xanh lên cells màu đỏ.

Khi rắn đã 3 lần ăn mồi thì cnt sẽ được gán là 4.

Điều kiện để khối block biến mất là cnt < Cells(20, 3) : Điều kiện này thỏa mãn là cần thiết. Đây là thời điểm khối block đã có tuổi thọ là 5.
Cho tới khi điều kiện này còn chưa được thỏa mãn thì tuyệt đối khối block này không được biến mất, tiếp tục hiển thị là màu xanh.
Bạn có thể trì hoãn quá trình xóa khối block (xóa dấu vết di chuyển- con rắn đã đi qua) sau 3 vòng lặp.

(Còn nữa)
 

thanhphong

Thành viên
(tiếp theo)
Ta tiếp tục tìm hiểu kỹ hơn code của .
Dòng code 24~34:
Mã:
    'Phan doan huong di chuyen cua khoi Block
            Select Case muki
                Case 2
                    Y = Y + 1
                Case 4
                    X = X - 1
                Case 6
                    X = X + 1
                Case 8
                    Y = Y - 1
            End Select
Biến số muki (phương hướng) sẽ làm tăng X,Y.
Trong đó muki bằn 8 nghĩa là con rắn đi lên, bằng 2 là đi xuống, bằng 4 là đi sang trái, bằng 6 là đi sang phải.

Y = Y+1 : rắn di chuyển xuống, Y = Y-1: rắn di chuyển lên.

Code cho các nút bấm điều khiển rắn di chuyển:
Mã:
Private Sub CommandButtonLen_Click()
    If muki <> 2 Then
        muki = 8
    End If
End Sub

Private Sub CommandButtonPhai_Click()
    If muki <> 4 Then
        muki = 6
    End If
End Sub

Private Sub CommandButtonTrai_Click()
    If muki <> 6 Then
        muki = 4
    End If
End Sub

Private Sub CommandButtonXuong_Click()
    If muki <> 8 Then
        muki = 2
    End If
End Sub
Để có thể điều khiển được bằng các nút bấm này thì ta cần có DoEvents mà bạn thấy ở dòng code 68.

Tiếp theo là các dòng code 36~41:
Mã:
    'Phan doan Game ket thuc
        If Y < 3 Or Y > 17 Or X < 3 Or X > 17 Or Cells(Y, X).Interior.ColorIndex = 5 Then
            fin = True
            play = False
            cnt = cnt - 1
        End If
Khi rắn di chuyển ra ngoài phạm vi thì fin được gán là True để thoát khỏi vòng lặp đồng thời kết thúc game ( play gán là False).
(Còn nữa)
 

thanhphong

Thành viên
(tiếp theo)
Ta tiếp tục tìm hiểu kỹ hơn code của .
Dòng code 47~63.
Mã:
'Hien thi khoi block mau do (moi) vao vi tri ngau nhien
            Dim flag As Boolean
            flag = False
            
            Do Until flag = True
            
                Randomize
            
                i = Int(Rnd * 15 + 1) + 2
                j = Int(Rnd * 15 + 1) + 2
                
                If Cells(i, j).Interior.ColorIndex = xlNone Then
                    Cells(i, j).Interior.ColorIndex = 3
                    flag = True
                End If
            Loop
        End If
Vòng lặp Do~Loop thực hiện công việc tìm cells chưa bị tô màu (cells trong suốt). Tất nhiên quá trình lặp này sẽ kết thúc cho tới khi tìm thấy, ở đây ta có một biến cờ, là biến flag. Khi tìm thấy thì biến này được gán là True. Và khi biến này là True thì vòng lặp sẽ kết thúc.
Để đảm bảo tính ngẫu nhiên ở đây đã dùng .

Trên đây tôi đã giải thích toàn bộ nội dung code của .
 

vanthanhVBA

Thành viên
Step 3: Xây dựng game-Code cho nút Start Game.
chúng ta đã đi vào phần code chính liên quan tới chuyển động, cũng như rắn ăn được con mồi, và việc tạo hiển thị vị trí ngẫu nhiên cho mồi ra sao.
Ở phần này ta sẽ hợp code các phần đó để xây dựng game.

1. Code cho nút bấm Start:
Mã:
Private Sub CommandButton1_Click()
'Start
    If play = False Then
        Call khoitao
        Call VtriNgauNhien
        fin = False
        play = True
        X = 10
        Y = 10
        muki = 2
        Call block
    End If
End Sub
Đầu tiên thủ tục khoitao sẽ được gọi.
Tiếp theo, vị trí cho con mồi cần được xắp đặt ngẫu nhiên do đó thủ tục VtriNgauNhien được gọi.
Mã:
Public Sub VtriNgauNhien()
'Hien thi con moi vao vi tri cells trong mot cach ngau nhien
    Dim flag As Boolean
    flag = False
    
    Do Until flag = True
    
        Randomize
    
        i = Int(Rnd * 15 + 1) + 2
        j = Int(Rnd * 15 + 1) + 2
        
        If Cells(i, j).Interior.ColorIndex = xlNone Then
            Cells(i, j).Interior.ColorIndex = 3
            flag = True
        End If
    
    Loop
End Sub
Như vậy game đến đây đã được hoàn thành các bước chính. Bạn có thể download file demo ở đây:
Chú ý, để di chuyển rắn, bạn cần click vào các nút bấm trên giao diện game.

Nguồn tham khảo:
 
Top