[Procedural Programming + Ada] Bài 21 – Console Tic-Tac-Toe App (tiếp theo)

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

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ếu User_Set có ít nhất một bộ số thắng cuộc.
  • Hoặc COMPUTER_WIN – nếu Computer_Set có ít nhất một bộ số thắng cuộc.
  • Hoặc DRAW – nếu Common_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);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ào function.
  • 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

Bài viết liên quan

WebP là gì? Hướng dẫn cách để chuyển hình ảnh jpg, png qua webp

WebP là gì? WebP là một định dạng ảnh hiện đại, được phát triển bởi Google

Điểm khác biệt giữa IPv4 và IPv6 là gì?

IPv4 và IPv6 là hai phiên bản của hệ thống địa chỉ Giao thức Internet (IP). IP l

Check nameservers của tên miền xem website trỏ đúng chưa

Tìm hiểu cách check nameservers của tên miền để xác định tên miền đó đang dùn

Mình đang dùng Google Domains để check tên miền hàng ngày

Từ khi thông báo dịch vụ Google Domains bỏ mác Beta, mình mới để ý và bắt đầ