希望有人可以解释为什么我的程序默认为Piece Type的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;
chess.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;
adjust_board.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;
答案 0 :(得分: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。如果你想将它初始化为另一个表示“没有片段”的片段,你需要自己分配给电路板中未使用的空格。]
但是一旦完成所有这些,当你说
时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派生出一块。
更多:避免自己处理访问和分配/解除分配的方法可能是使用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。但这应该消除了进行自己的分配的需要,我认为它也会在容器被销毁时为你解除分配。