Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit ConstructorUnit;
- interface
- uses
- Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
- Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.StdCtrls, Vcl.ExtCtrls;
- type
- TConstructorForm = class(TForm)
- MainMenu: TMainMenu;
- FileMenuItem: TMenuItem;
- ManualMenuItem: TMenuItem;
- AboutDeveloperMenuItem: TMenuItem;
- LoadTemplateMenuItem: TMenuItem;
- SaveTemplateMenuItem: TMenuItem;
- BackLabel: TLabel;
- StartLabel: TLabel;
- UserFieldImage: TImage;
- HLongShip: TImage;
- HMiddleShip: TImage;
- HSmallShip: TImage;
- HShortShip: TImage;
- VLongShip: TImage;
- VMiddleShip: TImage;
- VSmallShip: TImage;
- VShortShip: TImage;
- PopupMenu: TPopupMenu;
- DeleteShipButton: TMenuItem;
- TurnButton: TMenuItem;
- GenerateFieldButton: TLabel;
- procedure LabelMouseEnter(Sender: TObject);
- procedure LabelMouseLeave(Sender: TObject);
- procedure BackLabelClick(Sender: TObject);
- procedure FormShow(Sender: TObject);
- procedure UserFieldImageDragOver(Sender, Source: TObject; X, Y: Integer;
- State: TDragState; var Accept: Boolean);
- procedure UserFieldImageDragDrop(Sender, Source: TObject; X, Y: Integer);
- procedure UserFieldImageMouseDown(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure UserFieldImageMouseMove(Sender: TObject; Shift: TShiftState; X,
- Y: Integer);
- procedure UserFieldImageMouseUp(Sender: TObject; Button: TMouseButton;
- Shift: TShiftState; X, Y: Integer);
- procedure ShipStartDrag(Sender: TObject; var DragObject: TDragObject);
- procedure DeleteShipButtonClick(Sender: TObject);
- procedure TurnButtonClick(Sender: TObject);
- procedure GenerateFieldButtonClick(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
- var
- ConstructorForm: TConstructorForm;
- implementation
- uses
- GridUnit, FieldGeneratorUnit;
- const
- CELL_WIDTH = 30;
- var
- Field, TempField, NewField: TField;
- IsDrag, IsMovingShipHorizontal, IsShipPlaced: Boolean;
- MovingShipType: TShip;
- ImpossibleCellsMatrix, TempMatrix: TImpossibleCellsMatrix;
- MovingShipCol, MovingShipRow: ShortInt;
- MovingShip: TImage;
- ShipsCountArr: TShipsCountArray;
- {$R *.dfm}
- procedure TConstructorForm.BackLabelClick(Sender: TObject);
- begin
- ConstructorForm.Close;
- end;
- procedure DrawShips();
- begin
- with ConstructorForm do
- begin
- DrawShip(HLongShip, 4, 1);
- HLongShip.Visible := True;
- DrawShip(HMiddleShip, 3, 1);
- HMiddleShip.Visible := True;
- DrawShip(HSmallShip, 2, 1);
- HSmallShip.Visible := True;
- DrawShip(HShortShip, 1, 1);
- HShortShip.Visible := True;
- DrawShip(VLongShip, 1, 4);
- VLongShip.Visible := True;
- DrawShip(VMiddleShip, 1, 3);
- VMiddleShip.Visible := True;
- DrawShip(VSmallShip, 1, 2);
- VSmallShip.Visible := True;
- DrawShip(VShortShip, 1, 1);
- VShortShip.Visible := True;
- end;
- end;
- procedure TConstructorForm.FormShow(Sender: TObject);
- begin
- Field := CreateField();
- ImpossibleCellsMatrix := CreateImpossibleCellsMatrix();
- DrawField(UserFieldImage, Field);
- DrawShips;
- ShipsCountArr := IinializeShipsCountArray();
- IsShipPlaced := False;
- end;
- procedure TConstructorForm.GenerateFieldButtonClick(Sender: TObject);
- begin
- ImpossibleCellsMatrix := CreateImpossibleCellsMatrix();
- Field := GenerateField(ImpossibleCellsMatrix);
- DrawField(UserFieldImage, Field);
- end;
- procedure TConstructorForm.LabelMouseEnter(Sender: TObject);
- begin
- with Sender as TLabel do
- begin
- Font.Color := clBlack;
- end;
- end;
- procedure TConstructorForm.LabelMouseLeave(Sender: TObject);
- begin
- with Sender as TLabel do
- begin
- Font.Color := clGrayText;
- end;
- end;
- function IsShipFromFormHorizontal(MovingShip: TImage): Boolean;
- begin
- IsShipFromFormHorizontal := MovingShip.Width Div CELL_WIDTH <> 1;
- end;
- function ReturnRowElemState(ShipField: TField; Col, Row, I: ShortInt): TFieldCellState;
- begin
- ReturnRowElemState := ShipField[Col+I, Row];
- end;
- function ReturnColElemState(ShipField: TField; Col, Row, I: ShortInt): TFieldCellState;
- begin
- ReturnColElemState := ShipField[Col, Row+I];
- end;
- function CanPlaceShipHere(Field: TField; Ship: TShip; Col, Row: ShortInt; IsHorizontal: Boolean): Boolean;
- var
- I: ShortInt;
- CanPlace: Boolean;
- ReturnCellStateFunction: TReturnCellStateFunction;
- begin
- I := 0;
- CanPlace := True;
- if IsHorizontal then
- ReturnCellStateFunction := ReturnRowElemState
- else
- ReturnCellStateFunction := ReturnColElemState;
- while (I < Ord(Ship)) and CanPlace do
- begin
- CanPlace := ReturnCellStateFunction(Field, Col, Row, I) = stFree;
- Inc(I);
- end;
- CanPlaceShipHere := CanPlace;
- end;
- function ConvertImageToShipType(MovingShip: TImage; IsHorizontal: Boolean): TShip;
- const
- TempArr: array [1..4] of TShip = (tShortShip, tSmallShip, tMiddleShip, tLongShip);
- var
- DeckCount: Byte;
- begin
- if IsHorizontal then
- DeckCount := MovingShip.Width div CELL_WIDTH
- else
- DeckCount := MovingShip.Height div CELL_WIDTH;
- ConvertImageToShipType := TempArr[DeckCount];
- end;
- procedure TConstructorForm.ShipStartDrag(Sender: TObject;
- var DragObject: TDragObject);
- begin
- MovingShip := TImage(Sender);
- IsMovingShipHorizontal := IsShipFromFormHorizontal(MovingShip);
- MovingShipType := ConvertImageToShipType(MovingShip, IsMovingShipHorizontal);
- end;
- procedure TConstructorForm.UserFieldImageDragOver(Sender, Source: TObject; X,
- Y: Integer; State: TDragState; var Accept: Boolean);
- var
- Col, Row: ShortInt;
- begin
- Col := X div CELL_WIDTH;
- Row := Y div CELL_WIDTH;
- Accept := CanPlaceShipHere(Field, MovingShipType, Col, Row, IsMovingShipHorizontal);
- if Accept then
- begin
- TempField := Field;
- PlaceShip(TempField, MovingShipType, Col, Row, IsMovingShipHorizontal);
- DrawField(UserFieldImage, TempField);
- end;
- if State = dsDragLeave then
- DrawField(UserFieldImage, Field);
- end;
- procedure EditImagesVisible(Ship: TShip; Value: Byte);
- begin
- with ConstructorForm do
- begin
- if Value = 0 then
- begin
- case Ship of
- tShortShip:
- begin
- HShortShip.Visible := False;
- VShortShip.Visible := False;
- end;
- tSmallShip:
- begin
- HSmallShip.Visible := False;
- VSmallShip.Visible := False;
- end;
- tMiddleShip:
- begin
- HMiddleShip.Visible := False;
- VMiddleShip.Visible := False;
- end;
- tLongShip:
- begin
- HLongShip.Visible := False;
- VLongShip.Visible := False;
- end;
- end;
- end
- else
- begin
- case Ship of
- tShortShip:
- begin
- HShortShip.Visible := True;
- VShortShip.Visible := True;
- end;
- tSmallShip:
- begin
- HSmallShip.Visible := True;
- VSmallShip.Visible := True;
- end;
- tMiddleShip:
- begin
- HMiddleShip.Visible := True;
- VMiddleShip.Visible := True;
- end;
- tLongShip:
- begin
- HLongShip.Visible := True;
- VLongShip.Visible := True;
- end;
- end;
- end;
- end;
- end;
- procedure TConstructorForm.UserFieldImageDragDrop(Sender, Source: TObject; X,
- Y: Integer);
- var
- Col, Row: Byte;
- begin
- Col := X div CELL_WIDTH;
- Row := Y div CELL_WIDTH;
- //////////////////////////////////////////////////////////////////////////////////////
- Dec(ShipsCountArr[MovingShipType]);
- EditImagesVisible(MovingShipType, ShipsCountArr[MovingShipType]);
- ///////////////////////////////////////////////////////////////////////////////////////
- Field := TempField;
- FillImpossibleCellsMatrix(ImpossibleCellsMatrix, MovingShipType, Col, Row, IsMovingShipHorizontal);
- DrawField(UserFieldImage, Field);
- end;
- ////////////Поправляем вставленный корабль
- function IsShipInFieldHorizontal(Field: TField; Ship: TShip; Col, Row: ShortInt): Boolean;
- var
- IsHorizontal: Boolean;
- begin
- if Ship = tShortShip then
- IsHorizontal := True
- else
- begin
- if (Field[Col-1, Row] <> stImpossible) or (Field[Col+1, Row] <> stImpossible) then
- IsHorizontal := True
- else
- IsHorizontal := False;
- end;
- IsShipInFieldHorizontal := IsHorizontal;
- end;
- procedure TConstructorForm.TurnButtonClick(Sender: TObject);
- var
- FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, I: ShortInt;
- CanPlace: Boolean;
- begin
- TempField := Field;
- FindSideOfShip(TempField, MovingShipType, MovingShipCol, MovingShipRow, FirstSideCol, FirstSideRow, IsMovingShipHorizontal, -1);
- FindSideOfShip(TempField, MovingShipType, MovingShipCol, MovingShipRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal, 1);
- DeleteShip(TempField, ImpossibleCellsMatrix, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal);
- if CanPlaceShipHere(TempField, MovingShipType, MovingShipCol, MovingShipRow, not IsMovingShipHorizontal) then
- begin
- PlaceShip(TempField, MovingShipType, MovingShipCol, MovingShipRow, not IsMovingShipHorizontal);
- Field := TempField;
- FillImpossibleCellsMatrix(ImpossibleCellsMatrix, MovingShipType, MovingShipCol, MovingShipRow, not IsMovingShipHorizontal);
- end
- else
- begin
- I := -1;
- CanPlace := False;
- repeat
- Inc(I);
- CanPlace := CanPlaceShipInLine(TempField, MovingShipType, I, not IsMovingShipHorizontal);
- until CanPlace or (I = High(Field));
- if CanPlace then
- begin
- PlaceShipToField(TempField, ImpossibleCellsMatrix, MovingShipType, I, not IsMovingShipHorizontal);
- Field := TempField;
- end;
- end;
- DrawField(UserFieldImage, Field);
- end;
- procedure TConstructorForm.DeleteShipButtonClick(Sender: TObject);
- var
- FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow: ShortInt;
- begin
- FindSideOfShip(Field, MovingShipType, MovingShipCol, MovingShipRow, FirstSideCol, FirstSideRow, IsMovingShipHorizontal, -1);
- FindSideOfShip(Field, MovingShipType, MovingShipCol, MovingShipRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal, 1);
- DeleteShip(Field, ImpossibleCellsMatrix, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal);
- DrawField(UserFieldImage, Field);
- /////////////////////////////////////////////////////////////////////////////////////
- Inc(ShipsCountArr[MovingShipType]);
- EditImagesVisible(MovingShipType, ShipsCountArr[MovingShipType]);
- //////////////////////////////////////////////////////////////////////////////////////
- end;
- procedure TConstructorForm.UserFieldImageMouseDown(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- var
- Col, Row, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow: ShortInt;
- IsShip: Boolean;
- begin
- Col := X div CELL_WIDTH;
- Row := Y div CELL_WIDTH;
- IsShip := Ord(Field[Col, Row]) > 0;
- if IsShip then
- begin
- MovingShipType := ConvertFieldStateToShip(Field[Col, Row]);
- IsMovingShipHorizontal := IsShipInFieldHorizontal(Field, MovingShipType, Col, Row);
- case Button of
- mbLeft:
- begin
- IsDrag := True;
- TempField := Field;
- TempMatrix := ImpossibleCellsMatrix;
- FindSideOfShip(TempField, MovingShipType, Col, Row, FirstSideCol, FirstSideRow, IsMovingShipHorizontal, -1);
- FindSideOfShip(TempField, MovingShipType, Col, Row, SecondSideCol, SecondSideRow, IsMovingShipHorizontal, 1);
- DeleteShip(TempField, TempMatrix, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal);
- end;
- mbRight:
- begin
- MovingShipCol := Col;
- MovingShipRow := Row;
- X := X + Left + UserFieldImage.Left+15;
- Y := Y + Top + UserFieldImage.Top + 30;
- PopupMenu.Popup(X, Y);
- end;
- mbMiddle: ;
- end;
- end;
- end;
- procedure TConstructorForm.UserFieldImageMouseMove(Sender: TObject;
- Shift: TShiftState; X, Y: Integer);
- var
- Col, Row: ShortInt;
- CanPlaceShip, IsCursorOnField: Boolean;
- begin
- if IsDrag then
- begin
- Col := X div CELL_WIDTH;
- Row := Y div CELL_WIDTH;
- IsCursorOnField := (Col > -1) and (Col < 10) and (Row > -1) and (Row < 10);
- if IsCursorOnField then
- begin
- NewField := TempField;
- CanPlaceShip := CanPlaceShipHere(NewField, MovingShipType, Col, Row, IsMovingShipHorizontal);
- if CanPlaceShip then
- begin
- PlaceShip(NewField, MovingShipType, Col, Row, IsMovingShipHorizontal);
- DrawField(UserFieldImage, NewField);
- MovingShipCol := Col;
- MovingShipRow := Row;
- Field := NewField;
- IsShipPlaced := True;
- end;
- end;
- end;
- end;
- procedure TConstructorForm.UserFieldImageMouseUp(Sender: TObject;
- Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- if IsDrag and IsShipPlaced then
- begin
- FillImpossibleCellsMatrix(TempMatrix, MovingShipType, MovingShipCol, MovingShipRow, IsMovingShipHorizontal);
- ImpossibleCellsMatrix := TempMatrix;
- end;
- IsShipPlaced := False;
- IsDrag := False;
- DrawField(UserFieldImage, Field);
- end;
- end.
- unit FieldGeneratorUnit;
- interface
- type
- TFieldCellState = (stImpossible = -1, stFree, stShortShip, stSmallShip, stMiddleShip, stLongShip);
- TField = array [-1..10, -1..10] of TFieldCellState;
- TImpossibleCellsMatrix = array [-1..10, -1..10] of ShortInt;
- TShip = (tShortShip = 1, tSmallShip, tMiddleShip, tLongShip);
- TShipsArray = array [0..9] of TShip;
- TShipsCountArray = array [TShip] of Byte;
- TReturnCellStateFunction = function (ShipField: TField; Col, Row, I: ShortInt): TFieldCellState;
- TReturnLineCellStateFunction = function (ShipField: TField; J, I: ShortInt): TFieldCellState;
- TPlaceShipProcedure = procedure (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
- TCompareFunction = function(ShootField: TField; Ship: TShip; Col, Row, I: ShortInt): Boolean;
- TCellsArray = array [0..99] of Byte;
- function CreateField(): TField;
- procedure FindSideOfShip(ShootField: TField; Ship: TShip; Col, Row: ShortInt; var SideCol: ShortInt; var SideRow: ShortInt; IsHorizontal: Boolean; DirectionCoef: ShortInt);
- procedure DeleteShip (var Field: TField; var Matrix: TImpossibleCellsMatrix; Col1, Row1, Col2, Row2: ShortInt; IsHorizontal: Boolean);
- function ConvertShipToFieldState(Ship: TShip): TFieldCellState;
- function ConvertFieldStateToShip(FieldState: TFieldCellState): TShip;
- procedure PlaceShip(var Field: TField; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
- function CreateImpossibleCellsMatrix(): TImpossibleCellsMatrix;
- procedure FillImpossibleCellsMatrix(var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
- function IinializeShipsCountArray(): TShipsCountArray;
- function GenerateField(var ImpossibleCellsMatrix: TImpossibleCellsMatrix): TField;
- function CanPlaceShipInLine(Field: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): Boolean;
- procedure PlaceShipToField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean);
- implementation
- function CreateField(): TField;
- var
- I, J: ShortInt;
- NewField: TField;
- begin
- for J := Low(NewField) to High(NewField) do
- NewField[-1, J] := stImpossible;
- for I := Low(NewField)+1 to High(NewField)-1 do
- begin
- for J := Low(NewField)+1 to High(NewField)-1 do
- NewField[I, J] := stFree;
- NewField[I, Low(NewField)] := stImpossible;
- NewField[I, High(NewField)] := stImpossible;
- end;
- for J := Low(NewField) to High(NewField) do
- NewField[High(NewField), J] := stImpossible;
- CreateField := NewField;
- end;
- function CreateImpossibleCellsMatrix(): TImpossibleCellsMatrix;
- var
- I, J: ShortInt;
- NewField: TImpossibleCellsMatrix;
- begin
- for J := Low(NewField) to High(NewField) do
- NewField[-1, J] := 1;
- for I := Low(NewField)+1 to High(NewField)-1 do
- begin
- for J := Low(NewField)+1 to High(NewField)-1 do
- NewField[I, J] := 0;
- NewField[I, Low(NewField)] := 1;
- NewField[I, High(NewField)] := 1;
- end;
- for J := Low(NewField) to High(NewField) do
- NewField[High(NewField), J] := 1;
- CreateImpossibleCellsMatrix := NewField;
- end;
- function IinializeShipsCountArray(): TShipsCountArray;
- var
- Arr: TShipsCountArray;
- I: TShip;
- begin
- for I := tShortShip to tLongShip do
- Arr[I] := 5-Ord(I);
- IinializeShipsCountArray := Arr;
- end;
- function ConvertShipToFieldState(Ship: TShip): TFieldCellState;
- const
- TempArr: array [TShip] of TFieldCellState = (stShortShip, stSmallShip, stMiddleShip, stLongShip);
- begin
- ConvertShipToFieldState := TempArr[Ship];
- end;
- function ConvertFieldStateToShip(FieldState: TFieldCellState): TShip;
- const
- TempArr: array [stShortShip..stLongShip] of TShip = (tShortShip, tSmallShip, tMiddleShip, tLongShip);
- begin
- ConvertFieldStateToShip := TempArr[FieldState];
- end;
- function CompareCellsVertically(ShootField: TField; Ship: TShip; Col,Row,I: ShortInt): Boolean;
- begin
- CompareCellsVertically := ShootField[Col, Row+I] = ConvertShipToFieldState(Ship);
- end;
- function CompareCellsHorizontally(ShootField: TField; Ship: TShip; Col,Row,I: ShortInt): Boolean;
- begin
- CompareCellsHorizontally := ShootField[Col+I, Row] = ConvertShipToFieldState(Ship);
- end;
- procedure FindSideOfShip(ShootField: TField; Ship: TShip; Col, Row: ShortInt; var SideCol: ShortInt; var SideRow: ShortInt; IsHorizontal: Boolean; DirectionCoef: ShortInt);
- var
- I: ShortInt;
- HasPartOfShip: Boolean;
- begin
- if IsHorizontal then
- begin
- I := 0;
- Repeat
- Inc(I);
- HasPartOfShip := CompareCellsHorizontally(ShootField, Ship, Col, Row, DirectionCoef*I);
- Until not HasPartOfShip;
- SideRow := Row;
- SideCol := Col + DirectionCoef * I;
- end
- else
- begin
- I := 0;
- Repeat
- Inc(I);
- HasPartOfShip := CompareCellsVertically(ShootField, Ship, Col, Row, DirectionCoef*I);
- Until not HasPartOfShip;
- SideCol := Col;
- SideRow := Row + DirectionCoef * I;
- end;
- end;
- procedure DeleteShipPart (var Field: TField; var Matrix: TImpossibleCellsMatrix; Col, Row: ShortInt);
- begin
- Dec(Matrix[Col, Row]);
- if (Matrix[Col, Row] = 0) then
- Field[Col, Row] := stFree;
- end;
- procedure DeleteShip (var Field: TField; var Matrix: TImpossibleCellsMatrix; Col1, Row1, Col2, Row2: ShortInt; IsHorizontal: Boolean);
- var
- I: ShortInt;
- begin
- if IsHorizontal then
- for I := Col1 to Col2 do
- begin
- DeleteShipPart(Field, Matrix, I, Row1-1);
- DeleteShipPart(Field, Matrix, I, Row1);
- DeleteShipPart(Field, Matrix, I, Row1+1);
- end
- else
- for I := Row1 to Row2 do
- begin
- DeleteShipPart(Field, Matrix, Col1-1, I);
- DeleteShipPart(Field, Matrix, Col1, I);
- DeleteShipPart(Field, Matrix, Col1+1, I);
- end;
- end;
- procedure FillImpossibleCellsHorizontaly (var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt);
- var
- I: ShortInt;
- begin
- for I := -1 to Ord(Ship) do
- begin
- Inc(Matrix[X+I, Y-1]);
- Inc(Matrix[X+I, Y]);
- Inc(Matrix[X+I, Y+1]);
- end;
- end;
- procedure FillImpossibleCellsVerticaly (var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt);
- var
- I: ShortInt;
- begin
- for I := -1 to Ord(Ship) do
- begin
- Inc(Matrix[X-1, Y+I]);
- Inc(Matrix[X, Y+I]);
- Inc(Matrix[X+1, Y+I]);
- end;
- end;
- procedure FillImpossibleCellsMatrix(var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
- begin
- if IsHorizontal then
- FillImpossibleCellsHorizontaly(Matrix, Ship, X, Y)
- else
- FillImpossibleCellsVerticaly(Matrix, Ship, X, Y);
- end;
- procedure PlaceShipHorizontal (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
- var
- I: ShortInt;
- begin
- for I := -1 to Ord(Ship) do
- begin
- ShipsField[X+I, Y-1] := stImpossible;
- ShipsField[X+I, Y] := ConvertShipToFieldState(Ship);
- ShipsField[X+I, Y+1] := stImpossible;
- end;
- ShipsField[X-1, Y] := stImpossible;
- ShipsField[X+Ord(Ship), Y] := stImpossible;
- end;
- procedure PlaceShipVertical (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
- var
- I: ShortInt;
- begin
- for I := -1 to Ord(Ship) do
- begin
- ShipsField[X-1, Y+I] := stImpossible;
- ShipsField[X, Y+I] := ConvertShipToFieldState(Ship);
- ShipsField[X+1, Y+I] := stImpossible;
- end;
- ShipsField[X, Y-1] := stImpossible;
- ShipsField[X, Y+Ord(Ship)] := stImpossible;
- end;
- procedure PlaceShip(var Field: TField; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
- begin
- if IsHorizontal then
- PlaceShipHorizontal (Field, Ship, X, Y)
- else
- PlaceShipVertical (Field, Ship, X, Y);
- end;
- ////////////////////////////////////////////////////////////////////////////////////////
- procedure InitializeShips(var ShipsArray: TShipsArray);
- var
- CurrShip: TShip;
- I, J: Byte;
- begin
- J := Low(ShipsArray);
- for CurrShip := Low(TShip) to High(TShip) do
- for I := 5 - Ord(CurrShip) DownTo 1 do
- begin
- ShipsArray[J] := CurrShip;
- Inc(J);
- end;
- end;
- function ReturnHorizontalLineCellState(ShipField: TField; Row, I: ShortInt): TFieldCellState;
- begin
- ReturnHorizontalLineCellState := ShipField[I, Row];
- end;
- function ReturnVerticalLineCellState(ShipField: TField; Col, I: ShortInt): TFieldCellState;
- begin
- ReturnVerticalLineCellState := ShipField[Col, I];
- end;
- function CanPlaceShipInLine(Field: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): Boolean;
- var
- I, Counter: ShortInt;
- HasFreePlace: Boolean;
- ReturnCellState: TReturnLineCellStateFunction;
- begin
- Counter := 0;
- HasFreePlace := False;
- I := Low(Field)+1;
- if IsHorizontal then
- ReturnCellState := ReturnHorizontalLineCellState
- else
- ReturnCellState := ReturnVerticalLineCellState;
- while not HasFreePlace and (I < High(Field)) do
- begin
- if Ord(ReturnCellState(Field, Coord, I)) = 0 then
- Inc(Counter)
- else
- Counter := 0;
- if Counter = Ord(Ship) then
- HasFreePlace := True;
- Inc(I);
- end;
- CanPlaceShipInLine := HasFreePlace;
- end;
- function GetSecondCoord(var Field: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): ShortInt;
- var
- I, Counter, StartCell, PossibleCellCount: ShortInt;
- ReturnCellState: TReturnLineCellStateFunction;
- begin
- Counter := 0;
- PossibleCellCount := 0;
- I := Low(Field)+1;
- if IsHorizontal then
- ReturnCellState := ReturnHorizontalLineCellState
- else
- ReturnCellState := ReturnVerticalLineCellState;
- while I < High(Field) do
- begin
- if Ord(ReturnCellState(Field, Coord, I)) = 0 then
- Inc(Counter)
- else
- begin
- Counter := 0;
- PossibleCellCount := 0;
- end;
- if Counter = Ord(Ship) then
- StartCell := I - Ord(Ship)+1;
- if (Counter - Ord(Ship)) > PossibleCellCount then
- PossibleCellCount := Counter - Ord(Ship);
- Inc(I);
- end;
- GetSecondCoord := StartCell + Random(PossibleCellCount + 1);
- end;
- function PullShip(var ShipsArray: TShipsArray; CommonShipsCount: Byte): TShip;
- var
- Ship: TShip;
- begin
- Ship := ShipsArray[CommonShipsCount-1];
- PullShip := Ship;
- end;
- function GetRandomDirection(): Boolean;
- var
- IsHorizontal: Boolean;
- begin
- IsHorizontal := Random(2) = 0;
- GetRandomDirection := isHorizontal;
- end;
- procedure PlaceShipToField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean);
- var
- SecondCoord: ShortInt;
- begin
- SecondCoord := GetSecondCoord(Field, Ship, Coord, IsHorizontal);
- if IsHorizontal then
- begin
- PlaceShipHorizontal(Field, Ship, SecondCoord, Coord);
- FillImpossibleCellsHorizontaly(ImpossibleCellsMatrix, Ship, SecondCoord, Coord);
- end
- else
- begin
- PlaceShipVertical(Field, Ship, Coord, SecondCoord);
- FillImpossibleCellsVerticaly(ImpossibleCellsMatrix, Ship, Coord, SecondCoord);
- end;
- end;
- procedure PutShipToField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; Ship: TShip);
- var
- Coord, SecondCoord: ShortInt;
- IsHorizontal: Boolean;
- begin
- repeat
- IsHorizontal := GetRandomDirection();
- Coord := Random(10);
- until CanPlaceShipInLine(Field, Ship, Coord, IsHorizontal);
- PlaceShipToField(Field, ImpossibleCellsMatrix, Ship, Coord, IsHorizontal);
- end;
- procedure FillGameField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; var ShipsArray: TShipsArray; var CommonShipsCount: Byte);
- var
- Ship: TShip;
- I: ShortInt;
- begin
- for I := 1 to 10 do
- begin
- Ship := PullShip(ShipsArray, CommonShipsCount);
- Dec(CommonShipsCount);
- PutShipToField(Field, ImpossibleCellsMatrix, Ship);
- end;
- end;
- function GenerateField(var ImpossibleCellsMatrix: TImpossibleCellsMatrix): TField;
- var
- NewField: TField;
- ShipsArray: TShipsArray;
- CommonShipsCount: Byte;
- begin
- CommonShipsCount := 10;
- NewField := CreateField();
- InitializeShips(ShipsArray);
- FillGameField(NewField, ImpossibleCellsMatrix, ShipsArray, CommonShipsCount);
- GenerateField := NewField;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement