ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# dgeiger's solution

## to Queen Attack in the Delphi Pascal Track

Published at Aug 30 2020 · 0 comments
Instructions
Test suite
Solution

Given the position of two queens on a chess board, indicate whether or not they are positioned so that they can attack each other.

In the game of chess, a queen can attack pieces which are on the same row, column, or diagonal.

A chessboard can be represented by an 8 by 8 array.

So if you're told the white queen is at (2, 3) and the black queen at (5, 6), then you'd know you've got a set-up like so:

``````_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ W _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ B _
_ _ _ _ _ _ _ _
_ _ _ _ _ _ _ _
``````

You'd also be able to answer whether the queens can attack each other. In this case, that answer would be yes, they can, because both pieces share a diagonal.

## Testing

In order to run the tests for this track, you will need to install DUnitX. Please see the installation instructions for more information.

If Delphi is properly installed, and `*.dpr` file types have been associated with Delphi, then double clicking the supplied `*.dpr` file will start Delphi and load the exercise/project. `control + F9` is the keyboard shortcut to compile the project or pressing `F9` will compile and run the project.

Alternatively you may opt to start Delphi and load your project via. the `File` drop down menu.

### When Questions Come Up

We monitor the Pascal-Delphi support room on gitter.im to help you with any questions that might arise.

### Submitting Exercises

Note that, when trying to submit an exercise, make sure the exercise file you're submitting is in the `exercism/delphi/<exerciseName>` directory.

For example, if you're submitting `ubob.pas` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/delphi/bob/ubob.pas`.

## Source

J Dalbey's Programming Practice problems http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you may request help from a mentor.

### uQueenAttackTests.pas

``````unit uQueenAttackTests;

interface
uses
DUnitX.TestFramework, uQueenAttack;

const
CanonicalVersion = '2.3.0.1';

type
[TestFixture('Creation of queens with valid and invalid positions')]
TQueenCreationTests = class(TObject)
public
[Test]
//    [Ignore('Comment the "[Ignore]" statement to run the test')]
procedure queen_with_a_valid_position;

[Test]
[Ignore]
procedure queen_must_have_positive_row;

[Test]
[Ignore]
procedure queen_must_have_row_on_board;

[Test]
[Ignore]
procedure queen_must_have_positive_column;

[Test]
[Ignore]
procedure queen_must_have_column_on_board;
end;

[TestFixture('Ability of one queen to attack another')]
TQueenAttackTests = class(TObject)
private
WhiteQueen: TQueen;
BlackQueen: TQueen;
public
[Test]
[Ignore]
procedure can_not_attack;

[Test]
[Ignore]
procedure can_attack_on_same_row;

[Test]
[Ignore]
procedure can_attack_on_same_column;

[Test]
[Ignore]
procedure can_attack_on_first_diagonal;

[Test]
[Ignore]
procedure can_attack_on_second_diagonal;

[Test]
[Ignore]
procedure can_attack_on_third_diagonal;

[Test]
[Ignore]
procedure can_attack_on_fourth_diagonal;
end;

implementation
uses
System.SysUtils;

{\$REGION 'TQueenCreationTests'}

procedure TQueenCreationTests.queen_must_have_column_on_board;
begin
Assert.WillRaise(procedure
begin
TQueen.Create(4, 8)
end, EArgumentException, 'column not on board');

end;

procedure TQueenCreationTests.queen_must_have_positive_column;
begin
Assert.WillRaise(procedure
begin
TQueen.Create(2, -2)
end, EArgumentException, 'column not positive');
end;

procedure TQueenCreationTests.queen_must_have_positive_row;
begin
Assert.WillRaise(procedure
begin
TQueen.Create(-2, 2)
end, EArgumentException, 'row not positive');
end;

procedure TQueenCreationTests.queen_must_have_row_on_board;
begin
Assert.WillRaise(procedure
begin
TQueen.Create(8, 4)
end, EArgumentException, 'row not on board');
end;

procedure TQueenCreationTests.queen_with_a_valid_position;
begin
Assert.WillNotRaise(
procedure
begin
TQueen.Create(2, 2)
end, EArgumentException);
end;

{\$ENDREGION}

{\$REGION 'TQueenAttackTests'}

procedure TQueenAttackTests.can_attack_on_first_diagonal;
begin
WhiteQueen := TQueen.Create(2, 2);
BlackQueen := TQueen.Create(0, 4);
Assert.IsTrue(WhiteQueen.CanAttack(BlackQueen));
end;

procedure TQueenAttackTests.can_attack_on_fourth_diagonal;
begin
WhiteQueen := TQueen.Create(1, 7);
BlackQueen := TQueen.Create(0, 6);
Assert.IsTrue(WhiteQueen.CanAttack(BlackQueen));
end;

procedure TQueenAttackTests.can_attack_on_same_column;
begin
WhiteQueen := TQueen.Create(4, 5);
BlackQueen := TQueen.Create(2, 5);
Assert.IsTrue(WhiteQueen.CanAttack(BlackQueen));
end;

procedure TQueenAttackTests.can_attack_on_same_row;
begin
WhiteQueen := TQueen.Create(2, 4);
BlackQueen := TQueen.Create(2, 6);
Assert.IsTrue(WhiteQueen.CanAttack(BlackQueen));
end;

procedure TQueenAttackTests.can_attack_on_second_diagonal;
begin
WhiteQueen := TQueen.Create(2, 2);
BlackQueen := TQueen.Create(3, 1);
Assert.IsTrue(WhiteQueen.CanAttack(BlackQueen));
end;

procedure TQueenAttackTests.can_attack_on_third_diagonal;
begin
WhiteQueen := TQueen.Create(2, 2);
BlackQueen := TQueen.Create(1, 1);
Assert.IsTrue(WhiteQueen.CanAttack(BlackQueen));
end;

procedure TQueenAttackTests.can_not_attack;
begin
WhiteQueen := TQueen.Create(2, 4);
BlackQueen := TQueen.Create(6, 6);
Assert.IsFalse(WhiteQueen.CanAttack(BlackQueen));
end;

{\$ENDREGION}

initialization
TDUnitX.RegisterTestFixture(TQueenCreationTests);
TDUnitX.RegisterTestFixture(TQueenAttackTests);
end.``````
``````unit uQueenAttack;

interface

uses
System.SysUtils;

type
TQueen = class
private
FRow: Integer;
FCol: Integer;

public

constructor Create(Row, Column: Integer);

function CanAttack(Opponent: TQueen): Boolean;

end;

implementation

const
TopRow      = 0;
BottomRow   = 7;
LeftColumn  = 0;
RightColumn = 7;

{ TQueen }

function TQueen.CanAttack(Opponent: TQueen): Boolean;
begin
// We'll start off assuming that the attack can't happen.
Result := False;

// If the queens are on the same row, an attack can happen.
if FRow = Opponent.FRow then
Result := True;

// If the queens are on the same column, an attack can happen.
if FCol = Opponent.FCol then
Result := True;

// If the queens are on the same diagonal, an attack can happen.
// We can quickly check this by making sure the row distance from one
// queen to the other is the same as the column difference. If they are
// different, the queens are not on a diagonal to each other.  We use the
// absolute values to ensure that we are only looking at the magnitude of the
// difference, as it is the same if the row is to the top or bottom, and
// if the column is to the left or right.
if Abs(FRow - Opponent.FRow) = Abs(FCol - Opponent.FCol) then
Result := True;
end;

constructor TQueen.Create(Row, Column: Integer);
begin
// If the Row is not between the top row and the bottom row,
// it is off of the board, creating an error condition.
if not (Row in [TopRow..BottomRow]) then
raise EArgumentException.Create('row not on board');

// If the Column is not between the left column and the right column,
// it is off of the board, creating an error condition.
if not (Column in [LeftColumn..RightColumn]) then
raise EArgumentException.Create('row not on board');

// If we got this far, the row and column values are valid. Now we save them
// in the appropriate fields.
FRow := Row;
FCol := Column;
end;

end.``````