0

只是希望有人能解释为什么我的程序默认为 Piece 类型的 Move_Piece 过程,而不是当我尝试移动池塘时 Pond 类型的 Move_Piece 过程。当我将 Pond 类型的变量传递给 Move_Piece 过程时,将打印“使用基本 Move_Piece”而不是“1”。为什么是这样?

我正在使用 Ada 2005,以防覆盖关键字不明显。我希望我没有提供太少的信息。谢谢!

chess_types.ads:

package Chess_Types is
  type Color is (Black, White);
  type Piece is tagged
    record
     Name : String (1 .. 3) := "   ";
     Alive : Boolean := False;
     Team  : Color;
     Coordinate : Integer;
  end record;
  procedure Move_Piece(P: in out Piece);
  -- Board Types
  type Board_Row is array (Positive range 1 .. 8) of Piece;
  type Board_Type is array (Positive range 1 .. 8) of Board_Row;
end Chess_Types;

chess_types.adb:

with Ada.Text_IO;
use Ada.Text_IO;

package body Chess_Types is
   procedure Move_Piece(P: in out Piece) is
   begin
      Put_Line("Using basic Move_Piece");
   end Move_Piece;
end Chess_types;

chess_types-piece_types.ads:

package Chess_Types.Piece_Types is

   type Pond is new Piece with
      record
         First_Move : Boolean := True;
      end record;
   overriding
   procedure Move_Piece(Po: in out Pond);

   type Rook is new Piece with null record;
      overriding
   procedure Move_Piece(Ro: in out Rook);

   type Knight is new Piece with null record;
      overriding
   procedure Move_Piece(Kn: in out Knight);

   type Bishop is new Piece with null record;
      overriding
   procedure Move_Piece(Bi: in out Bishop);

   type Queen is new Piece with null record;
      overriding
   procedure Move_Piece(Qu: in out Queen);

   type King is new Piece with null record;
      overriding
   procedure Move_Piece(Ki: in out King);
end Chess_Types.Piece_Types;

chess_types-piece_types.adb:

with Ada.Text_IO;
use Ada.Text_IO;

package body Chess_Types.Piece_Types is
--   Possible_Moves : array (Integer range 1 .. 100) of Integer range 11 .. 88;
   procedure Move_Piece(Po: in out Pond) is
   begin
      Put_Line("1");
   end Move_Piece;

   procedure Move_Piece(Ro: in out Rook) is
   begin
      Put_Line("2");
   end Move_Piece;

   procedure Move_Piece(Kn: in out Knight) is
   begin
      Put_Line("3");
   end Move_Piece;

   procedure Move_Piece(Bi: in out Bishop) is
   begin
      Put_Line("4");
   end Move_Piece;

   procedure Move_Piece(Qu: in out Queen) is
   begin
      Put_Line("5");
   end Move_Piece;

   procedure Move_Piece(Ki: in out King) is
   begin
      Put_Line("6");
   end Move_Piece;
end Chess_types.Piece_Types;

国际象棋.adb:

with Ada.Text_IO;
with Print_Things;
with Adjust_Board;
with Chess_Types;
with Chess_Types.Piece_Types;
use Ada.Text_IO;
use Print_Things;
use Adjust_Board;
use Chess_Types;
use Chess_Types.Piece_Types;

procedure Chess is
   Board : Board_Type;
   Move  : String (1 .. 5);
   Move_From : Integer range 11 .. 88;
   Move_To   : Integer range 11 .. 88;
begin

   -- Initialize and Print default board
   Initialize_Board(Board);
   Print_Board(Board);

   -- Get the move
   Put_Line("Select a move:");
   Move := Get_Line;
   while move /= "Q" loop
      Move_From := Integer'Value(Move(Move'First .. Move'First + 1));
      Move_To := Integer'Value(Move(Move'First + 3 .. Move'Last));
      --   Put_Line(Integer'Image(Move_From) & " to" & Integer'Image(Move_To));

      -- Associate the move with a piece
      for I in Board'Range(1) loop
         for J in Board'Range(1) loop
            if Move_From = Board(I)(J).Coordinate then
               Move_Piece(Board(I)(J));
            end if;
         end loop;
      end loop;
      -- Print the Board
      Print_Board(Board);
      -- Get the move
      Put_Line("Select a move:");
      Move := Get_Line;
   end loop;


end Chess;

调整板.adb:

with Chess_Types;
use Chess_Types;
with Chess_Types.Piece_Types;
use Chess_Types.Piece_Types;
package body Adjust_Board is

   procedure Initialize_Board(Board: in out Board_Type) is
      -- Define White Chess Pieces
      WP1   : Pond := ("wP ", True, White, 12, True);
      WP2   : Pond := ("wP ", True, White, 22, True);
      WP3   : Pond := ("wP ", True, White, 32, True);
      WP4   : Pond := ("wP ", True, White, 42, True);
      WP5   : Pond := ("wP ", True, White, 52, True);
      WP6   : Pond := ("wP ", True, White, 62, True);
      WP7   : Pond := ("wP ", True, White, 72, True);
      WP8   : Pond := ("wP ", True, White, 82, True);
      WR1   : Rook := ("wRk", True, White, 11);
      WR2   : Rook := ("wRk", True, White, 81);
      WK1   : Knight := ("wKn", True, White, 21);
      WK2   : Knight := ("wKn", True, White, 71);
      WB1   : Bishop := ("wBi", True, White, 31);
      WB2   : Bishop := ("wBi", True, White, 61);
      WQ    : Queen := ("wQu", True, White, 41);
      WK    : King := ("wKi", True, White, 51);

      -- Define Black Chess Pieces
      BP1   : Pond := ("bP ", True, Black, 17, True);
      BP2   : Pond := ("bP ", True, Black, 27, True);
      BP3   : Pond := ("bP ", True, Black, 37, True);
      BP4   : Pond := ("bP ", True, Black, 47, True);
      BP5   : Pond := ("bP ", True, Black, 57, True);
      BP6   : Pond := ("bP ", True, Black, 67, True);
      BP7   : Pond := ("bP ", True, Black, 77, True);
      BP8   : Pond := ("bP ", True, Black, 87, True);
      BR1   : Rook := ("bRk", True, Black, 18);
      BR2   : Rook := ("bRk", True, Black, 88);
      BK1   : Knight := ("bKn", True, Black, 28);
      BK2   : Knight := ("bKn", True, Black, 78);
      BB1   : Bishop := ("bBi", True, Black, 38);
      BB2   : Bishop := ("bBi", True, Black, 68);
      BQ    : Queen := ("bQu", True, Black, 48);
      BK    : King := ("bKi", True, Black, 58);

   begin
      -- Initialize Chess Board
      Board(1)(1) := Piece(WR1);
      Board(8)(1) := Piece(WR2);
      Board(2)(1) := Piece(WK1);
      Board(7)(1) := Piece(WK1);
      Board(3)(1) := Piece(WB1);
      Board(6)(1) := Piece(WB1);
      Board(4)(1) := Piece(WQ);
      Board(5)(1) := Piece(WK);
      Board(1)(2) := Piece(WP1);
      Board(2)(2) := Piece(WP2);
      Board(3)(2) := Piece(WP3);
      Board(4)(2) := Piece(WP4);
      Board(5)(2) := Piece(WP5);
      Board(6)(2) := Piece(WP6);
      Board(7)(2) := Piece(WP7);
      Board(8)(2) := Piece(WP8);

      Board(1)(8) := Piece(BR1);
      Board(8)(8) := Piece(BR2);
      Board(2)(8) := Piece(BK1);
      Board(7)(8) := Piece(BK1);
      Board(3)(8) := Piece(BB1);
      Board(6)(8) := Piece(BB1);
      Board(4)(8) := Piece(BQ);
      Board(5)(8) := Piece(BK);
      Board(1)(7) := Piece(BP1);
      Board(2)(7) := Piece(BP2);
      Board(3)(7) := Piece(BP3);
      Board(4)(7) := Piece(BP4);
      Board(5)(7) := Piece(BP5);
      Board(6)(7) := Piece(BP6);
      Board(7)(7) := Piece(BP7);
      Board(8)(7) := Piece(BP8);
   end Initialize_Board;
end Adjust_Board;
4

1 回答 1

3

在 chess_types.ads 中,添加

type Piece_Acc is access all Piece'Class;

Board_Row 需要是 Piece_Acc 的数组:

type Board_Row is array (1..8) of Piece_Acc;

您确实希望数组中的元素是 Piece'Class,但这不起作用,因为编译器此时无法判断哪些类型可能从 Piece 派生以及它们的内存大小是多少,所以它不会能够设置一个数组。所以它需要是一个访问类型。(在 C# 或 Java 中,无论您是否愿意,所有对象都会自动访问类型 [指针]。在 Ada 中,您需要告诉它何时需要指针。)然后,当您在 adjust_board.adb 中进行设置时,您会说类似的话

Board(1)(1) := new Rook' (WR1);

依此类推,以创建访问对象。

[此外,这将导致 Board 中未初始化的所有其他内容初始化为 null。如果你想将它初始化为其他一些表示“没有”的 Piece,您需要自己分配给 Board 中未使用的空间。]

但是一旦这一切都完成了,当你说

Board(I)(J).Move_Piece;  -- same as Board(I)(J).all.Move_Piece;

或者

Move_Piece(Board(I)(J).all);

Board(I)(J).all 的类型是一个类范围的类型,所以它会像你想要的那样调度到正确的 Move_Piece。

请注意,如果当您自己使用“new”分配事物时,您还必须负责解除分配以避免内存泄漏(除非所有内容只分配一次,然后您并不真正关心)。做到这一点的最佳方法涉及受控类型,即从 Ada.Finalization.Controlled 派生 Piece。

更多:避免自己处理访问和分配/解除分配的方法可能是使用 Ada.Containers.Indefinite_Vectors 而不是数组:

subtype Board_Index is Integer range 1 .. 64;
package Chessboard is new Ada.Containers.Indefinite_Vectors (Board_Index, Piece'Class);

这个包不允许多维类型的索引,所以你需要自己计算一个索引(在 1..64 或 0..63 范围内),或者实例化 Indefinite_Vectors 两次,我认为这很笨重。但这应该消除您自己分配的需要,而且我认为它也会在容器被销毁时为您进行释放。

于 2013-07-09T22:40:59.047 回答