Unit Placers of BattleshipGames

by Josh Blake: L6 Age ~17

unit Placers;
{
    Copyright (c) 2014 Josh Blake

    Licensed under the Apache License, Version 2.0 (the "License"); you may not
    use this file except in compliance with the License, as described at
    http://www.apache.org/licenses/ and http://www.pp4s.co.uk/licenses/
}
interface

uses
  Game,
  Grid,
  Players,
  Settings,
  StrUtils,
  UI;

type
  TPlacer = class(TObject)
  protected
    Game: TGame;
    Grid: TGrid;
    UI: TBaseUI;
    const INVALID_STR = ''; 
    function ChoosePosition(const Size: Integer): TChoice; virtual; abstract;
    function CreatePosition(Location: TChoice; Size: Integer): TPosition;
  public
    procedure PlaceShip(Size: Integer);
    constructor Create(GameUsed: TGame; aUI: TBaseUI);
  end;

  RandomPlacer = class(TPlacer)
  protected
    function ChoosePosition(const Size: Integer): TChoice; override;
  end;

  UserPlacer = class(TPlacer)
  protected
    const INVALID_STR = 'Ship already exists there, please try again';
    function ChoosePosition(const Size: Integer): TChoice; override;
  end;

implementation

constructor TPlacer.Create(GameUsed: TGame; aUI: TBaseUI);
begin
  Grid := GameUsed.Grid;
  Game := GameUsed;
  UI := aUI;
end;

procedure TPlacer.PlaceShip(Size: Integer);
{Places a ship of Size in Game.Grid}
var
  Position: TPosition;
  Suitable: Boolean;
  I: Integer;
  Ship: TShip;
  Square: TGridSquare;
begin
  repeat   //Keep choosing positions until a suitable one is found
    Suitable := True;
    Position := CreatePosition(
                  ChoosePosition(Size),
                  Size
                );
    for I := Low(Position) to High(Position) do begin
      Square := Grid[Position[I].X, Position[I].Y];
      if Square.Content.CheckFilled then begin
        Suitable := False;
        break;
      end;
    end;
    if (not Suitable) and (INVALID_STR <> '') then UI.ShowMessage(INVALID_STR);
  until Suitable;

  Ship := TShip.Create(Size);
  for I := Low(Position) to High(Position) do begin
    Grid[Position[I].X][Position[I].Y].Content := Ship;
  end;
  Game.AddShip;
end;

function TPlacer.CreatePosition(Location: TChoice; Size: Integer): TPosition;
{Generate a TPosition of [0..Length] starting at (X, Y) and changing either X or Y}
var
  I: Integer;
  Position: TCoord;
begin
  Position := Location.Start;
  SetLength(Result, Size);
  for I := Low(Result) to High(Result) do begin
    Result[I].X := Position.X;
    Result[I].Y := Position.Y;
    if Location.ChangeX then Inc(Position.X)
    else Inc(Position.Y);
  end;
end;
  
function RandomPlacer.ChoosePosition(const Size: Integer): TChoice;
var
  GridMax, GridMin: Integer;
{Randomly choose a square and direction for a ship}
begin;
  GridMax := High(Grid);
  GridMin := Low(Grid);
  if Random() >= 0.5 then begin
    Result.ChangeX := False;   //ship is vertical
    Result.Start.X := Random(GridMax) + GridMin;
    Result.Start.Y := Random(GridMax - Size) + GridMin;
  end else begin
    Result.ChangeX := True;   //ship is horizontal
    Result.Start.Y := Random(GridMax) + GridMin;;
    Result.Start.X := Random(GridMax - Size) + GridMin;
  end;
end;

function UserPlacer.ChoosePosition(const Size: Integer): TChoice;
begin
  Result := UI.PlaceUserShip(Grid, Size);
end;

end.
Programming - a skill for life!

by Josh Blake: L6 Age ~17