Thủ tục cuối cùng trong lượt di chuyển của User là cập nhật trạng thái của ván cờ Update_Match_Status;. Thủ tục này cũng sẽ được sử dụng lại ở lượt di chuyển của Computer giống như Put_Chess_Board;. Như vậy là chúng ta viết code rẽ nhánh bao gồm tất cả các trạng thái tiềm năng của Match_Status đã định nghĩa bởi kiểu Status:
- Sẽ là
USER_WIN– nếuUser_Setcó ít nhất một bộ số thắng cuộc. - Hoặc
COMPUTER_WIN– nếuComputer_Setcó ít nhất một bộ số thắng cuộc. - Hoặc
DRAW– nếuCommon_Setkhông còn giá trị nào có ý nghĩa và bàn cờ đã hết ô trống. - Hoặc
PLAYING– nếu tất cả các trường hợp ở trên đều chưa hiện diện.
Do đó chúng ta sẽ có thêm các function hỗ trợ là Found_Wining (Move_Set); và Found_Empty (Move_Set); để kiểm tra xem một *_Set bất kỳ có chứa bộ số thắng cuộc không, và kiểm tra một *_Set bất kỳ có đang ở trạng thái trống rỗng không.
package App_Model is
subtype Digit is Integer range 0 .. 9;
type Digit_Array is array (1 .. 9) of Digit;
type Status is (PLAYING, DRAW, USER_WIN, COMPUTER_WIN);
type State is record
Common_Set : Digit_Array;
User_Set : Digit_Array;
Computer_Set : Digit_Array;
Match_Status : Status;
end record;
procedure Init (App_State : out State)
with Post => Areas_Are_Unique (App_State) and Sets_Are_Complement (App_State);
procedure Update_User_Set (App_State : out State; User_Move : in Digit)
with Post => Areas_Are_Unique (App_State) and Sets_Are_Complement (App_State);
procedure Update_Match_Status (App_State : in out State); -- - new
function Areas_Are_Unique (App_State : State)
return Boolean;
function Sets_Are_Complement (App_State : State)
return Boolean;
function Found (Area : Digit; Move_Set : Digit_Array)
return Boolean;
function Found_Winning (Move_Set : Digit_Array) -- - new
return Boolean;
function Found_Empty (Move_Set : Digit_Array) -- - new
return Boolean;
end App_Model;
Update_Match_Status;
package body App_Model is
-- ...
procedure Update_Match_Status (App_State : in out State) is
-- local
begin
if Found_Winning (App_State.User_Set) then
App_State.Match_Status := USER_WIN;
elsif Found_Winning (App_State.Computer_Set) then
App_State.Match_Status := COMPUTER_WIN;
elsif Found_Empty (App_State.Common_Set) then
App_State.Match_Status := DRAW;
else
App_State.Match_Status := PLAYING;
end if;
end Update_Match_Status;
end App_Model;
Found_Winning;
Thao kiểm tra sự hiện điện của ít nhất một bộ số thắng cuộc bất kỳ trong User_Set hoặc Computer_Set có thể được thực hiện bằng những cách khác nhau:
- Liệt kê các bộ số thắng cuộc sau đó kiểm tra sự hiện diện của từng bộ số đó trong
Move_Setđược truyền vàofunction. - Hoặc lấy ra lần từng bộ số trong
Move_Setđể kiểm tra tổng giá trị. Nếu có ít nhất một bộ số cho kết quả tổng là 15 thì trả về giá trị làTRUE.
Phép kiểm tra đầu tiên có thể áp dụng với mọi cách thức đánh số các ô trên bàn cờ. Còn cách làm thứ hai thì chỉ có thể áp dụng nếu như bàn cờ được đánh số như chúng ta đang sử dụng hiện tại.
+ - - + - - + - - +
| 2 | 9 | 4 |
+ - - + - - + - - +
| 7 | 5 | 3 |
+ - - + - - + - - +
| 6 | 1 | 8 |
+ - - + - - + - - +
Mỗi đường thẳng bất kỳ giữa hai biên đối diện của bàn cờ trong trường hợp này sẽ luôn đi qua các ô tạo thành một bộ số có tổng là 15.
package body App_Model is
-- ...
function Found_Winning (Move_Set : Digit_Array)
return Boolean
is -- local
Result : Boolean := FALSE;
begin
for I1 in 1 .. 7 loop
for I2 in 2 .. 8 loop
for I3 in 3 .. 9 loop
if Move_Set (I1) + Move_Set (I2) + Move_Set (I3) = 15 then
Result := TRUE;
end if;
end loop;
end loop;
end loop;
--
return Result;
end Found_Winning;
end App_Model;
Found_Empty;
Hàm kiểm tra một Move_Set được truyền vào có đang ở trạng thái rỗng hay không.
package body App_Model is
-- ...
function Found_Empty (Move_Set : Digit_Array)
return Boolean
is -- local
Result : Boolean := TRUE;
begin
for Index in Move_Set'Range loop
if Move_Set (Index) /= 0 then
Result := FALSE;
end if;
end loop;
--
return Result;
end Found_Empty;
end App_Model;
Main;
Và cuối cùng là code sử dụng ở Main, chúng ta sẽ thử Update_User_Move; thêm vài bước đi để kiểm tra hoạt động của Update_Match_Status;
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);
Put_Chess_Board (App_State, User_Symbol);
-- loop
for I in 1 .. 3 loop
Get (User_Move, App_State);
Update_User_Set (App_State, User_Move);
--
Update_Match_Status (App_State);
Put_Line (Status'Image (App_State.Match_Status));
--
Put_Chess_Board (App_State, User_Symbol);
end loop;
--
-- 8. Get_Computer_Move;
-- 9. Update_Computer_Set;
-- 10. Update_Match_Status;
-- 11. Put_Chess_Board;
--
-- 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 |
+ - - + - - + - - +
Your move: 1
PLAYING
+ - - + - - + - - +
| 2 | 9 | 4 |
+ - - + - - + - - +
| 7 | 5 | 3 |
+ - - + - - + - - +
| 6 | X | 8 |
+ - - + - - + - - +
Your move: 5
PLAYING
+ - - + - - + - - +
| 2 | 9 | 4 |
+ - - + - - + - - +
| 7 | X | 3 |
+ - - + - - + - - +
| 6 | X | 8 |
+ - - + - - + - - +
Your move: 9
USER_WIN
+ - - + - - + - - +
| 2 | X | 4 |
+ - - + - - + - - +
| 7 | X | 3 |
+ - - + - - + - - +
| 6 | X | 8 |
+ - - + - - + - - +
(chưa đăng tải) [Procedural Programming + Ada] Bài 22 – Console Tic-Tac-Toe App (tiếp theo)
Nguồn: viblo.asia
