Advertisement
THOMAS_SHELBY_18

back 09/04

Apr 9th, 2024
98
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 26.95 KB | Source Code | 0 0
  1. unit ConstructorUnit;
  2.  
  3. interface
  4.  
  5. uses
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.StdCtrls, Vcl.ExtCtrls;
  8.  
  9. type
  10.   TConstructorForm = class(TForm)
  11.     MainMenu: TMainMenu;
  12.     FileMenuItem: TMenuItem;
  13.     ManualMenuItem: TMenuItem;
  14.     AboutDeveloperMenuItem: TMenuItem;
  15.     LoadTemplateMenuItem: TMenuItem;
  16.     SaveTemplateMenuItem: TMenuItem;
  17.     BackLabel: TLabel;
  18.     StartLabel: TLabel;
  19.     UserFieldImage: TImage;
  20.     HLongShip: TImage;
  21.     HMiddleShip: TImage;
  22.     HSmallShip: TImage;
  23.     HShortShip: TImage;
  24.     VLongShip: TImage;
  25.     VMiddleShip: TImage;
  26.     VSmallShip: TImage;
  27.     VShortShip: TImage;
  28.     PopupMenu: TPopupMenu;
  29.     DeleteShipButton: TMenuItem;
  30.     TurnButton: TMenuItem;
  31.     GenerateFieldButton: TLabel;
  32.     procedure LabelMouseEnter(Sender: TObject);
  33.     procedure LabelMouseLeave(Sender: TObject);
  34.     procedure BackLabelClick(Sender: TObject);
  35.     procedure FormShow(Sender: TObject);
  36.     procedure UserFieldImageDragOver(Sender, Source: TObject; X, Y: Integer;
  37.       State: TDragState; var Accept: Boolean);
  38.     procedure UserFieldImageDragDrop(Sender, Source: TObject; X, Y: Integer);
  39.     procedure UserFieldImageMouseDown(Sender: TObject; Button: TMouseButton;
  40.       Shift: TShiftState; X, Y: Integer);
  41.     procedure UserFieldImageMouseMove(Sender: TObject; Shift: TShiftState; X,
  42.       Y: Integer);
  43.     procedure UserFieldImageMouseUp(Sender: TObject; Button: TMouseButton;
  44.       Shift: TShiftState; X, Y: Integer);
  45.     procedure ShipStartDrag(Sender: TObject; var DragObject: TDragObject);
  46.     procedure DeleteShipButtonClick(Sender: TObject);
  47.     procedure TurnButtonClick(Sender: TObject);
  48.     procedure GenerateFieldButtonClick(Sender: TObject);
  49.   private
  50.     { Private declarations }
  51.   public
  52.     { Public declarations }
  53.   end;
  54.  
  55. var
  56.   ConstructorForm: TConstructorForm;
  57.  
  58. implementation
  59.  
  60. uses
  61.     GridUnit, FieldGeneratorUnit;
  62.  
  63. const
  64.     CELL_WIDTH = 30;
  65. var
  66.     Field, TempField, NewField: TField;
  67.     IsDrag, IsMovingShipHorizontal, IsShipPlaced: Boolean;
  68.     MovingShipType: TShip;
  69.     ImpossibleCellsMatrix, TempMatrix: TImpossibleCellsMatrix;
  70.     MovingShipCol, MovingShipRow: ShortInt;
  71.     MovingShip: TImage;
  72.     ShipsCountArr: TShipsCountArray;
  73.  
  74. {$R *.dfm}
  75.  
  76. procedure TConstructorForm.BackLabelClick(Sender: TObject);
  77. begin
  78.     ConstructorForm.Close;
  79. end;
  80.  
  81. procedure DrawShips();
  82. begin
  83.     with ConstructorForm do
  84.     begin
  85.         DrawShip(HLongShip, 4, 1);
  86.         HLongShip.Visible := True;
  87.  
  88.         DrawShip(HMiddleShip, 3, 1);
  89.         HMiddleShip.Visible := True;
  90.  
  91.         DrawShip(HSmallShip, 2, 1);
  92.         HSmallShip.Visible := True;
  93.  
  94.         DrawShip(HShortShip, 1, 1);
  95.         HShortShip.Visible := True;
  96.  
  97.         DrawShip(VLongShip, 1, 4);
  98.         VLongShip.Visible := True;
  99.  
  100.         DrawShip(VMiddleShip, 1, 3);
  101.         VMiddleShip.Visible := True;
  102.  
  103.         DrawShip(VSmallShip, 1, 2);
  104.         VSmallShip.Visible := True;
  105.  
  106.         DrawShip(VShortShip, 1, 1);
  107.         VShortShip.Visible := True;
  108.     end;
  109. end;
  110.  
  111. procedure TConstructorForm.FormShow(Sender: TObject);
  112. begin
  113.     Field := CreateField();
  114.     ImpossibleCellsMatrix := CreateImpossibleCellsMatrix();
  115.     DrawField(UserFieldImage, Field);
  116.     DrawShips;
  117.     ShipsCountArr := IinializeShipsCountArray();
  118.     IsShipPlaced := False;
  119. end;
  120.  
  121. procedure TConstructorForm.GenerateFieldButtonClick(Sender: TObject);
  122. begin
  123.     ImpossibleCellsMatrix := CreateImpossibleCellsMatrix();
  124.     Field := GenerateField(ImpossibleCellsMatrix);
  125.     DrawField(UserFieldImage, Field);
  126. end;
  127.  
  128. procedure TConstructorForm.LabelMouseEnter(Sender: TObject);
  129. begin
  130.     with Sender as TLabel do
  131.     begin
  132.         Font.Color := clBlack;
  133.     end;
  134. end;
  135.  
  136. procedure TConstructorForm.LabelMouseLeave(Sender: TObject);
  137. begin
  138.     with Sender as TLabel do
  139.     begin
  140.         Font.Color := clGrayText;
  141.     end;
  142. end;
  143.  
  144. function IsShipFromFormHorizontal(MovingShip: TImage): Boolean;
  145. begin
  146.     IsShipFromFormHorizontal := MovingShip.Width Div CELL_WIDTH <> 1;
  147. end;
  148.  
  149. function ReturnRowElemState(ShipField: TField; Col, Row, I: ShortInt): TFieldCellState;
  150. begin
  151.     ReturnRowElemState := ShipField[Col+I, Row];
  152. end;
  153.  
  154. function ReturnColElemState(ShipField: TField; Col, Row, I: ShortInt): TFieldCellState;
  155. begin
  156.     ReturnColElemState := ShipField[Col, Row+I];
  157. end;
  158.  
  159. function CanPlaceShipHere(Field: TField; Ship: TShip; Col, Row: ShortInt; IsHorizontal: Boolean): Boolean;
  160. var
  161.     I: ShortInt;
  162.     CanPlace: Boolean;
  163.     ReturnCellStateFunction: TReturnCellStateFunction;
  164. begin
  165.     I := 0;
  166.     CanPlace := True;
  167.     if IsHorizontal then
  168.         ReturnCellStateFunction := ReturnRowElemState
  169.     else
  170.         ReturnCellStateFunction := ReturnColElemState;
  171.  
  172.     while (I < Ord(Ship)) and CanPlace do
  173.     begin
  174.        CanPlace := ReturnCellStateFunction(Field, Col, Row, I) = stFree;
  175.        Inc(I);
  176.     end;
  177.  
  178.     CanPlaceShipHere := CanPlace;
  179. end;
  180.  
  181. function ConvertImageToShipType(MovingShip: TImage; IsHorizontal: Boolean): TShip;
  182. const
  183.     TempArr: array [1..4] of TShip = (tShortShip, tSmallShip, tMiddleShip, tLongShip);
  184. var
  185.     DeckCount: Byte;
  186. begin
  187.     if IsHorizontal then
  188.         DeckCount := MovingShip.Width div CELL_WIDTH
  189.     else
  190.         DeckCount := MovingShip.Height div CELL_WIDTH;
  191.  
  192.     ConvertImageToShipType := TempArr[DeckCount];
  193. end;
  194.  
  195. procedure TConstructorForm.ShipStartDrag(Sender: TObject;
  196.   var DragObject: TDragObject);
  197. begin
  198.     MovingShip := TImage(Sender);
  199.     IsMovingShipHorizontal := IsShipFromFormHorizontal(MovingShip);
  200.     MovingShipType := ConvertImageToShipType(MovingShip, IsMovingShipHorizontal);
  201. end;
  202.  
  203. procedure TConstructorForm.UserFieldImageDragOver(Sender, Source: TObject; X,
  204.   Y: Integer; State: TDragState; var Accept: Boolean);
  205. var
  206.     Col, Row: ShortInt;
  207. begin
  208.     Col := X div CELL_WIDTH;
  209.     Row := Y div CELL_WIDTH;
  210.  
  211.     Accept := CanPlaceShipHere(Field, MovingShipType, Col, Row, IsMovingShipHorizontal);
  212.     if Accept then
  213.     begin
  214.         TempField := Field;
  215.         PlaceShip(TempField, MovingShipType, Col, Row, IsMovingShipHorizontal);
  216.         DrawField(UserFieldImage, TempField);
  217.     end;
  218.  
  219.     if State = dsDragLeave then
  220.         DrawField(UserFieldImage, Field);
  221. end;
  222.  
  223. procedure EditImagesVisible(Ship: TShip; Value: Byte);
  224. begin
  225.     with ConstructorForm do
  226.     begin
  227.         if Value = 0 then
  228.         begin
  229.             case Ship of
  230.                 tShortShip:
  231.                 begin
  232.                     HShortShip.Visible := False;
  233.                     VShortShip.Visible := False;
  234.                 end;
  235.                 tSmallShip:
  236.                 begin
  237.                     HSmallShip.Visible := False;
  238.                     VSmallShip.Visible := False;
  239.                 end;
  240.                 tMiddleShip:
  241.                 begin
  242.                     HMiddleShip.Visible := False;
  243.                     VMiddleShip.Visible := False;
  244.                 end;
  245.                 tLongShip:
  246.                 begin
  247.                     HLongShip.Visible := False;
  248.                     VLongShip.Visible := False;
  249.                 end;
  250.             end;
  251.         end
  252.         else
  253.         begin
  254.             case Ship of
  255.                 tShortShip:
  256.                 begin
  257.                     HShortShip.Visible := True;
  258.                     VShortShip.Visible := True;
  259.                 end;
  260.                 tSmallShip:
  261.                 begin
  262.                     HSmallShip.Visible := True;
  263.                     VSmallShip.Visible := True;
  264.                 end;
  265.                 tMiddleShip:
  266.                 begin
  267.                     HMiddleShip.Visible := True;
  268.                     VMiddleShip.Visible := True;
  269.                 end;
  270.                 tLongShip:
  271.                 begin
  272.                     HLongShip.Visible := True;
  273.                     VLongShip.Visible := True;
  274.                 end;
  275.             end;
  276.         end;
  277.     end;
  278. end;
  279.  
  280. procedure TConstructorForm.UserFieldImageDragDrop(Sender, Source: TObject; X,
  281.   Y: Integer);
  282. var
  283.     Col, Row: Byte;
  284. begin
  285.     Col := X div CELL_WIDTH;
  286.     Row := Y div CELL_WIDTH;
  287.    //////////////////////////////////////////////////////////////////////////////////////
  288.     Dec(ShipsCountArr[MovingShipType]);
  289.     EditImagesVisible(MovingShipType, ShipsCountArr[MovingShipType]);
  290.     ///////////////////////////////////////////////////////////////////////////////////////
  291.     Field := TempField;
  292.     FillImpossibleCellsMatrix(ImpossibleCellsMatrix, MovingShipType, Col, Row, IsMovingShipHorizontal);
  293.  
  294.     DrawField(UserFieldImage, Field);
  295. end;
  296.  
  297. ////////////Поправляем вставленный корабль
  298. function IsShipInFieldHorizontal(Field: TField; Ship: TShip; Col, Row: ShortInt): Boolean;
  299. var
  300.     IsHorizontal: Boolean;
  301. begin
  302.     if Ship = tShortShip then
  303.         IsHorizontal := True
  304.     else
  305.     begin
  306.         if (Field[Col-1, Row] <> stImpossible) or (Field[Col+1, Row] <> stImpossible) then
  307.              IsHorizontal := True
  308.         else
  309.             IsHorizontal := False;
  310.     end;
  311.     IsShipInFieldHorizontal := IsHorizontal;
  312. end;
  313.  
  314. procedure TConstructorForm.TurnButtonClick(Sender: TObject);
  315. var
  316.    FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, I: ShortInt;
  317.    CanPlace: Boolean;
  318. begin
  319.     TempField := Field;
  320.     FindSideOfShip(TempField, MovingShipType, MovingShipCol, MovingShipRow, FirstSideCol, FirstSideRow, IsMovingShipHorizontal, -1);
  321.     FindSideOfShip(TempField, MovingShipType, MovingShipCol, MovingShipRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal, 1);
  322.  
  323.     DeleteShip(TempField, ImpossibleCellsMatrix, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal);
  324.  
  325.     if CanPlaceShipHere(TempField, MovingShipType, MovingShipCol, MovingShipRow, not IsMovingShipHorizontal) then
  326.     begin
  327.         PlaceShip(TempField, MovingShipType, MovingShipCol, MovingShipRow, not IsMovingShipHorizontal);
  328.         Field := TempField;
  329.         FillImpossibleCellsMatrix(ImpossibleCellsMatrix, MovingShipType, MovingShipCol, MovingShipRow, not IsMovingShipHorizontal);
  330.     end
  331.     else
  332.     begin
  333.         I := -1;
  334.         CanPlace := False;
  335.         repeat
  336.             Inc(I);
  337.             CanPlace := CanPlaceShipInLine(TempField, MovingShipType, I, not IsMovingShipHorizontal);
  338.         until CanPlace or (I = High(Field));
  339.  
  340.         if CanPlace then
  341.         begin
  342.             PlaceShipToField(TempField, ImpossibleCellsMatrix, MovingShipType, I, not IsMovingShipHorizontal);
  343.             Field := TempField;
  344.         end;
  345.     end;
  346.     DrawField(UserFieldImage, Field);
  347. end;
  348.  
  349. procedure TConstructorForm.DeleteShipButtonClick(Sender: TObject);
  350. var
  351.     FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow: ShortInt;
  352. begin
  353.     FindSideOfShip(Field, MovingShipType, MovingShipCol, MovingShipRow, FirstSideCol, FirstSideRow, IsMovingShipHorizontal, -1);
  354.     FindSideOfShip(Field, MovingShipType, MovingShipCol, MovingShipRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal, 1);
  355.  
  356.     DeleteShip(Field, ImpossibleCellsMatrix, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal);
  357.     DrawField(UserFieldImage, Field);
  358.     /////////////////////////////////////////////////////////////////////////////////////
  359.     Inc(ShipsCountArr[MovingShipType]);
  360.     EditImagesVisible(MovingShipType, ShipsCountArr[MovingShipType]);
  361.     //////////////////////////////////////////////////////////////////////////////////////
  362. end;
  363.  
  364. procedure TConstructorForm.UserFieldImageMouseDown(Sender: TObject;
  365.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  366. var
  367.     Col, Row, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow: ShortInt;
  368.     IsShip: Boolean;
  369. begin
  370.     Col := X div CELL_WIDTH;
  371.     Row := Y div CELL_WIDTH;
  372.  
  373.     IsShip := Ord(Field[Col, Row]) > 0;
  374.     if IsShip then
  375.     begin
  376.         MovingShipType := ConvertFieldStateToShip(Field[Col, Row]);
  377.         IsMovingShipHorizontal := IsShipInFieldHorizontal(Field, MovingShipType, Col, Row);
  378.  
  379.         case Button of
  380.             mbLeft:
  381.             begin
  382.                 IsDrag := True;
  383.  
  384.                 TempField := Field;
  385.                 TempMatrix := ImpossibleCellsMatrix;
  386.  
  387.                 FindSideOfShip(TempField, MovingShipType, Col, Row, FirstSideCol, FirstSideRow, IsMovingShipHorizontal, -1);
  388.                 FindSideOfShip(TempField, MovingShipType, Col, Row, SecondSideCol, SecondSideRow, IsMovingShipHorizontal, 1);
  389.  
  390.                 DeleteShip(TempField, TempMatrix, FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, IsMovingShipHorizontal);
  391.             end;
  392.             mbRight:
  393.             begin
  394.                 MovingShipCol := Col;
  395.                 MovingShipRow := Row;
  396.  
  397.                 X := X + Left + UserFieldImage.Left+15;
  398.                 Y :=  Y + Top + UserFieldImage.Top + 30;
  399.                 PopupMenu.Popup(X, Y);
  400.             end;
  401.             mbMiddle: ;
  402.         end;
  403.     end;
  404. end;
  405.  
  406. procedure TConstructorForm.UserFieldImageMouseMove(Sender: TObject;
  407.   Shift: TShiftState; X, Y: Integer);
  408. var
  409.     Col, Row: ShortInt;
  410.     CanPlaceShip, IsCursorOnField: Boolean;
  411. begin
  412.     if IsDrag then
  413.     begin
  414.         Col := X div CELL_WIDTH;
  415.         Row := Y div CELL_WIDTH;
  416.  
  417.         IsCursorOnField := (Col > -1) and (Col < 10)  and (Row > -1) and (Row < 10);
  418.         if IsCursorOnField then
  419.         begin
  420.             NewField := TempField;
  421.  
  422.             CanPlaceShip := CanPlaceShipHere(NewField, MovingShipType, Col, Row, IsMovingShipHorizontal);
  423.             if CanPlaceShip then
  424.             begin
  425.                 PlaceShip(NewField, MovingShipType, Col, Row, IsMovingShipHorizontal);
  426.                 DrawField(UserFieldImage, NewField);
  427.  
  428.                 MovingShipCol := Col;
  429.                 MovingShipRow := Row;
  430.  
  431.                 Field := NewField;
  432.                 IsShipPlaced := True;
  433.             end;
  434.         end;
  435.     end;
  436. end;
  437.  
  438. procedure TConstructorForm.UserFieldImageMouseUp(Sender: TObject;
  439.   Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  440. begin
  441.     if IsDrag and IsShipPlaced then
  442.     begin
  443.         FillImpossibleCellsMatrix(TempMatrix, MovingShipType, MovingShipCol, MovingShipRow, IsMovingShipHorizontal);
  444.         ImpossibleCellsMatrix := TempMatrix;
  445.     end;
  446.     IsShipPlaced := False;
  447.     IsDrag := False;
  448.     DrawField(UserFieldImage, Field);
  449. end;
  450.  
  451.  
  452. end.
  453.  
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470. unit FieldGeneratorUnit;
  471.  
  472. interface
  473. type
  474.     TFieldCellState = (stImpossible = -1, stFree, stShortShip, stSmallShip, stMiddleShip, stLongShip);
  475.     TField = array [-1..10, -1..10] of TFieldCellState;
  476.     TImpossibleCellsMatrix = array [-1..10, -1..10] of ShortInt;
  477.  
  478.     TShip = (tShortShip = 1, tSmallShip, tMiddleShip, tLongShip);
  479.     TShipsArray = array [0..9] of TShip;
  480.     TShipsCountArray = array [TShip] of Byte;
  481.  
  482.     TReturnCellStateFunction = function (ShipField: TField; Col, Row, I: ShortInt): TFieldCellState;
  483.     TReturnLineCellStateFunction = function (ShipField: TField; J, I: ShortInt): TFieldCellState;
  484.     TPlaceShipProcedure = procedure (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
  485.     TCompareFunction = function(ShootField: TField; Ship: TShip; Col, Row, I: ShortInt): Boolean;
  486.  
  487.     TCellsArray = array [0..99] of Byte;
  488.  
  489.     function CreateField(): TField;
  490.     procedure FindSideOfShip(ShootField: TField; Ship: TShip; Col, Row: ShortInt; var SideCol: ShortInt; var SideRow: ShortInt; IsHorizontal: Boolean; DirectionCoef: ShortInt);
  491.     procedure DeleteShip (var Field: TField; var Matrix: TImpossibleCellsMatrix; Col1, Row1, Col2, Row2: ShortInt; IsHorizontal: Boolean);
  492.     function ConvertShipToFieldState(Ship: TShip): TFieldCellState;
  493.     function ConvertFieldStateToShip(FieldState: TFieldCellState): TShip;
  494.     procedure PlaceShip(var Field: TField; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
  495.     function CreateImpossibleCellsMatrix(): TImpossibleCellsMatrix;
  496.     procedure FillImpossibleCellsMatrix(var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
  497.     function IinializeShipsCountArray(): TShipsCountArray;
  498.     function GenerateField(var ImpossibleCellsMatrix: TImpossibleCellsMatrix): TField;
  499.     function CanPlaceShipInLine(Field: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): Boolean;
  500.     procedure PlaceShipToField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean);
  501. implementation
  502.  
  503. function CreateField(): TField;
  504. var
  505.     I, J: ShortInt;
  506.     NewField: TField;
  507. begin
  508.     for J := Low(NewField) to High(NewField) do
  509.         NewField[-1, J] := stImpossible;
  510.  
  511.     for I := Low(NewField)+1 to High(NewField)-1 do
  512.     begin
  513.         for J := Low(NewField)+1 to High(NewField)-1 do
  514.             NewField[I, J] := stFree;
  515.         NewField[I, Low(NewField)] := stImpossible;
  516.         NewField[I, High(NewField)] := stImpossible;
  517.     end;
  518.  
  519.     for J := Low(NewField) to High(NewField) do
  520.         NewField[High(NewField), J] := stImpossible;
  521.  
  522.     CreateField := NewField;
  523. end;
  524.  
  525. function CreateImpossibleCellsMatrix(): TImpossibleCellsMatrix;
  526. var
  527.     I, J: ShortInt;
  528.     NewField: TImpossibleCellsMatrix;
  529. begin
  530.     for J := Low(NewField) to High(NewField) do
  531.         NewField[-1, J] := 1;
  532.  
  533.     for I := Low(NewField)+1 to High(NewField)-1 do
  534.     begin
  535.         for J := Low(NewField)+1 to High(NewField)-1 do
  536.             NewField[I, J] := 0;
  537.         NewField[I, Low(NewField)] := 1;
  538.         NewField[I, High(NewField)] := 1;
  539.     end;
  540.  
  541.     for J := Low(NewField) to High(NewField) do
  542.         NewField[High(NewField), J] := 1;
  543.  
  544.     CreateImpossibleCellsMatrix := NewField;
  545. end;
  546.  
  547. function IinializeShipsCountArray(): TShipsCountArray;
  548. var
  549.     Arr: TShipsCountArray;
  550.     I: TShip;
  551. begin
  552.     for I := tShortShip to tLongShip do
  553.         Arr[I] := 5-Ord(I);
  554.  
  555.     IinializeShipsCountArray := Arr;
  556. end;
  557.  
  558. function ConvertShipToFieldState(Ship: TShip): TFieldCellState;
  559. const
  560.     TempArr: array [TShip] of TFieldCellState = (stShortShip, stSmallShip, stMiddleShip, stLongShip);
  561. begin
  562.     ConvertShipToFieldState := TempArr[Ship];
  563. end;
  564.  
  565. function ConvertFieldStateToShip(FieldState: TFieldCellState): TShip;
  566. const
  567.     TempArr: array [stShortShip..stLongShip] of TShip = (tShortShip, tSmallShip, tMiddleShip, tLongShip);
  568. begin
  569.     ConvertFieldStateToShip := TempArr[FieldState];
  570. end;
  571.  
  572. function CompareCellsVertically(ShootField: TField; Ship: TShip; Col,Row,I: ShortInt): Boolean;
  573. begin
  574.     CompareCellsVertically := ShootField[Col, Row+I] = ConvertShipToFieldState(Ship);
  575. end;
  576.  
  577. function CompareCellsHorizontally(ShootField: TField; Ship: TShip; Col,Row,I: ShortInt): Boolean;
  578. begin
  579.     CompareCellsHorizontally := ShootField[Col+I, Row] = ConvertShipToFieldState(Ship);
  580. end;
  581.  
  582. procedure FindSideOfShip(ShootField: TField; Ship: TShip; Col, Row: ShortInt; var SideCol: ShortInt; var SideRow: ShortInt; IsHorizontal: Boolean; DirectionCoef: ShortInt);
  583. var
  584.     I: ShortInt;
  585.     HasPartOfShip: Boolean;
  586. begin
  587.     if IsHorizontal then
  588.     begin
  589.         I := 0;
  590.         Repeat
  591.             Inc(I);
  592.             HasPartOfShip := CompareCellsHorizontally(ShootField, Ship, Col, Row, DirectionCoef*I);
  593.         Until not HasPartOfShip;
  594.  
  595.         SideRow := Row;
  596.         SideCol := Col + DirectionCoef * I;
  597.     end
  598.     else
  599.     begin
  600.         I := 0;
  601.         Repeat
  602.             Inc(I);
  603.             HasPartOfShip := CompareCellsVertically(ShootField, Ship, Col, Row, DirectionCoef*I);
  604.         Until not HasPartOfShip;
  605.         SideCol := Col;
  606.         SideRow := Row + DirectionCoef * I;
  607.     end;
  608. end;
  609.  
  610. procedure DeleteShipPart (var Field: TField; var Matrix: TImpossibleCellsMatrix; Col, Row: ShortInt);
  611. begin
  612.     Dec(Matrix[Col, Row]);
  613.     if (Matrix[Col, Row] = 0) then
  614.         Field[Col, Row] := stFree;
  615. end;
  616.  
  617. procedure DeleteShip (var Field: TField; var Matrix: TImpossibleCellsMatrix; Col1, Row1, Col2, Row2: ShortInt; IsHorizontal: Boolean);
  618. var
  619.     I: ShortInt;
  620. begin
  621.     if IsHorizontal then
  622.         for I := Col1 to Col2 do
  623.         begin
  624.             DeleteShipPart(Field, Matrix, I, Row1-1);
  625.             DeleteShipPart(Field, Matrix, I, Row1);
  626.             DeleteShipPart(Field, Matrix, I, Row1+1);
  627.         end
  628.     else
  629.         for I := Row1 to Row2 do
  630.         begin
  631.             DeleteShipPart(Field, Matrix, Col1-1, I);
  632.             DeleteShipPart(Field, Matrix, Col1, I);
  633.             DeleteShipPart(Field, Matrix, Col1+1, I);
  634.         end;
  635. end;
  636.  
  637. procedure FillImpossibleCellsHorizontaly (var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt);
  638. var
  639.     I: ShortInt;
  640. begin
  641.     for I := -1 to Ord(Ship) do
  642.     begin
  643.         Inc(Matrix[X+I, Y-1]);
  644.         Inc(Matrix[X+I, Y]);
  645.         Inc(Matrix[X+I, Y+1]);
  646.     end;
  647. end;
  648.  
  649. procedure FillImpossibleCellsVerticaly (var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt);
  650. var
  651.     I: ShortInt;
  652. begin
  653.     for I := -1 to Ord(Ship) do
  654.     begin
  655.         Inc(Matrix[X-1, Y+I]);
  656.         Inc(Matrix[X, Y+I]);
  657.         Inc(Matrix[X+1, Y+I]);
  658.     end;
  659. end;
  660.  
  661. procedure FillImpossibleCellsMatrix(var Matrix: TImpossibleCellsMatrix; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
  662. begin
  663.     if IsHorizontal then
  664.         FillImpossibleCellsHorizontaly(Matrix, Ship, X, Y)
  665.     else
  666.         FillImpossibleCellsVerticaly(Matrix, Ship, X, Y);
  667. end;
  668.  
  669. procedure PlaceShipHorizontal (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
  670. var
  671.     I: ShortInt;
  672. begin
  673.     for I := -1 to Ord(Ship) do
  674.     begin
  675.         ShipsField[X+I, Y-1] := stImpossible;
  676.         ShipsField[X+I, Y] := ConvertShipToFieldState(Ship);
  677.         ShipsField[X+I, Y+1] := stImpossible;
  678.     end;
  679.     ShipsField[X-1, Y] := stImpossible;
  680.     ShipsField[X+Ord(Ship), Y] := stImpossible;
  681. end;
  682.  
  683. procedure PlaceShipVertical (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
  684. var
  685.     I: ShortInt;
  686. begin
  687.     for I := -1 to Ord(Ship) do
  688.     begin
  689.         ShipsField[X-1, Y+I] := stImpossible;
  690.         ShipsField[X, Y+I] := ConvertShipToFieldState(Ship);
  691.         ShipsField[X+1, Y+I] := stImpossible;
  692.     end;
  693.     ShipsField[X, Y-1] := stImpossible;
  694.     ShipsField[X, Y+Ord(Ship)] := stImpossible;
  695. end;
  696.  
  697. procedure PlaceShip(var Field: TField; Ship: TShip; X, Y: ShortInt; IsHorizontal: Boolean);
  698. begin
  699.     if IsHorizontal then
  700.         PlaceShipHorizontal (Field, Ship, X, Y)
  701.     else
  702.         PlaceShipVertical (Field, Ship, X, Y);
  703. end;
  704. ////////////////////////////////////////////////////////////////////////////////////////
  705.  
  706. procedure InitializeShips(var ShipsArray: TShipsArray);
  707. var
  708.     CurrShip: TShip;
  709.     I, J: Byte;
  710. begin
  711.     J := Low(ShipsArray);
  712.     for CurrShip := Low(TShip) to High(TShip) do
  713.         for I := 5 - Ord(CurrShip) DownTo 1 do
  714.         begin
  715.             ShipsArray[J] := CurrShip;
  716.             Inc(J);
  717.         end;
  718. end;
  719.  
  720. function ReturnHorizontalLineCellState(ShipField: TField; Row, I: ShortInt): TFieldCellState;
  721. begin
  722.     ReturnHorizontalLineCellState := ShipField[I, Row];
  723. end;
  724.  
  725. function ReturnVerticalLineCellState(ShipField: TField; Col, I: ShortInt): TFieldCellState;
  726. begin
  727.     ReturnVerticalLineCellState := ShipField[Col, I];
  728. end;
  729.  
  730. function CanPlaceShipInLine(Field: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): Boolean;
  731. var
  732.     I, Counter: ShortInt;
  733.     HasFreePlace: Boolean;
  734.     ReturnCellState: TReturnLineCellStateFunction;
  735. begin
  736.     Counter := 0;
  737.     HasFreePlace := False;
  738.     I := Low(Field)+1;
  739.  
  740.     if IsHorizontal then
  741.         ReturnCellState := ReturnHorizontalLineCellState
  742.     else
  743.         ReturnCellState := ReturnVerticalLineCellState;
  744.  
  745.     while not HasFreePlace and (I < High(Field)) do
  746.     begin
  747.         if Ord(ReturnCellState(Field, Coord, I)) = 0 then
  748.             Inc(Counter)
  749.         else
  750.             Counter := 0;
  751.  
  752.         if Counter = Ord(Ship) then
  753.             HasFreePlace := True;
  754.         Inc(I);
  755.     end;
  756.  
  757.     CanPlaceShipInLine := HasFreePlace;
  758. end;
  759.  
  760. function GetSecondCoord(var Field: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): ShortInt;
  761. var
  762.     I, Counter, StartCell, PossibleCellCount: ShortInt;
  763.     ReturnCellState: TReturnLineCellStateFunction;
  764. begin
  765.     Counter := 0;
  766.     PossibleCellCount := 0;
  767.     I := Low(Field)+1;
  768.  
  769.     if IsHorizontal then
  770.         ReturnCellState := ReturnHorizontalLineCellState
  771.     else
  772.         ReturnCellState := ReturnVerticalLineCellState;
  773.  
  774.     while I < High(Field) do
  775.     begin
  776.         if Ord(ReturnCellState(Field, Coord, I)) = 0 then
  777.             Inc(Counter)
  778.         else
  779.         begin
  780.             Counter := 0;
  781.             PossibleCellCount := 0;
  782.         end;
  783.  
  784.         if Counter = Ord(Ship) then
  785.             StartCell :=  I - Ord(Ship)+1;
  786.  
  787.         if (Counter - Ord(Ship)) > PossibleCellCount then
  788.             PossibleCellCount := Counter - Ord(Ship);
  789.  
  790.         Inc(I);
  791.     end;
  792.  
  793.     GetSecondCoord := StartCell + Random(PossibleCellCount + 1);
  794. end;
  795.  
  796. function PullShip(var ShipsArray: TShipsArray; CommonShipsCount: Byte): TShip;
  797. var
  798.     Ship: TShip;
  799. begin
  800.     Ship := ShipsArray[CommonShipsCount-1];
  801.     PullShip := Ship;
  802. end;
  803.  
  804. function GetRandomDirection(): Boolean;
  805. var
  806.     IsHorizontal: Boolean;
  807. begin
  808.     IsHorizontal := Random(2) = 0;
  809.     GetRandomDirection := isHorizontal;
  810. end;
  811.  
  812. procedure PlaceShipToField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean);
  813. var
  814.     SecondCoord: ShortInt;
  815. begin
  816.     SecondCoord := GetSecondCoord(Field, Ship, Coord, IsHorizontal);
  817.  
  818.     if IsHorizontal then
  819.     begin
  820.         PlaceShipHorizontal(Field, Ship, SecondCoord, Coord);
  821.         FillImpossibleCellsHorizontaly(ImpossibleCellsMatrix, Ship, SecondCoord, Coord);
  822.     end
  823.     else
  824.     begin
  825.         PlaceShipVertical(Field, Ship, Coord, SecondCoord);
  826.         FillImpossibleCellsVerticaly(ImpossibleCellsMatrix, Ship, Coord, SecondCoord);
  827.     end;
  828. end;
  829.  
  830. procedure PutShipToField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; Ship: TShip);
  831. var
  832.     Coord, SecondCoord: ShortInt;
  833.     IsHorizontal: Boolean;
  834. begin
  835.     repeat
  836.         IsHorizontal := GetRandomDirection();
  837.         Coord := Random(10);
  838.     until CanPlaceShipInLine(Field, Ship, Coord, IsHorizontal);
  839.  
  840.     PlaceShipToField(Field, ImpossibleCellsMatrix, Ship, Coord, IsHorizontal);
  841. end;
  842.  
  843. procedure FillGameField(var Field: TField; var ImpossibleCellsMatrix: TImpossibleCellsMatrix; var ShipsArray: TShipsArray; var CommonShipsCount: Byte);
  844. var
  845.     Ship: TShip;
  846.     I: ShortInt;
  847. begin
  848.     for I := 1 to 10 do
  849.     begin
  850.         Ship := PullShip(ShipsArray, CommonShipsCount);
  851.         Dec(CommonShipsCount);
  852.         PutShipToField(Field, ImpossibleCellsMatrix, Ship);
  853.     end;
  854. end;
  855.  
  856. function GenerateField(var ImpossibleCellsMatrix: TImpossibleCellsMatrix): TField;
  857. var
  858.     NewField: TField;
  859.     ShipsArray: TShipsArray;
  860.     CommonShipsCount: Byte;
  861. begin
  862.     CommonShipsCount := 10;
  863.     NewField := CreateField();
  864.     InitializeShips(ShipsArray);
  865.     FillGameField(NewField, ImpossibleCellsMatrix, ShipsArray, CommonShipsCount);
  866.  
  867.     GenerateField := NewField;
  868. end;
  869.  
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement