Làm game Crazy Math với AutoIT

Luật của game Crazy Math là bạn phải trả lời thật nhanh 10 câu hỏi ngẫu nhiên về các phép toán cộng, trừ, nhân, chia giữa hai số hạng (thời gian tối đa cho mỗi câu là 3 giây), cứ mỗi câu đúng sẽ nhận được 1 điểm.






📕 KIẾN THỨC CẦN BIẾT

Bạn cần biết cơ bản về AutoIT để đọc hiểu bài viết này. Bạn có thể xem tutorial AutoIT tại đây, hoặc học vỡ lòng AutoIT qua video tại đây.


💡 MÔ TẢ TRÒ CHƠI

Các bạn có thể xem chi tiết mô tả trò chơi qua hình dưới đây:


🚀 LET'S DO IT

Bước 1: Nhập tên người chơi. Chúng ta sử dụng InputBox trong AutoIT để mời user nhập tên của họ vào, và gán giá trị InputBox nhận được cho biến $user_name.

Global $user_name
Do
$user_name = InputBox ("Mời nhập tên","Chào mừng bạn đến với trò chơi CRAZY MATH. Xin mời bạn nhập tên để tiếp tục:"&@CRLF&'Ấn nút Cancel để thoát')
If @error = 1 Then Exit
Until $user_name <> ''
Mục đích của việc sử dụng vòng lặp Do, Until là để đảm bảo tính đúng của chương trình, bắt người dùng nhập lại user name nếu như họ không nhập hoặc nhập ký tự rỗng. Mục đích của việc sử dụng If @error = 1 là để biết được khi nào user bấm vào nút Cancel để thoát khỏi chương trình.

Bước 2: Chọn tính năng. Tương tự như nhập tên, ta cũng sử dụng InputBox để mời user chọn tính năng và gán giá trị nhận được cho biến $game_mode.

$game_mode = InputBox("CRAZY MATH","Mời "&$user_name&" chọn tính năng bằng cách điền vào ô bên dưới và bấm OK:"&@CRLF&'- Gõ "1": Bắt đầu chơi'&@CRLF&'- Gõ "2": Xem bảng điểm'&@CRLF&'- Còn lại: Thoát')
Vậy nếu $game_mode = 1 thì game bắt đầu, $game_mode = 2 thì xem điểm và còn lại thì thoát game. Ta sử dụng cấu trúc điều kiện để phân loại các trường hợp trên.

If Number($game_mode) = 1 Then
; game bat dau
Elsef Number($game_mode) = 2 Then
; xem diem
Else
; ket thuc
Exit
Endif
Bước 3: Chơi game. Luật game giới hạn cho mỗi câu hỏi tối đa 3 giây trả lời, và có 10 câu như vậy. Nội dung câu hỏi là những phép toán cộng trừ nhân chia giữa 2 số hạng. Vì vậy việc đầu tiên, chúng ta phải thiết lập các câu hỏi.
Đầu tiên, tôi tạo 1 mảng $so_hang có 2 ngăn, ngăn 1 là số hạng thứ nhất và ngăn 2 là số hạng thứ hai, cả hai ngăn này đều nhận giá trị là số nguyên, random từ 1 đến 9.

Local $so_hang[2]
$so_hang[0] = Random(1,9,1) ; số hạng 1
$so_hang[1] = Random(1,9,1) ; số hạng 2
Tuy nhiên để đơn giản hóa dòng này, ta có thể viết như sau:

Local $so_hang[2] = [Random(1,9,1),Random(1,9,1)]
Tiếp theo, tôi Random 1 phép toán +, - hoặc *, /. Và lưu vào biến $phep_tinh

Local $cac_phep_tinh = StringSplit("+,-,*,/",",")
Local $phep_tinh = cac_phep_tinh[Random(1,4,1)]
Tuy nhiên để đơn giản hóa dòng này, ta có thể viết như sau:

Local $phep_tinh = StringSplit("+-*/","")[Random(1,4,1)]
Như vậy, bài toán của tôi sẽ có dạng:

Local $bai_toan = $so_hang[0]&$phep_tinh&$so_hang[1]
Việc tiếp theo là tôi lấy kết quả của phép toán trên để đem đi so sánh với Input người dùng.

Local $dap_an
If $phep_tinh = '+' Then $dap_an = $so_hang[0]+$so_hang[1]
If $phep_tinh = '-' Then $dap_an = $so_hang[0]-$so_hang[1]
If $phep_tinh = '*' Then $dap_an = $so_hang[0]*$so_hang[1]
If $phep_tinh = '/' Then $dap_an = Int($so_hang[0]/$so_hang[1])
Lý do dùng Int() ở phép tính chia, vì để đơn giản hóa trò chơi, chúng ta sẽ chỉ nhận kết quả phần nguyên của 1 phép toán chia (ví dụ: 1/3=0, 2/3=0, 3/3=1, 6/3=2, 7/3=2,...)
Nhưng ta có thể làm bước lấy đáp án nhanh gọn hơn bằng cách sử dụng hàm Execute để cộng trừ các giá trị trong một chuỗi, ví dụ '1+1' để bình thường trong biến $dap_an thì không thể tự cộng được do nó là chuỗi, nhưng Excute('1+1') thì được. Do đó:

Local $dap_an = Int(Execute($so_hang[0]&$phep_tinh&$so_hang[1]))
Như vậy, ta đó có phép toán, có đáp án, lúc này ta hiển thị câu hỏi và yêu cầu người dùng nhập đáp án vào:

Local $tip = $phep_tinh == '/' ? ' (chỉ lấy phần nguyên)' : ''
Local $tra_loi = InputBox("CRAZY MATH","Câu số "&$i&" - Điểm "&$user_point&@CRLF&$so_hang[0]&" "&$phep_tinh&" "&$so_hang[1]&" = ?" & $tip,"","",-1,-1,Default,Default,3)
Dòng đầu tiên, biến $tip là một dạng như cấu trúc if, nghĩa là nếu phép tính mà bằng dấu chia thì biến $tip sẽ nhận giá trị 'chỉ lấy phần nguyên', ngược lại biến $tip rỗng.
Dòng thứ 2 là InputBox, hiển thị câu hỏi cho người dùng, với timeout là 3 (giây).
Tiếp theo ta kiểm tra xem, người dùng có nhập đúng đáp án không rồi cộng điểm bằng cách:

If $tra_loi <> '' and Number($tra_loi) = Number($dap_an) Then $user_point += 1
Vì sao $tra_loi phải khác rỗng (''): vì nếu trả lời bằng rỗng thì khi so sánh với số, AutoIT sẽ tự hiểu $tra_loi = 0, mà giả sử 3-3 mà user nhập rỗng thì theo luật user sai, nhưng AutoIT sẽ so sánh và cho nó đúng, vì vậy chúng ta cần điều kiện để loại trừ.
Vì sao: Number($tra_loi) và Number($dap_an), vì $tra_loi và $dap_an của chúng ta có thể nhận kiểu dữ liệu là chuỗi, để so sánh chúng ta phải ép kiểu về để đảm bảo tính đúng của bài toán.
Như vậy, việc còn lại chúng ta chỉ cần lồng hàm For cho chương trình chạy đủ 10 lần, tức 10 câu hỏi.

$user_point = 0
For $i = 1 To 10
 Local $phep_tinh = StringSplit("+-*/","")[Random(1,4,1)]
 Local $so_hang[2] = [Random(1,9,1),Random(1,9,1)]
 Local $dap_an = Int(Execute($so_hang[0]&$phep_tinh&$so_hang[1]))
 Local $tip = $phep_tinh == '/' ? ' (chỉ lấy phần nguyên)' : ''
 Local $tra_loi = InputBox("CRAZY MATH","Câu số "&$i&" - Điểm "&$user_point&@CRLF&$so_hang[0]&" "&$phep_tinh&" "&$so_hang[1]&" = ?" & $tip,"","",-1,-1,Default,Default,3)
 If $tra_loi <> '' and String(Number($tra_loi)) = $dap_an Then $user_point += 1
Next
Cuối cùng, sau khi trả lời xong 10 câu hỏi, chúng ta sẽ lưu điểm, nhưng nếu điểm cũ của người chơi > điểm hiện tại thì không lưu. Vì vậy, ta dùng hàm If để loại trừ như sau:

$user_last_point = IniRead($file_ini,"CRAZYMATH",$user_name,0)   
If $user_last_point < $user_point Then
 IniWrite($file_ini,"CRAZYMATH",$user_name,$user_point)
 $user_last_point = $user_point
EndIf
Bước 4: Xem điểm, để xem lại điểm, ta chỉ cần đọc lại điểm đã lưu bằng InIRead rồi thông báo cho người dùng, nếu như không tìm thấy điểm, thì trả về điểm 0 cho người dùng.

Local $user_last_point = IniRead($file_ini,"CRAZYMATH",$user_name,0)
MsgBox(64,"CRAZY MATH","Điểm của bạn "&$user_name&" là: "&$user_last_point)
Bước 5: Hoàn tất, để chương trình hoàn tất, ta đặt toàn bộ chương trình vào vòng lặp While 1 ... WEnd để đảm bảo chương trình được gọi lại sau khi chơi game xong hoặc xem điểm xong mà không thoát, chương trình chỉ thoát khi ta nhập số khác vào Inputbox gán cho $game_mod mà thôi

While 1
; toàn bộ code từ lúc chọn game mode
WEnd
Xin chúc mừng, về cơ bản bạn đã hoàn tất kỹ thuật lập trình game Crazy Math đơn giản. Bạn có thể thêm thắt các độ khó (từ 2 đến 3, 4, 5 số hạng với đa dạng phép toán,...) để trò chơi hoàn thiện hơn ^^.


CODE MẪU

Bạn có thể xem chương trình hoàn chỉnh tại đây

Xin chào, mình là opdo - một đứa mê những dòng code vô tận. Rất cám ơn vì bạn đã ghé thăm blog của mình ^^. Hi vọng được bạn ủng hộ để blog mình phát triển hơn

Share this

Related Posts

Previous
Next Post »