Advertisement
THOMAS_SHELBY_18

New Generator + Shooter + ListUnit

Apr 3rd, 2024 (edited)
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 16.30 KB | Source Code | 0 0
  1. program Intellect;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. {$R *.res}
  6.  
  7. uses
  8.   System.SysUtils,
  9.   ListUnit in 'ListUnit.pas';
  10.  
  11. type
  12.     TFieldCellState = (stImpossible = -1, stFree, stShortShip, stSmallShip, stMiddleShip, stLongShip);
  13.     TField = array [-1..10, -1..10] of TFieldCellState;
  14.  
  15.     TShip = (tShortShip = 1, tSmallShip, tMiddleShip, tLongShip);
  16.     TShipsArray = array [0..9] of TShip;
  17.  
  18.     TReturnCellStateFunction = function (ShipField: TField; I, J: ShortInt): TFieldCellState;
  19.     TPlaceShipProcedure = procedure (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
  20.     TCompareFunction = function(ShootField: TField; Ship: TShip; Col, Row, I: ShortInt): Boolean;
  21.  
  22.     TCellsArray = array [0..99] of Byte;
  23.  
  24.  
  25. var
  26.     TempField, ShootField: TField;
  27.     ShipsArray: TShipsArray;
  28.     CommonShipsCount, I: Byte;
  29.     FreeCellsCount: ShortInt;
  30.     CellsIndex, FreeCells: TCellsArray;
  31.     PriorityCellsListHeader: PListElem;
  32.  
  33. procedure CreateNewField(var Field: TField);
  34. var
  35.     I, J: ShortInt;
  36. begin
  37.     for J := Low(Field) to High(Field) do
  38.         Field[-1, J] := stImpossible;
  39.  
  40.     for I := Low(Field)+1 to High(Field)-1 do
  41.     begin
  42.         for J := Low(Field)+1 to High(Field)-1 do
  43.             Field[I, J] := stFree;
  44.         Field[I, Low(Field)] := stImpossible;
  45.         Field[I, High(Field)] := stImpossible;
  46.     end;
  47.  
  48.     for J := Low(Field) to High(Field) do
  49.         Field[High(Field), J] := stImpossible;
  50. end;
  51.  
  52. procedure OutputField(Field: TField);
  53. var
  54.     I, J: ShortInt;
  55. begin
  56.     for I := Low(Field) to High(Field) do
  57.     begin
  58.         for J := Low(Field) to High(Field) do
  59.             Write(StrToFloat(IntToStr(Ord(Field[J, I]))):4:0);
  60.         Writeln;
  61.     end;
  62. end;
  63.  
  64. procedure InitializeShips(var ShipsArray: TShipsArray);
  65. var
  66.     CurrShip: TShip;
  67.     I, J: Byte;
  68. begin
  69.     J := Low(ShipsArray);
  70.     for CurrShip := Low(TShip) to High(TShip) do
  71.         for I := 5 - Ord(CurrShip) DownTo 1 do
  72.         begin
  73.             ShipsArray[J] := CurrShip;
  74.             Inc(J);
  75.         end;
  76.  
  77.     CommonShipsCount := 10;
  78. end;
  79.  
  80. procedure OutputShips(ShipsArray: TShipsArray);
  81. var
  82.     I: Byte;
  83. begin
  84.     for I := Low(ShipsArray) to CommonShipsCount-1 do
  85.         Write(Ord(ShipsArray[I]), ' ');
  86. end;
  87.  
  88. function PullShip(var ShipsArray: TShipsArray): TShip;
  89. var
  90.     Ship: TShip;
  91. begin
  92.     Ship := ShipsArray[CommonShipsCount-1];
  93.     Dec(CommonShipsCount);
  94.  
  95.     PullShip := Ship;
  96. end;
  97.  
  98. function GetRandomDirection(): Boolean;
  99. var
  100.     IsHorizontal: Boolean;
  101. begin
  102.     if Random(2) = 0 then
  103.         IsHorizontal := True
  104.     else
  105.         IsHorizontal := False;
  106.  
  107.     GetRandomDirection := isHorizontal;
  108. end;
  109.  
  110. function ConvertShipToFieldState(Ship: TShip): TFieldCellState;
  111. const
  112.     TempArr: array [TShip] of TFieldCellState = (stShortShip, stSmallShip, stMiddleShip, stLongShip);
  113. begin
  114.     ConvertShipToFieldState := TempArr[Ship];
  115. end;
  116.  
  117. function ConvertFieldStateToShip(FieldState: TFieldCellState): TShip;
  118. const
  119.     TempArr: array [stShortShip..stLongShip] of TShip = (tShortShip, tSmallShip, tMiddleShip, tLongShip);
  120. begin
  121.     ConvertFieldStateToShip := TempArr[FieldState];
  122. end;
  123.  
  124. function ReturnRowElemState(ShipField: TField; I, J: ShortInt): TFieldCellState;
  125. begin
  126.     ReturnRowElemState := ShipField[J, I];
  127. end;
  128.  
  129. function ReturnColElemState(ShipField: TField; I, J: ShortInt): TFieldCellState;
  130. begin
  131.     ReturnColElemState := ShipField[I, J];
  132. end;
  133.  
  134. procedure PlaceShipHorizontal (var ShipsField: TField; Ship: TShip; Y, X: ShortInt);
  135. var
  136.     I: ShortInt;
  137. begin
  138.     for I := -1 to Ord(Ship) do
  139.     begin
  140.         ShipsField[X+I, Y-1] := stImpossible;
  141.         ShipsField[X+I, Y] := ConvertShipToFieldState(Ship);
  142.         ShipsField[X+I, Y+1] := stImpossible;
  143.     end;
  144.     ShipsField[X-1, Y] := stImpossible;
  145.     ShipsField[X+Ord(Ship), Y] := stImpossible;
  146. end;
  147.  
  148. procedure PlaceShipVertical (var ShipsField: TField; Ship: TShip; X, Y: ShortInt);
  149. var
  150.     I: ShortInt;
  151. begin
  152.     for I := -1 to Ord(Ship) do
  153.     begin
  154.         ShipsField[X-1, Y+I] := stImpossible;
  155.         ShipsField[X, Y+I] := ConvertShipToFieldState(Ship);
  156.         ShipsField[X+1, Y+I] := stImpossible;
  157.     end;
  158.     ShipsField[X, Y-1] := stImpossible;
  159.     ShipsField[X, Y+Ord(Ship)] := stImpossible;
  160. end;
  161.  
  162. function IsShipPlacedInField(var ShipsField: TField; Ship: TShip; Coord: ShortInt; IsHorizontal: Boolean): Boolean;
  163. var
  164.     I, SecondCoord, Counter, StartCell, PossibleCellCount: ShortInt;
  165.     HasFreePlace: Boolean;
  166.     ReturnCellState: TReturnCellStateFunction;
  167.     PlaceShip: TPlaceShipProcedure;
  168. begin
  169.     PossibleCellCount := 0;
  170.     Counter := 0;
  171.     HasFreePlace := False;
  172.     I := Low(ShipsField)+1;
  173.  
  174.     if IsHorizontal then
  175.     begin
  176.         ReturnCellState := ReturnColElemState;
  177.         PlaceShip := PlaceShipHorizontal;
  178.     end
  179.     else
  180.     begin
  181.         ReturnCellState := ReturnRowElemState;
  182.         PlaceShip := PlaceShipVertical;
  183.     end;
  184.  
  185.     while I < High(ShipsField) do
  186.     begin
  187.         if Ord(ReturnCellState(ShipsField, I, Coord)) = 0 then
  188.             Inc(Counter)
  189.         else
  190.         begin
  191.             Counter := 0;
  192.             PossibleCellCount := 0;
  193.         end;
  194.  
  195.         if Counter = Ord(Ship) then
  196.         begin
  197.             HasFreePlace := True;
  198.             StartCell :=  I - Ord(Ship)+1;
  199.         end;
  200.  
  201.         if (Counter - Ord(Ship)) > PossibleCellCount then
  202.             PossibleCellCount := Counter - Ord(Ship);
  203.  
  204.         Inc(I);
  205.     end;
  206.  
  207.     if HasFreePlace then
  208.     begin
  209.         SecondCoord := StartCell + Random(PossibleCellCount + 1);
  210.         PlaceShip(ShipsField, Ship, Coord, SecondCoord );
  211.     end;
  212.  
  213.     IsShipPlacedInField := HasFreePlace;
  214. end;
  215.  
  216. procedure PutShipToField(Ship: TShip; var ShipsField: TField);
  217. var
  218.     Coord: ShortInt;
  219.     IsHorizontal: Boolean;
  220. begin
  221.     repeat
  222.         IsHorizontal := GetRandomDirection;
  223.         Coord := Random(10);
  224.     until IsShipPlacedInField(ShipsField, Ship, Coord, IsHorizontal);
  225. end;
  226.  
  227. procedure FillGameField(var Field: TField; var ShipsArray: TShipsArray);
  228. var
  229.     Ship: TShip;
  230.     I: ShortInt;
  231. begin
  232.     for I := 1 to 10 do
  233.     begin
  234.         Ship := PullShip(ShipsArray);
  235.         PutShipToField(Ship, TempField);
  236.     end;
  237. end;
  238.  
  239. procedure CellsArrayInitialize(var FreeCells: TCellsArray);
  240. var
  241.     I, J, Temp: Byte;
  242. begin
  243.     for I := 0 to 9 do
  244.         for J := 0 to 9 do
  245.         begin
  246.             Temp := I + 9 * I + J;
  247.             FreeCells[Temp] := Temp;
  248.         end;
  249.     FreeCellsCount := 100;
  250. end;
  251.  
  252. procedure EditFreeCells(ShootField: TField; var FreeCells: TCellsArray; var CellsIndex: TCellsArray; Col, Row: ShortInt; var FreeCellsCount: ShortInt);
  253. var
  254.     LastFreeCellsValue, Coord: Byte;
  255. begin
  256.     if ShootField[Col, Row] <> stImpossible then
  257.     begin
  258.         Coord := 10 * Col + Row;
  259.         LastFreeCellsValue := FreeCells[FreeCellsCount-1];
  260.         FreeCells[CellsIndex[Coord]] := LastFreeCellsValue;
  261.         CellsIndex[LastFreeCellsValue] := CellsIndex[Coord];
  262.         Dec(FreeCellsCount);
  263.     end;
  264. end;
  265.  
  266. procedure EditFieldAroundShootPlace(var ShootField: TField; var FreeCells: TCellsArray; var CellsIndex: TCellsArray; Col, Row: ShortInt; var FreeCellsCount: ShortInt);
  267. var
  268.     I, J: ShortInt;
  269. begin
  270.     I := -1;
  271.     while I < 2 do
  272.     begin
  273.         J := -1;
  274.         while J < 2 do
  275.         begin
  276.             EditFreeCells(ShootField, FreeCells, CellsIndex, Col+I, Row+J, FreeCellsCount);
  277.             ShootField[Col+I, Row+J] := stImpossible;
  278.             Inc(J, 2);
  279.         end;
  280.         Inc(I, 2);
  281.     end;
  282. end;
  283.  
  284. function CompareCellsVertically(ShootField: TField; Ship: TShip; Col,Row,I: ShortInt): Boolean;
  285. begin
  286.     CompareCellsVertically := ShootField[Col, Row+I] = ConvertShipToFieldState(Ship);
  287. end;
  288.  
  289. function CompareCellsHorizontally(ShootField: TField; Ship: TShip; Col,Row,I: ShortInt): Boolean;
  290. begin
  291.     CompareCellsHorizontally := ShootField[Col+I, Row] = ConvertShipToFieldState(Ship);
  292. end;
  293.  
  294. procedure FindSideOfShip(ShootField: TField; Ship: TShip; Col, Row: ShortInt; var FirstSideCol: ShortInt; var FirstSideRow: ShortInt; IsHorizontal: Boolean; DirectionCoef: ShortInt);
  295. var
  296.     I: ShortInt;
  297.     HasPartOfShip: Boolean;
  298. begin
  299.     if IsHorizontal then
  300.     begin
  301.         I := 0;
  302.         Repeat
  303.             Inc(I);
  304.             HasPartOfShip := CompareCellsHorizontally(ShootField, Ship, Col, Row, DirectionCoef*I);
  305.         Until not HasPartOfShip;
  306.  
  307.         FirstSideRow := Row;
  308.         FirstSideCol := Col + DirectionCoef * I;
  309.     end
  310.     else
  311.     begin
  312.         I := 0;
  313.         Repeat
  314.             Inc(I);
  315.             HasPartOfShip := CompareCellsVertically(ShootField, Ship, Col, Row, DirectionCoef*I);
  316.         Until not HasPartOfShip;
  317.         FirstSideCol := Col;
  318.         FirstSideRow := Row + DirectionCoef * I;
  319.     end;
  320. end;
  321.  
  322. procedure EditFieldForDestroyedShip(var ShootField: TField; Ship: TShip; var FreeCells: TCellsArray; var CellsIndex: TCellsArray; Col, Row: ShortInt; var FreeCellsCount: ShortInt; IsHorizontal: Boolean);
  323. var
  324.     FirstSideCol, FirstSideRow, SecondSideCol, SecondSideRow, I: ShortInt;
  325. begin
  326.     if Ship = tShortShip then
  327.     begin
  328.         I := -1;
  329.         while I < 2 do
  330.         begin
  331.             EditFreeCells(ShootField, FreeCells, CellsIndex, Col+I, Row, FreeCellsCount);
  332.             EditFreeCells(ShootField, FreeCells, CellsIndex, Col, Row+I, FreeCellsCount);
  333.             ShootField[Col+I, Row] := stImpossible;
  334.             ShootField[Col, Row+I] := stImpossible;
  335.             Inc(I, 2);
  336.         end;
  337.     end
  338.     else
  339.     begin
  340.         FindSideOfShip(ShootField, Ship, Col, Row, FirstSideCol, FirstSideRow, IsHorizontal, -1);
  341.         FindSideOfShip(ShootField, Ship, Col, Row, SecondSideCol, SecondSideRow, IsHorizontal, 1);
  342.  
  343.         EditFreeCells(ShootField, FreeCells, CellsIndex, FirstSideCol, FirstSideRow, FreeCellsCount);
  344.         EditFreeCells(ShootField, FreeCells, CellsIndex, SecondSideCol, SecondSideRow, FreeCellsCount);
  345.         ShootField[FirstSideCol, FirstSideRow] := stImpossible;
  346.         ShootField[SecondSideCol, SecondSideRow] := stImpossible;
  347.     end;
  348. end;
  349.  
  350. function IsShipDestroyed(ShootField: TField; Ship: TShip; Col, Row: ShortInt; CompareFieldCellAndShipsDeck: TCompareFunction): Boolean;
  351. var
  352.     I, DamagedDecksCount: ShortInt;
  353.     IsDestroyed, HasPartOfShip: Boolean;
  354. begin
  355.     DamagedDecksCount := 0;
  356.     I := 0;
  357.     Repeat
  358.         HasPartOfShip := CompareFieldCellAndShipsDeck(ShootField, Ship, Col, Row, -I);
  359.         if HasPartOfShip then
  360.            Inc(DamagedDecksCount);
  361.         Inc(I);
  362.     Until (I = Ord(Ship)) or not HasPartOfShip;
  363.     IsDestroyed := DamagedDecksCount = Ord(Ship);
  364.  
  365.     if not IsDestroyed then
  366.     begin
  367.         I := 1;
  368.         Repeat
  369.             HasPartOfShip := CompareFieldCellAndShipsDeck(ShootField, Ship, Col, Row, I);
  370.             if HasPartOfShip then
  371.                 Inc(DamagedDecksCount);
  372.             Inc(I);
  373.         Until (I = Ord(Ship)) or not HasPartOfShip;
  374.         IsDestroyed := DamagedDecksCount = Ord(Ship);
  375.     end;
  376.  
  377.     IsShipDestroyed := IsDestroyed;
  378. end;
  379.  
  380. function IsFieldCellFree(ShootField: TField; Col, Row: ShortInt): Boolean;
  381. begin
  382.     IsFieldCellFree := ShootField [Col, Row] = stFree;
  383. end;
  384.  
  385. procedure AddPriorityCellsToList (ListHeader: PListElem; ShootField: TField; Col, Row: ShortInt);
  386. var
  387.     I: ShortInt;
  388. begin
  389.     I := -1;
  390.     while I < 2 do
  391.     begin
  392.         if IsFieldCellFree(ShootField, Col+I, Row) then
  393.             AddListElem(ListHeader, 10 * (Col+I) + Row);
  394.         if IsFieldCellFree(ShootField, Col, Row+I) then
  395.             AddListElem(ListHeader, 10 * Col + (Row+I));
  396.  
  397.         Inc(I, 2);
  398.     end;
  399. end;
  400.  
  401. procedure MakeShoot(var ShootField: TField; UserField: TField; var FreeCells: TCellsArray; var CellsIndex: TCellsArray; var FreeCellsCount: ShortInt);
  402. var
  403.     ListElem: PListElem;
  404.     Coord, I, Col, Row: ShortInt;
  405.     State: TFieldCellState;
  406.     Ship: TShip;
  407.     IsDestroyedShipHorizontal, IsDestroyedShipVertical: Boolean;
  408. begin
  409.     if (PriorityCellsListHeader^.Next = nil) then
  410.     begin
  411.         I := Random(FreeCellsCount);
  412.         Coord := FreeCells[I];
  413.         FreeCells[I] := FreeCells[FreeCellsCount-1];
  414.         CellsIndex[FreeCellsCount-1] := I;
  415.         Dec(FreeCellsCount);
  416.  
  417.         Col := Coord div 10;
  418.         Row := Coord mod 10;
  419.     end
  420.     else
  421.     begin
  422.         repeat
  423.             ListElem := ExtractElem(PriorityCellsListHeader);
  424.             Coord := ListElem^.Coord;
  425.             Col := Coord div 10;
  426.             Row := Coord mod 10;
  427.             EditFreeCells(ShootField, FreeCells, CellsIndex, Col, Row, FreeCellsCount);
  428.         until (PriorityCellsListHeader^.Next = nil) or (ShootField[Col, Row] = stFree);
  429.  
  430.     end;
  431.  
  432.     State := UserField[Col, Row];
  433.     case State of
  434.         stFree:
  435.         begin
  436.             ShootField[Col, Row] := stImpossible;
  437.         end;
  438.         stImpossible:
  439.         begin
  440.             ShootField[Col, Row] := stImpossible;
  441.         end;
  442.         stShortShip:
  443.         begin
  444.             Ship := tShortShip;
  445.             ShootField[Col, Row] := State;
  446.             EditFieldAroundShootPlace(ShootField, FreeCells, CellsIndex, Col, Row, FreeCellsCount);
  447.             EditFieldForDestroyedShip(ShootField, Ship, FreeCells, CellsIndex, Col, Row, FreeCellsCount, True);
  448.         end;
  449.         else
  450.         begin
  451.             Ship := ConvertFieldStateToShip(State);
  452.             ShootField[Col, Row] := State;
  453.             EditFieldAroundShootPlace(ShootField, FreeCells, CellsIndex, Col, Row, FreeCellsCount);
  454.             AddPriorityCellsToList(PriorityCellsListHeader, ShootField, Col, Row);
  455.  
  456.             IsDestroyedShipHorizontal := IsShipDestroyed(ShootField, Ship, Col, Row, CompareCellsHorizontally);
  457.             IsDestroyedShipVertical := IsShipDestroyed(ShootField, Ship, Col, Row, CompareCellsVertically);
  458.             if IsDestroyedShipHorizontal or IsDestroyedShipVertical then
  459.             begin
  460.                 EditFieldForDestroyedShip(ShootField, Ship, FreeCells, CellsIndex, Col, Row, FreeCellsCount, IsDestroyedShipHorizontal);
  461.                 DisposeList(PriorityCellsListHeader);
  462.             end;
  463.         end;
  464.     end;
  465. end;
  466.  
  467. begin
  468.     Randomize;
  469.     CreateNewField(TempField);
  470.     OutputField(TempField);
  471.  
  472.     InitializeShips(ShipsArray);
  473.     OutputShips(ShipsArray);
  474.  
  475.     FillGameField(TempField, ShipsArray);
  476.     Writeln;
  477.     Writeln;
  478.  
  479.     OutputField(TempField);
  480.  
  481.  
  482.     CellsArrayInitialize(FreeCells);
  483.     CellsArrayInitialize(CellsIndex);
  484.     CreateNewField(ShootField);
  485.  
  486.  
  487.     InitializeList(PriorityCellsListHeader);
  488.  
  489.     //for I := 1 to 15 do
  490.  
  491.     while FreeCellsCount > 0 do
  492.     begin
  493.         MakeShoot(ShootField, TempField, FreeCells, CellsIndex, FreeCellsCount);
  494.     end;
  495.          Writeln;
  496.     Writeln;
  497.     OutputField(ShootField);
  498.     Readln;
  499. end.
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515. unit ListUnit;
  516.  
  517. interface
  518. type
  519.     PListElem = ^TPriorityCellsList;
  520.     TPriorityCellsList = record
  521.         Coord: ShortInt;
  522.         Next: PListElem;
  523.     end;
  524.     function CreateListElem(Coord: ShortInt): PListElem;
  525.     procedure AddListElem(var Header: PListElem; Coord: ShortInt);
  526.     function ExtractElem (var Header: PListElem): PListElem;
  527.     procedure DisposeList(var Header: PListElem);
  528.     procedure InitializeList(var PriorityCellsListHeader: PListElem);
  529.  
  530.  
  531. implementation
  532. function CreateListElem(Coord: ShortInt): PListElem;
  533. var
  534.     NewElem: PListElem;
  535. begin
  536.     New(NewElem);
  537.     NewElem^.Coord := Coord;
  538.     NewElem^.Next := nil;
  539.     CreateListElem := NewElem;
  540. end;
  541.  
  542. procedure AddListElem(var Header: PListElem; Coord: ShortInt);
  543. var
  544.     Temp: PListElem;
  545. begin
  546.     Temp := Header^.Next;
  547.     Header^.Next := CreateListElem(Coord);
  548.     Header^.Next^.Next := Temp;
  549. end;
  550.  
  551. function ExtractElem (var Header: PListElem): PListElem;
  552. var
  553.     Temp: PListElem;
  554. begin
  555.     if Header^.Next <> nil then
  556.     begin
  557.         Temp := Header^.Next;
  558.         Header^.Next := Temp^.Next;
  559.         Temp^.Next := nil;
  560.     end
  561.     else
  562.         Temp := nil;
  563.     ExtractElem := Temp;
  564. end;
  565.  
  566. procedure DisposeList(var Header: PListElem);
  567. var
  568.     Prev, Curr: PListElem;
  569. begin
  570.     Curr := Header^.Next;
  571.     while Curr <> nil do
  572.     begin
  573.         Prev := Curr;
  574.         Curr := Curr^.Next;
  575.         Dispose(Prev);
  576.     end;
  577.     Header^.Next := nil;
  578. end;
  579.  
  580. procedure InitializeList(var PriorityCellsListHeader: PListElem);
  581. begin
  582.     New(PriorityCellsListHeader);
  583.     PriorityCellsListHeader^.Next := nil;
  584. end;
  585. end.
  586.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement