Advertisement
THOMAS_SHELBY_18

back 10/04

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