0

池を移動しようとしたときに、私のプログラムが、Pond タイプの Move_Piece プロシージャではなく、Piece タイプの Move_Piece プロシージャにデフォルト設定されている理由を誰かが説明してくれることを願っています。Pond 型の変数を Move_Piece プロシージャに渡すと、「1」ではなく「Using basic Move_Piece」と出力されます。どうしてこれなの?

私は 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 に初期化されます。「ピースなし」を示す他のピースに初期化したい場合は、ボードの未使用スペースに自分で割り当てる必要があります。]

しかし、それがすべて終わったら、あなたが言うとき

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」を使用して自分で割り当てを行う場合は、メモリ リークを回避するために割り当て解除も行う必要があることに注意してください (すべてが 1 回だけ割り当てられ、その後はあまり気にしない場合を除きます)。これを行う最善の方法は、制御された型を使用することです。つまり、Piece を Ada.Finalization.Controlled から派生させます。

詳細: アクセスと割り当て/割り当て解除を自分で処理しないようにする方法は、配列の代わりに Ada.Containers.Indefined_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 の範囲) を自分で計算するか、不格好だと思う Indefined_Vectors を 2 回インスタンス化する必要があります。しかし、これにより、独自の割り当てを行う必要がなくなります。また、コンテナーが破棄されたときに割り当て解除も行われると思います。

于 2013-07-09T22:40:59.047 に答える