Trò chơi và hệ nhị phân
Hệ nhị phân có vị trí hết sức quan trọng trong máy tính. Có một trò chơi đơn
giản cho thấy hệ nhị phân cũng có một vai trò quyết định trong chiến thuật để
người biết luôn luôn thắng. Ta tạm gọi là trò chơi LẤY HẠT.
Trò chơi như sau: có 3 đống hạt và ban đầu mỗi đống phải có ít nhất 1 hạt. Hai
người chơi (hoặc một người và máy tính), lần lượt thực hiện như sau: Với một số hạt đã cho,
người thứ nhất được quyền bố trí 3 đống sao cho mỗi đống có ít nhất 1 hạt; người thứ hai lấy một
số hạt theo nguyên tắc chỉ lấy trong một đống nào đó và phải lấy ít nhất 1 hạt hay có thể lấy tất
cả các hạt trong đống đó. Sau đó người thứ nhất lại phải lấy hạt theo nguyên tắc trên. Hai người
lần lượt lấy hạt theo nguyên tắc đó cho đến khi người nào sau cùng phải lấy 1 hạt duy nhất thì
người đó thua.
Với số hạt là 3 hoặc một số nguyên dương chẵn và khác 2n
(n là số nguyên dương), bao giờ cũng có một chiến thuật để
người được quyền bố trí số hạt đầu tiên chiến thắng. Với số
hạt là một số nguyên dương lẻ lớn hơn 3 hoặc số nguyên
dương chẵn 2n (n là số nguyên lớn hơn 1) mà người thứ
nhất bố trí, người thứ hai biết chiến thuật luôn luôn chiến
thắng (dĩ nhiên phải thực hiện đúng chiến thuật, không hề
sơ suất). Chiến thuật này đơn giản, chứng minh không quá
khó nhưng cần có kiến thức chuyển đổi một số nguyên từ
hệ thập phân sang hệ nhị phân và lưu ý cộng theo hệ thập phân của các số viết theo hệ nhị phân!
Sau đây là trò chơi LẤY HẠT viết một cách đơn giản bằng VB 6.0, trong đó số hạt giới hạn của
mỗi đống không quá 25 hạt và người chơi với máy.
Tạo giao diện trò chơi
Chạy VB 6.0, chọn ứng dụng 'Standard EXE', bạn có form tên là Form1. Trong form này bạn tạo
các điều khiển sau (chỉ nêu một số tính chất chính, các tính chất khác có thể sử dụng mặc định;
dùng font tiếng Việt nào đó; các mảng 1, 2, 3 phải đặt tương ứng):
Vị trí, kích thước của form1 và điều khiển tuỳ bạn bố trí sao cho đẹp và thuận tiện.
Nhập code
Trong cửa sổ Code của Form1 bạn nhập các đoạn code theo mã nguồn mẫu (tải về mã nguồn trên
website của TGVT-PCW VN). Chiến thuật nhị phân được thể hiện trong thủ tục MayChoi().
Sau khi nhập code xong, biên dịch thành tập tin EXE để sử dụng.
Hướng dẫn vắn tắt cách chơi
- Khi chạy chương trình bạn chọn một trong hai việc: 'Máy bố trí hạt' hoặc 'Bạn bố trí hạt', và sau
đó nhấn nút lệnh 'Bắt đầu'.
- Nếu bạn bố trí hạt trước, bạn gõ số hạt trong TextBox và nhấn nút lệnh 'Số hạt:' trong từng
đống.
- Sau khi bạn bố trí số hạt đủ ba đống sẽ xuất hiện nút lệnh 'Máy thực hiện'. Bạn nhấn nút lệnh
này (Vì muốn người thi đấu có thời gian xem máy thực hiện nên ở đây tôi không viết chương
trình cho máy tự động lấy hạt, nếu không bạn sẽ không theo dõi kịp). Cứ lần lượt thực hiện cho
đến kết thúc.
- Nếu bạn muốn lấy hạt: hãy chọn CheckBox trong đống nào đó, mỗi CheckBox được chọn là 1
hạt sẽ xoá. Sau đó click nút lệnh 'Xoá hạt chọn'.
- Nút lệnh 'Bắt đầu lại' dùng khi bạn muốn chơi lại trò chơi mà không chờ kết thúc.
Frame: Thủ tục MayChoi() For i = 0 To 2
If X(i Mod 3) + X((i + 1) Mod 3) = 1
Dim i As Integer, n As Integer, j As Then
Integer, k As Integer ' Lấy hết các hạt của đống còn lại (nhiều
Dim XX As Single hơn 1):
Dim Y(0 To 2) As String z = (i + 2) Mod 3
Dim YY As Single d = Coso10(X(z))
Dim a, ZZ Exit For
For i = 0 To 2 End If
Hat(i).Enabled = False Next i
SoHat(i).Enabled = False 'Ngược lại:
Next i Else
For i = 0 To 24 ' Chú ý: các số viết trong hệ nhị phân
If Check0(i).Visible = True And nhưng
Check0(i).Value = 1 Then ' cộng theo hệ thập phân!
Check0(i).Value = 0 XX = X(0) + X(1) + X(2)
If Check1(i).Visible = True And ' Xác định z cho đống nhiều hạt nhất:
Check1(i).Value = 1 Then If X(0) > X(1) And X(0) > X(2) Then z
Check1(i).Value = 0 =0
If Check2(i).Visible = True And If X(1) > X(2) And X(1) > X(0) Then z
Check2(i).Value = 1 Then =1
Check2(i).Value = 0 If X(2) > X(0) And X(2) > X(1) Then z
Next i =2
' Ghi vào List một lần: n = Len(Trim(XX))
If h = True Then ' Chuyển đổi thành chuỗi có chiều dài là
List1.AddItem 'BẠN: ' & vbTab & n:
SoHat(0).Text & vbTab & SoHat(1) Y(z) = CStr(X(z))
& vbTab & SoHat(2) Y((z + 1) Mod 3) = String$(n -
h = False Len(Trim(X((z + 1) Mod 3))), '0') &
End If CStr(X((z + 1) Mod 3))
' Nếu có ít nhất hai đống cùng số hạt: Y((z + 2) Mod 3) = String$(n -
If (X(0) - X(1)) * (X(1) - X(2)) * Len(Trim(X((z + 2) Mod 3))), '0') &
(X(2) - X(0)) = 0 Then CStr(X((z + 2) Mod 3))
For j = 0 To 2 'Tìm chữ số của XX có trị là 1 hoặc 3:
If X(j Mod 3) = X((j + 1) Mod 3) For i = 1 To n
Then If Mid(XX, i, 1) = 1 Or Mid(XX, i, 1) =
' Nếu hai đống có số hạt bằng 0 thì 3 Then
(đống còn lại phải có số hạt lớn hơn 'Xác định lại z khi gặp chữ số 1 ở cột i
1): sau đó thoát ngay vòng lặp k:
If X(j Mod 3) = 0 Then For k = 0 To 2
If X((j + 2) Mod 3) > 1 Then If Mid(Y((z + k) Mod 3), i, 1) = 1 Then
z = (j + 2) Mod 3 z = (z + k) Mod 3
d = Coso10(X(z)) - 1 Exit For
Exit For End If
End If Next k
End If Exit For
' Nếu hai đống có số hạt bằng 1 thì: End If
If X(j Mod 3) = 1 Then Next i
' Nếu số hạt đống còn lại là 0 hay 1 ' Tính tổng của hai đống kia theo hệ thập
thì chọn đống (j mod 3): phân:
If X((j + 2) Mod 3) = 0 Or X((j + 2) YY = X((z + 1) Mod 3) + X((z + 2) Mod
Mod 3) = 1 Then 3)
z = j Mod 3 ' Xác định ZZ là số hạt của đống z còn
d=1 lại sau khi lấy đi (theo hệ nhị phân):
Exit For ZZ = ''
End If For i = 1 To Len(Trim(YY))
' Nếu số hạt đống còn lại lớn hơn 1 a = Mid(YY, i, 1)
thì chọn đống này và lấy đi chỉ chừa ZZ = ZZ & (a Mod 2)
1 hạt: Next i
If X((j + 2) Mod 3) > 1 Then ZZ = Val(ZZ)
z = (j + 2) Mod 3 ' Xác định số hạt phải lấy đi của đống z:
d = Coso10(X(z)) - 1 ' Khi XX toàn chữ số chẵn thì máy sẽ
Exit For thua, khi đó
End If ' ZZ=X(z), chọn d=1 để chờ thời cơ bạn
End If sơ suất
' Nếu hai đống có số hạt bằng nhau và If ZZ = X(z) Then
lớn hơn 1 thì: d=1
If X(j Mod 3) > 1 Then Else
' Nếu đống còn lại là 0, máy sẽ thua d = Coso10(X(z)) - Coso10(ZZ)
nếu bạn biết chiến thuật, End If
' chọn d=1 để 'câu giờ' và chờ bạn sơ End If
suất: End If
If X((j + 2) Mod 3) = 0 Then g = True
z = j Mod 3 Call Boc
d=1 g = False
Exit For ' Kiểm tra kết quả
End If KetQua.ForeColor = vbBlue
' Nếu đống còn lại có từ 1 hạt trở lên If T(0) + T(1) + T(2) = 1 Then
thì lấy đi hết số hạt của đống này: KetQua.Caption = 'Xin lỗi! Bạn đã
' Bạn sẽ thua! thua!'
If X((j + 2) Mod 3) > 0 Then For i = 0 To 2
z = (j + 2) Mod 3 Xoa(i).Enabled = False
d = Coso10(X(z)) Next i
Exit For Option1.Visible = True
End If Option2.Visible = True
End If ChoiMoi.Visible = False
End If BatDau.Visible = True
Next j BatDau.SetFocus
' Ngược lại, không có hai đống nào có h = True
số hạt bằng nhau: Else
Else For i = 0 To 2
' Nếu có hai đống, một đống 0 hạt và Xoa(i).Enabled = True
một đống có 1 hạt: Next i
' (Do các X không âm) KetQua.Caption = 'Bạn chọn và bóc
If X(0) + X(1) = 1 Or X(1) + X(2) = hạt!'
1 Or X(2) + X(0) = 1 Then End If
MayChoi.Enabled = False
End Sub