如何将 Ada 记录类型修改为支持两种变体的联合类型?

How do I modify the Ada record type to be a union type supporting two variants?

该程序包含一些类型定义,可用于 玩数字和十字(也称为井字游戏)的程序。 gamePos2 描述了一个玩家获胜的完整位置

我正在尝试将记录类型 GamePos 更改为支持两种变体的联合类型:已完成游戏的位置和正在进行的游戏的位置。

欢迎随时提出任何问题,以便我详细说明我的问题

type GamePos is
        record
            board : TTTBoard;
            turn : Player;
            value : Float;
        end record;

    procedure Put_Pos(pos : GamePos) is
    begin
        Put_Board(pos.board);
        Put("Player to make the next move: ");
        Put(pos.turn);
        Put_Line("");
        Put("Estimated advantage of player X over player O is: ");
        Put(pos.value, 0, 0, 0);
        Put_Line("");
    end Put_Pos;

    gamePos1 : GamePos
        := (board =>
                ((X, X, O),
                 (O, B, X),
                 (O, B, B)),
            turn => Player_X,
            value => 0.0);

     gamePos2 : GamePos
         := (pos_variant => WON, -- the discriminant
             board =>
                 ((X, X, O),
                  (O, X, X),
                  (O, O, X)),
             winner => Player_X);

begin
    Put_Pos(gamePos1);
    Put_Line("");
     Put_Pos(gamePos2);
end TTT;

下面的示例显示了如何创建和使用带有鉴别器的变体记录。可以在 learn.adacore.com.

上找到更多信息

main.adb

with Ada.Text_IO; use Ada.Text_IO;

procedure TTT is

   type Player is (Player_X, Player_Y);

   type Cell_State is (X, O, B);

   type TTT_Board is array (Positive range 1 .. 3,
                            Positive range 1 .. 3) of Cell_State;

   --  Game_State is the enumeration used as the discriminant type.
   
   type Game_State is (Ongoing, Done);   
   
   --  Make sure you use a default initialization (here: "Ongoing"). If you
   --  do not provide a default values, then the discriminant will be immutable.
    
   type Game_Pos (State : Game_State := Ongoing) is record
      Board : TTT_Board;      
      case State is
         when Ongoing =>
            Turn      : Player;
            Advantage : Float;
         when Done =>
            Winner    : Player;
      end case;
      end record;

   ---------------
   -- Put_Board --
   ---------------
   
   procedure Put_Board (Board : TTT_Board) is
   begin
      for R in Board'Range (1) loop
         for C in Board'Range (2) loop
            Put (Board (R, C)'Image & " ");
         end loop;
         New_Line;
      end loop;
   end Put_Board;
   
   -------------
   -- Put_Pos --
   -------------
   
   procedure Put_Pos (Pos : Game_Pos) is
   begin
      Put_Board (Pos.Board);
      New_Line;
      
      case Pos.State is
         when Ongoing =>
            Put_Line ("Player to make the next move: " & Pos.Turn'Image);
            New_Line;
     
         when Done =>
            Put_Line ("Winner: " & Pos.Winner'Image);
            New_Line;
            
      end case;
      
   end Put_Pos;

   
   Game_Pos_1 : Game_Pos :=
     (State     => Ongoing,
      Board     => ((X, X, O),
                    (O, B, X),
                    (O, B, B)),
      Turn      => Player_X,
      Advantage => 0.0);

   Game_Pos_2 : Game_Pos :=
     (State  => Done,
      Board  => ((X, X, O),
                 (O, X, X),
                 (O, O, X)),
      Winner => Player_X);

begin
   Put_Pos (Game_Pos_1);
   New_Line;
   Put_Pos (Game_Pos_2);
end TTT;

输出

$ ./ttt
X X O 
O B X 
O B B 

Player to make the next move: PLAYER_X


X X O 
O X X 
O O X 

Winner: PLAYER_X