|
HỒ LÔ BIẾN |
|
Lập trình trò chơi
15 bằng VB6
Ngô Bảo Khoa |
|
Trò chơi 15 là một trò chơi quen
thuộc: sau khi 15 ô số được xáo trộn, bạn cần di
chuyển các ô số sao cho chúng trở về vị trí ban đầu
(ô số chỉ có thể di chuyển qua ô trống ở cạnh nó). |
|

Các ô số chưa xáo trộn |

Các ô số bị xáo trộn |
|
Thay vì dùng các ô số, ta có thể
dùng một hình với kích thước 200x200 pixel, được
chia thành 16 phần nhỏ. Các phần nhỏ ấy bị xáo trộn
và người chơi phải sắp xếp lại thành hình hoàn
chỉnh. |
|
Phân tích |
|
Ta dùng mảng hai chiều Board
(kích thước 4x4, kiểu dữ liệu Integer) để thể hiện
các ô số trong chương trình. Mảng Board được đánh số
ở cột và hàng từ 1 đến 4. Giá trị Board(Row, Col)
là giá trị của ô số đang ở hàng Row và cột Col. |
|
Khi các ô số sắp xếp theo thứ tự ban đầu thì
Board(Row, Col)= (Row-1)*4+Col. Ví dụ như ô số ở vị
trí (3,2) là ô số 10 ((3-1)*4+2=10). |
|
Trong trò chơi này, chúng ta thể hiện một hình thay
cho các ô số. Để thể hiện hình ở vị trí (Row, Col),
ta cần tìm phần hình tương ứng với ô số Board(Row,
Col) rồi hiển thị phần hình này. Giả sử phần hình
nằm ở hàng Y, cột X, ta có: |
|
Y = Board(Row, Col) \ 4 + 1
X = Board(Row, Col) Mod 4 |
|
Tuy nhiên, giá trị các ô số ở cột thứ 4 chia cho 4
dư 0 (chứ không phải dư 4) nên ta phải xét thêm: |
|
If X = 0 Then
X = 4
Y = Y - 1
End If |
|
Các bước thực hiện |
|
1. Bạn tạo một dự án (Project) mới dạng Standard
EXE. Giá trị thuộc tính ScaleMode của biểu mẫu là “3
– Pixel”. Bạn thêm vào biểu mẫu hai PictureBox và
một CommandButton. CommandButton có thuộc tính Name
là cmdNewGame. Các thuộc tính của hai PictureBox
được trình bày ở bảng 1 và 2. |
|
1. Bạn tạo một dự án (Project) mới dạng Standard
EXE. Giá trị thuộc tính ScaleMode của biểu mẫu là “3
– Pixel”. Bạn thêm vào biểu mẫu hai PictureBox và
một CommandButton. CommandButton có thuộc tính Name
là cmdNewGame. Các thuộc tính của hai PictureBox
được trình bày ở bảng 1 và 2. |
|
Bảng 1: PictureBox thứ nhất: |
|
(Name) |
picBoard |
|
AutoRedraw |
True |
|
Enabled |
False |
|
Height |
204 |
|
ScaleMode |
3 - Pixel |
|
Visible |
True |
|
Width |
204 |
|
Bảng 2: PictureBox thứ hai: |
|
(Name) |
picSource |
|
AutoRedraw |
True |
|
AutoSize |
True |
|
Picture |
‘Bạn nạp vào hình có kích thước 200x200 pixel |
|
ScaleMode |
3 - Pixel |
|
Visible |
True |
|

Giao diện trò chơi |
|
2. Phần khai báo: |
|
Option Explicit
‘Chiều rộng một ô hình, tính bằng pixel
Const CellWidth = 50
Const SRCCOPY = &HCC0020
Dim Board(1 To 4, 1 To 4) As Integer |
|
3. Các thủ tục vẽ hình: |
|
‘Thủ tục DrawBlock vẽ hình một ô nổi có tọa độ
‘góc trên trái (x1, y1) và góc dưới phải (x2, y2)
‘trên picBoard.
Private Sub DrawBlock(x1 As Integer, y1 As Integer,
_
x2 As Integer, y2 As Integer)
picBoard.Line (x1, y2)-(x1, y1), QBColor(15)
picBoard.Line (x1, y1)-(x2, y1), QBColor(15)
picBoard.Line (x2, y1)-(x2, y2), QBColor(0)
picBoard.Line (x1, y2)-(x2, y2), QBColor(0)
End Sub |
|
‘Thủ tục DrawPiece dựa vào giá trị Board(Row, Col)
‘để tìm và vẽ hình tương ứng với ô số Board(Row,
Col)
‘ở vị trí (Row, Col) trên picBoard.
Private Sub DrawPiece(Row As Integer, Col As
Integer)
Dim X As Integer, Y As Integer
Y = Board(Row, Col) \ 4 + 1
X = Board(Row, Col) Mod 4
If X = 0 Then
X = 4
Y = Y - 1
End If
picBoard.PaintPicture picSource.Picture, _
(Col - 1) * CellWidth, (Row - 1) * CellWidth, _
CellWidth, CellWidth, (X - 1) * CellWidth, _
(Y - 1) * CellWidth, CellWidth, CellWidth, SRCCOPY
DrawBlock (Col - 1) * CellWidth, _
(Row - 1) * CellWidth, Col * CellWidth - 1, _
Row * CellWidth - 1
picBoard.Refresh
End Sub |
|
‘Thủ tục ClearPiece xóa đi ô hình ở vị trí
‘(Row, Col) trên picBoard.
Private Sub ClearPiece(Row As Integer, Col As
Integer)
picBoard.Line ((Col - 1) * CellWidth, _
(Row - 1) * CellWidth)-(Col * CellWidth - 1, _
Row * CellWidth - 1), QBColor(7), BF
End Sub |
|
4. Bắt đầu lượt chơi mới: |
|
Private Sub cmdNewGame_Click()
picBoard.Enabled = True
picBoard.Cls
cmdNewGame.Enabled = False
‘Khởi tạo những giá trị ban đầu của trò chơi
InitGame
End Sub |
|
Private Sub InitGame()
Dim xx(1 To 4) As Integer
Dim yy(1 To 4) As Integer
Dim Move As Integer
Dim i As Integer, j As Integer
‘Tọa độ của ô trống
Dim x0 As Integer, y0 As Integer |
|
‘Ô bên trái ô trống
xx(1) = -1: yy(1) = 0
‘Ô phía trên ô trống
xx(2) = 0: yy(2) = -1
‘Ô phía dưới ô trống
xx(3) = 0: yy(3) = 1
‘Ô bên phải ô trống
xx(4) = 1: yy(4) = 0 |
|
‘Sắp xếp các ô theo thứ tự
For i = 1 To 4
For j = 1 To 4
Board(i, j) = (i - 1) * 4 + j
Next j
Next i |
|
Ô cuối cùng là ô trống. Ô trống sẽ nhận giá trị 0.
Board(4, 4) = 0
x0 = 4
y0 = 4 |
|
‘Xác định ngẫu nhiên số lần di chuyển các ô
‘để xáo trộn chúng, ít nhất là 250 lần.
‘Bạn có thể thay đổi các giá trị này theo ý bạn.
Randomize
Move = Int(Rnd * 500) + 250 |
|
‘Xác định ngẫu nhiên một trong 4 ô quanh ô trống.
‘Nếu ô này “có tồn tại” (vì chỉ có 2 ô khác xung
quanh
‘ô ở góc và 3 ô khác xung quanh ô ở cạnh) thì di
chuyển
‘ô này đến ô trống và giá trị biến Move sẽ giảm đi
1.
Do While Move > 0
j = Int(Rnd * 4) + 1
If (y0 + yy(j) >= 1) And (x0 + xx(j) >= 1) And _
(y0 + yy(j) <= 4) And (x0 + xx(j) <= 4) Then
Board(y0, x0) = Board(y0 + yy(j), x0 + xx(j))
Board(y0 + yy(j), x0 + xx(j)) = 0
x0 = x0 + xx(j)
y0 = y0 + yy(j)
Move = Move - 1
End If
Loop |
|
‘Thể hiện các ô hình
For i = 1 To 4
For j = 1 To 4
If Board(i, j) <> 0 Then DrawPiece i, j
Next j
Next i
ClearPiece y0, x0 |
|
End Sub |
|
5. Hàm Inside(X As Single, Y As Single, x1 As
Integer, x2 As Integer, y1 As Integer, y2 As
Integer): |
|
Hàm Inside sẽ cho kết quả True nếu X nằm giữa x1 và
x2, Y nằm giữa y1 và y2. Nói cách khác, Inside có
giá trị True nếu điểm (X,Y) nằm trong hình chữ nhật
có góc trên trái (x1,y1) và góc dưới phải (x2,y2).
Nếu điểm (X,Y) nằm ngoài hình chữ nhật này, Inside
có giá trị False. |
|
Private Function Inside( _
X As Single, Y As Single, _
x1 As Integer, x2 As Integer, _
y1 As Integer, y2 As Integer)
If (X > x1) And (X < x2) And _
(Y > y1) And (Y < y2) Then
Inside = True
Else
Inside = False
End If
End Function |
|
6. Hàm Finish(): |
|
Hàm Finish sẽ cho giá trị True nếu người chơi đã
hoàn thành trò chơi, tức là sắp xếp được các ô hình
theo thứ tự ban đầu của chúng. Ngược lại Finish sẽ
mang giá trị False. |
|
Private Function Finish() As Boolean
Dim i As Integer, j As Integer
Finish = True
For i = 1 To 4
For j = 1 To 4
‘Không cần xét ô (4,4)
If i = 4 And j = 4 Then Exit Function
‘Nếu Board(i, j) không mang giá trị đáng lẽ
‘nó phải mang khi các ô được sắp xếp theo
‘thứ tự ban đầu thì có nghĩa là người chơi
‘chưa hoàn thành trò chơi, Finish = False.
If Board(i, j) <> (i - 1) * 4 + j Then
Finish = False
Exit For
End If
Next j
Next i |
|
End Function |
|
7. Thủ tục picBoard_MouseDown xử lý sự kiện
ấn phím trên vùng chơi: |
|
Private Sub picBoard_MouseDown(Button As Integer, _
Shift As Integer, X As Single, Y As Single) |
|
Dim xx(1 To 4) As Integer
Dim yy(1 To 4) As Integer
Dim Row As Integer, Col As Integer
Dim i As Integer, j As Integer |
|
xx(1) = -1: yy(1) = 0
xx(2) = 0: yy(2) = -1
xx(3) = 0: yy(3) = 1
xx(4) = 1: yy(4) = 0 |
|
‘Xác định ô nào được người chơi ấn chuột,
‘lưu giữ vào biến Row, Col
Row = 0
Col = 0
For i = 1 To 4
For j = 1 To 4
If Inside(X, Y, (j - 1) * CellWidth, _
j * CellWidth, (i - 1) * CellWidth, _
i * CellWidth) Then
Row = i
Col = j
Exit For
End If
Next j
Next i |
|
‘Người chơi có ấn chuột vào vùng chơi
If Row <> 0 And Col <> 0 Then |
|
‘Lần lượt xét 4 ô (ô có tồn tại) quanh ô
‘người chơi ấn chuột, nếu trong số 4 ô đó
‘có ô trống thì di chuyển ô người chơi vừa
‘ấn chuột đến ô trống này
For i = 1 To 4
If (Row + yy(i) >= 1) And (Col + xx(i) >= 1) _
And (Row + yy(i) <= 4) And (Col + xx(i) <= 4)
Then
If Board(Row + yy(i), Col + xx(i)) = 0 Then
Board(Row + yy(i), Col + xx(i)) = Board(Row,
Col)
DrawPiece Row + yy(i), Col + xx(i)
Board(Row, Col) = 0
ClearPiece Row,
Col
Exit For
End If
End If
Next i |
|
‘Xét xem sau mỗi lần di chuyển ô,
‘nếu người chơi đã hoàn thành trò chơi
‘thì ngưng trò chơi
If Finish Then
picBoard.Enabled = False
cmdNewGame.Enabled = True
‘Vẽ lại toàn bộ hình
picBoard.PaintPicture picSource, 0, 0, _
picBoard.ScaleWidth, picBoard.ScaleHeight, _
0, 0, picBoard.ScaleWidth, _
picBoard.ScaleHeight, SRCCOPY
End If |
|
End If
End Sub |
|
Vậy là bạn đã nắm được các bước chủ yếu tạo ra trò
chơi 15. Chúc bạn thành công! |
|
|