Bộ đôi thủ tục tiếp theo là Put_Chess_Board;
và Get_User_move;
lại rất tương đồng với đoạn xử lý Put_Symbol_Menu;
và Get (User_Symbol);
trước đó.
Put_Chess_Board;
Khởi đầu mỗi ván cờ, chúng ta sẽ có một bảng Tic-Tac-Toe với các ô được đánh số 1 .. 9
để người dùng có thể định vị và nhập lựa chọn ô muốn đánh dấu.
+ - - + - - + - - + | 2 | 9 | 4 | + - - + - - + - - + | 7 | 5 | 3 | + - - + - - + - - + | 6 | 1 | 8 | + - - + - - + - - +
Và nếu như sử dụng cách đánh số các ô trên bảng như thế này thì khi kiểm tra để cập nhật Match_Status
sau mỗi bước đi của User
hoặc Computer
, thì chúng ta sẽ kiểm tra xem có bất kỳ bộ 3 số nào trong tập User_Set
hoặc Computer_Set
có tổng bằng 15
hay không. Nếu có, thì có nghĩa là User
hoặc Computer
đã hoàn thành được một đường thẳng nào đó trên bảng và thắng ván cờ đó.
Giả sử User_Symbol
là X
thì ký hiệu còn lại O
sẽ là của Computer
, và chúng ta sẽ tùy vào dữ liệu của User_Set
và Computer_Set
để ghi các ký hiệu tương ứng thay thế vào vị trí của các chữ số trong bảng Tic-Tac-Toe. Như vậy trình in Put_Chess_Board
này có phức tạp hơn Put_Symbol_Menu
một chút và ở vị trí của mỗi chữ số, chúng ta sẽ cần một function Area_Image
để xác định ký ký tự được in ra là ký hiệu X
hay O
, hay chính chữ số đó.
package Console_IO is type Symbol is (X, O); SYMBOL_CHOICE_ERROR : exception; procedure Put_Symbol_Menu; procedure Get (User_Symbol : out Symbol); procedure Put_Chess_Board ( App_State : in State ; User_Symbol : in Symbol ) ; -- return Nothing function Area_Image ( Area : in Digit ; App_State : in State ; User_Symbol : in Symbol ) return String;
end Console_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions; package body Console_IO is procedure Put_Symbol_Menu is ... procedure Get (User_Symbol : out Symbol) is ... procedure Put_Chess_Board ( App_State : in State ; User_Symbol : in Symbol ) is ... function Area_Image ( Area : in Digit ; App_State : in State ; User_Symbol : in Symbol ) return String is ... end Console_IO;
Trong Put_Chess_Board
thì chúng ta vẫn thực hiện in ra từng dòng copy/paste
từ kết quả dự kiến. Và ở vị trí của các chữ số thì chúng ta cần sử dụng coupling function
như đã nói ở trên để xác định ký tự sẽ được in ra.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions; package body Console_IO is -- ... procedure Put_Chess_Board ( App_State : in State ; User_Symbol : in Symbol ) is begin Put_Line ("+ - - + - - + - - + "); Put_Line ("| " & Area_Image (2, App_State, User_Symbol) & " | " & Area_Image (9, App_State, User_Symbol) & " | " & Area_Image (4, App_State, User_Symbol) & " | "); Put_Line ("+ - - + - - + - - + "); Put_Line ("| " & Area_Image (7, App_State, User_Symbol) & " | " & Area_Image (5, App_State, User_Symbol) & " | " & Area_Image (3, App_State, User_Symbol) & " | "); Put_Line ("+ - - + - - + - - + "); Put_Line ("| " & Area_Image (6, App_State, User_Symbol) & " | " & Area_Image (1, App_State, User_Symbol) & " | " & Area_Image (8, App_State, User_Symbol) & " | "); Put_Line ("+ - - + - - + - - + "); end Put_Chess_Board; -- function Area_Image ... end Console_IO;
Và ở Area_image
, thao tác kiểm tra chữ số được truyền vào đang thuộc *_Set
nào sẽ được ủy thác cho một function
khác để duy trì logic xử lý ký tự in ra với các nhánh lệnh dễ theo dõi.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions; package body Console_IO is -- ... function Area_Image ( Area : in Digit ; App_State : in State ; User_Symbol : in Symbol ) return String is Computer_Symbol : Symbol; Result : String := "0"; begin Computer_Symbol := (if User_Symbol = X then O else X); -- if Found (Area, App_State.User_Set) then Result := Symbol'Image (User_Symbol); elsif Found (Area, App_State.Computer_Set) then Result := Symbol'Image (Computer_Symbol); else -- Found in App_State.Common_Set case Area is when 1 => Result := "1"; when 2 => Result := "2"; when 3 => Result := "3"; when 4 => Result := "4"; when 5 => Result := "5"; when 6 => Result := "6"; when 7 => Result := "7"; when 8 => Result := "8"; when 9 => Result := "9"; when others => Result := "0"; end case; end if; -- return Result; end Area_Image; end Console_IO;
Phép kiểm tra xem có tìm thấy Found
ô trống Area
trong một *_Set
nào đó hay không - rất có thể sẽ được sử dụng lại và không hẳn thuộc về mảng làm việc Input/Output
với cửa sổ Console
; Vì vậy nên chúng ta sẽ định nghĩa tại package App_Model
.
package App_Model is -- ... function Found (Area : Digit; Move_Set : Digit_Array) return Boolean; end App_Model;
package body App_Model is -- procedure Init ... function Found ( Area : Digit ; Move_Set : Digit_Array ) return Boolean is Result : Boolean := FALSE; begin for Index in Move_Set'Range loop if Area = Move_Set (Index) then Result := TRUE; end if; end loop; -- return Result; end Found; end App_Model;
Và cuối cùng là code sử dụng ở Main
, chúng ta sẽ tạm thời thêm vào một vài câu lệnh để thể hiện một bước đi của User
và một bước đi của Computer
ở phía trước câu lệnh in bảng để kiểm tra logic hoạt động của Area_Image
và `Found (Area, Move_Set).
with Ada.Text_IO; use Ada.Text_IO;
with App_Model; use App_Model;
with Console_IO; use Console_IO; procedure Main is User_Symbol : Symbol; App_State : State;
begin Put_Symbol_Menu; Get (User_Symbol); Init (App_State); -- loop Put_Chess_Board (App_State, User_Symbol); -- Put_Line ("User Moved: 1"); App_State.Common_Set (1) := 0; App_State.User_Set (1) := 1; -- Put_Line ("Computer Moved: 9"); App_State.Common_Set (9) := 0; App_State.Computer_Set (9) := 9; -- Put_Chess_Board (App_State, User_Symbol); -- 4. Get_User_Move -- 5. Update_User_Set -- 6. Update_Match_Status -- -- 7. Put_Chess_Board -- 8. Get_Computer_Move -- 9. Update_Computer_Set -- 10. Update_Match_Status -- -- exit when App_State.Match_Status /= PLAYING; -- end loop
end Main;
alr run Choose your Symbol ... 1. Letter 'X' 2. Letter 'O'
Your choice: 1
You've chosen: X
+ - - + - - + - - +
| 2 | 9 | 4 |
+ - - + - - + - - +
| 7 | 5 | 3 |
+ - - + - - + - - +
| 6 | 1 | 8 |
+ - - + - - + - - +
User Moved: 1
Computer Moved: 9
+ - - + - - + - - +
| 2 | O | 4 |
+ - - + - - + - - +
| 7 | 5 | 3 |
+ - - + - - + - - +
| 6 | X | 8 |
+ - - + - - + - - +
Get_User_Move;
Thao tác Get_User_Move;
cũng có thể thiết kế với cú pháp sử dụng giống như Get (User_Symbol);
trước đó. và kết quả sẽ được lưu lại vào biến cục bộ User_move
của procedure Main
. Trong trường hợp giá trị người dùng nhập vào ngoài khoảng 1 .. 9
thì chúng ta sẽ cần phải phát động ngoại lệ để đưa ra thông báo và yêu cầu thực hiện lại việc nhập liệu.
with App_Model; use App_Model; package Console_IO is type Symbol is (X, O); SYMBOL_CHOICE_ERROR : exception; MOVE_CHOICE_ERROR : exception; procedure Put_Symbol_Menu; procedure Get (User_Symbol : out Symbol); procedure Put_Chess_Board ... procedure Get (User_Move : out Digit); function Area_Image ... return String;
end Console_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions; package body Console_IO is -- ... procedure Get (User_Move : out Digit) is User_Input : String := "0"; Chosen_Number : Integer; begin Put ("Your move: "); Get (User_Input); Chosen_Number := Integer'Value (User_Input); case Chosen_Number is when 0 => raise MOVE_CHOICE_ERROR; when others => User_Move := Chosen_Number; end case; exception when others => Put_Line ("Choice number should be in 1 .. 9"); Get (User_Move); -- end when end Get; -- function Area_Image ... end Console_IO;
Và ở code sử dụng tại Main
chúng ta sẽ tạm thời thêm lệnh Put_Line
để kiểm tra kết quả nhập liệu.
with Ada.Text_IO; use Ada.Text_IO;
with App_Model; use App_Model;
with Console_IO; use Console_IO; procedure Main is User_Symbol : Symbol; App_State : State; User_Move : Digit;
begin Put_Symbol_Menu; Get (User_Symbol); Init (App_State); -- loop Put_Chess_Board (App_State, User_Symbol); Get (User_Move); Put_Line ("User Moved: " & Digit'Image (User_Move)); -- 5. Update_User_Set -- 6. Update_Match_Status -- -- 7. Put_Chess_Board -- 8. Get_Computer_Move -- 9. Update_Computer_Set -- 10. Update_Match_Status -- -- exit when App_State.Match_Status /= PLAYING; -- end loop
end Main;
Choose your Symbol ... 1. Letter 'X' 2. Letter 'O'
Your choice: 1
You've chosen: X
+ - - + - - + - - +
| 2 | 9 | 4 |
+ - - + - - + - - +
| 7 | 5 | 3 |
+ - - + - - + - - +
| 6 | 1 | 8 |
+ - - + - - + - - +
Your move: 0
Choice number should be in 1 .. 9
Your move: A
Choice number should be in 1 .. 9
Your move: 1
User Moved: 1
(chưa đăng tải) [Procedural Programming + Ada] Bài 20 - Console Tic-Tac-Toe App (tiếp theo)