SỐ 107
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!

[Đầu trang]
Trang chủ
Nội lực "Peter Pan"
Cầu nối Intel Việt Nam
Chuyện trong tuần
Cõi người ta
Bình luận thị trường
Cõi Mô-bai
Chuyên đề
Bổ ngửa
Túi càn khôn IT
Hồ lô biến
Cảm về Game
Nhật ký e-CHÍP
Bản quyền Công ty Phần mềm & Truyền thông VASC
 99 Triệu Việt Vương HN; Tel: (04) 9782235 • email: echip@vasc.com.vn
Mọi chi tiết về kinh doanh và quảng cáo xin liên hệ Phòng Quảng cáo. Tel: (04) 9782077 kd@vasc.com.vn