Console Tic-Tac-Toe App (tiếp theo)

Tram Ho

Chúng ta sẽ khởi đầu code thật tự nhiên với procedure Main và các comment về những bước cần thực hiện trong code.

  1. Ngay khi khởi chạy app thì chúng ta sẽ cần phải in ra màn hình tùy chọn để người dùng User chọn ký hiệu X hoặc O để ghi vào bảng Tic-Tac-Toe và thể hiện các bước đi của User và máy tính Computer.
  2. Scan lựa chọn nhập liệu của User và lưu lại trạng thái User_Symbol.
  3. Sau khi người dùng đã chọn ký hiệu đại diện thì app cần thực hiện khởi tạo State lưu trữ trạng thái của gameboard bao gồm các bước đi của User, và các bước của Computer, và cả các ô trống còn lại. State này có thể có chứa thêm các trạng thái khác như nhận định Match_Status để thể hiện là ván cờ đã kết thúc sau một bước đi nào đó của User hoặc Computer.

Để khởi đầu đơn giản thì chúng ta sẽ mặc định là User sẽ luôn luôn được thực hiện bước đi trước. Và trình tự các thủ tục procedure tiếp theo cần thực hiện là:

  1. In ra bảng Tic-Tac-Toe để người dùng User có thể theo dõi trạng thái hiện tại của gameboard và tính toán bước đi.
  2. Nhận kết quả nhập liệu để mô tả bước đi mà User muốn thực hiện.
  3. Cập nhật trạng thái State của ứng dụng tương ứng với bước đi vừa rồi của User.
  4. Kiểm tra trạng thái của gameboard xem ván cờ đã kết thúc chưa. Nếu kết thúc rồi thì User thắng hay là kết quả hòa.

Tương tự, với lượt đi của máy tính Computer thì chúng ta cũng có các thủ tục như trên:

  1. In ra bảng Tic-Tac-Toe để người dùng User có thể theo dõi trạng thái hiện tại của gameboard và tính toán bước đi.
  2. Gọi trình tự tạo bước đi cho Computer dựa trên trạng thái của gameboard hiện tại.
  3. Cập nhật trạng thái State của ứng dụng tương ứng với bước đi vừa rồi của Computer.
  4. Kiểm tra trạng thái của gameboard xem ván cờ đã kết thúc chưa. Nếu kết thúc rồi thì Computer thắng hay là kết quả hòa.

Sau một lượt di chuyển của UserComputer như thế này thì chúng ta chỉ cần lặp lại các thủ tục từ 3 .. 10 cho đến khi ván cờ kết thúc.

Put_Symbol_Menu;

Đây là kết quả in ra dự kiến của Put_Symbol_Menu;Get_User_Symbol;:

Chúng ta có thể thiết kế cú pháp sử dụng của các procedure khởi đầu này ở dạng tương tự với Put (Symbol_Menu);Get (User_Symbol); của thư viện Ada.Text_IO mà chúng ta đã biết. Tuy nhiên riêng đối với thao tác Put như vậy thì việc định nghĩa một hằng constant chứa toàn bộ nội dung của Symbol_Menu được định dạng thành các dòng và khoảng trống thụt vào như trên sẽ khá rườm rà trong Ada.

Vì vậy nên ở đây chúng ta sẽ thực hiện thao tác Put_Symbol_Menu với nội dung của menu được đặt trực tiếp bên trong procedure này, và định dạng bằng cách in ra từng dòng. Còn thao tác Get_User_Symbol sẽ được thiết kế dạng Get (User_Symbol); Về việc lưu lại kiểu ký hiệu mà User đã chọn thì tạm thời chúng ta sẽ định nghĩa một kiểu enum Symbol và lưu vào một biến cục bộ của procedure Main.

Và trong trường hợp lựa chọn mà người dùng nhập vào không hợp lệ thì chúng ta cần thêm một kiểu exception Error tự định nghĩa để raise và xử lý lại thao tác yêu cầu nhập lựa chọn.

Code triển khai của Put_Symbol_Menu; thì không có gì đáng lưu ý bởi vì chúng ta chỉ đơn giản là Put_Line từng dòng nội dung trong kết quả mong muốn.

Get (User_Symbol);

Thao tác Get (User_Symbol) cũng khá đơn giản và trình tự cần thực hiện là chúng ta sẽ Put thông báo Your choice: để con trỏ không nhảy duống dòng mới và nội dung nhập liệu của User sẽ xuất hiện trên cùng dòng. Sau đó thực hiện thao tác Get (User_Input) để hiện con trỏ nhập liệu và nhận vào chuỗi thông tin.

Việc còn lại là chuyển chuỗi nhập liệu thành giá trị số nguyên Chosen_Number bởi vì nội dung của menu đang gợi ý người dùng nhập vào 1 hoặc 2 để chọn ký hiệu X hoặc O. Sau đó tạo cấu trúc điều kiện để thực hiện gán kết quả phù hợp cho tham số User_Symbol, hoặc raise SYMBOL_CHOICE_ERROR nếu người dùng nhập lựa chọn không hợp lệ.

Phần thân của procedure là khối begin .. exception .. end ở đây vẫn khá dễ theo dõi do code cần thực hiện cũng không dài lắm. Riêng phần exception thì ở đây chúng ta có thể sử dụng others để bao gồm cả những ngoại lệ khác ví dụ như thao tác chuyển kiểu dữ liệu sang từ User_Input sang Chosen_Number.

Một lưu ý khác là procedure Get mà chúng ta tự định nghĩa sẽ được xem là một phiên bản overload song song với Ada.Text_IO.Get. Với chữ ký biểu trưng Get (out Symbol) có thể được trình biên dịch dễ dàng phân biệt với Get (out String) của Ada.Text_IO. Vì vậy nên khi chúng ta sử dụng Get (User_Input) ở đầu procedure và sau đó lại gọi Get (User_Symbol) ở phần exception sẽ không cần tham chiếu từ tên của các package để phân biệt.


Cuối cùng là code sử dụng tại Main, chúng ta cần bổ sung biến cục bộ User_Symbol để lưu ký hiệu mà người dùng đã chọn trong suốt ván cờ.
Chia sẻ bài viết ngay

Nguồn bài viết : Viblo