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_Set
có ít nhất một bộ số thắng cuộc. - Hoặc
COMPUTER_WIN
– nếuComputer_Set
có ít nhất một bộ số thắng cuộc. - Hoặc
DRAW
– nếuCommon_Set
khô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