I have a two-dimensional array of type Byte[,] containing the state of the cell:

 type field = array[1..10,1..10] of Byte; 

The cell field can have the values:

 cc_none = 0; // Пусто cc_fill = 1; // Есть корабль 

I need to randomly generate ships:

  • 4 single deck;
  • 3 double decks;
  • 2 three-decks;
  • 1 four-deck.

(it is desirable that they could be not only straight, but also a corner or something else).

It is necessary to place according to the rules of the sea battle: the ships cannot be near, and diagonally too.

  • And what did you try? What are the difficulties in random placement? - VladD
  • The difficulty is that the ships do not stand together and diagonally! - delphikettle
  • one
    It's easy, you just have to start. Houses is the source - renegator
  • as an option, if you are reluctant to write the generation logic, you can write preset patterns in advance, for example, 10-15 pieces and just choose a random one from the patterns) - IVsevolod
  • one
    and taking into account that it is possible to turn clockwise and mirror it (and these will be the correct locations), this immediately increases the number of variants by 8 times. - KoVadim

2 answers 2

The easiest way to do a matrix of "employment" - that is, after you put the ship, in a separate matrix enclosing points around it.

When installing a new ship, check that the ship itself does not fall into these fields. If hits, then turn. If you still do not - put in another place.

You can simply select points for a random access (there are not so many ships relative to the field), you just need to start from the longest ship.

For a start, it is better to set up straight ships, and then upgrade for bent ones.

In principle, in the online you can search for the source, but there will be no pleasure. Try it.

UPD -----------------

A more interesting task is to think over AI for a gaming computer (if you write computer-man battles). Shoot just randomly - not too interesting. To pry is bad (the computer should not take into account when working the matrix of the ships of a person - only the one that he “shot”).

Of course, you need to optimize the code, encapsulate class fields, etc. but ultimately something like this should turn out ...

ps left you the opportunity to register 4-sleeper, it will be easier to understand the principle of the code ... and randomly select the first cell of the ships :) (I really did not want to stop)

the general principle is quite simple ... we check the selected cell (by its type) ... if it is free, if free (for example, set 2), then we look at all the cells around it, if among them there is also "free", then we change the type of cells with "free" (cGood) to "ship" (cShip), and cells around it to "busy" (cBad).

 program Project1; {$APPTYPE CONSOLE} uses SysUtils; type //тип ячейки TKind = (cBad,cShip,cGood); TCellGrid = class; //ячейка поля TCell = class fKind:TKind; fVert:integer; fHorz:integer; public constructor Create(vert:integer;horz:integer); end; //поле TCellGrid = class fACells:array[0..9,0..9]of TCell; public function isGood(cell:TCell;ind:integer):boolean; function NewShip(ind:integer):boolean; function SetShip(cell:TCell;ind:integer):boolean; procedure toFile(fileName:string); constructor Create; end; { TCell } constructor TCell.Create; begin fKind:=cGood; fVert:=vert; fHorz:=horz; end; { TCellGrid } constructor TCellGrid.Create; var i,j:integer; begin for i:=0to 9do for j:=0to 9do begin fACells[i,j]:= TCell.Create(i,j); end; end; function TCellGrid.isGood(cell:TCell;ind:integer): boolean; var i,j:integer; bln:boolean; begin Result:=true; case ind of 1:for i:=cell.fVert-1 to cell.fVert+1 do for j:= cell.fHorz-1 to cell.fHorz+1 do if(i>-1)and(j>-1)and(i<10)and(j<10)then if(TKind(fACells[i,j].fKind)=cShip)then Result:=false; 2:if isGood(cell,1) then begin for i:=cell.fVert-1 to cell.fVert+1 do for j:= cell.fHorz-1 to cell.fHorz+1 do if(i>-1)and(j>-1)and(i<10)and(j<10)then if(i<>cell.fVert) or (j<>cell.fHorz)then if isGood(fACells[i,j],1)then begin Result:=true; if(bln)then begin bln:= not bln; isGood(fACells[i,j],2); end; end; end else Result:=false; 3:begin bln:=true; Result:= isGood(cell,2); end; end; end; function TCellGrid.NewShip(ind:integer): boolean; var i,j:integer; begin Result:=false; case ind of 1:for i:=0 to 9 do for j:=0 to 9 do if isGood(fACells[i,j],1) then begin SetShip(fACells[i,j],1); Result:=true; Exit; end; 2:for i:=0 to 9 do if not Result then for j:=0 to 9 do if not Result then if isGood(fACells[i,j],2) then begin SetShip(fACells[i,j],2); Result:=true; end; 3:for i:=0 to 9 do if not Result then for j:=0 to 9 do if not Result then if isGood(fACells[i,j],3) then begin SetShip(fACells[i,j],3); Result:=true; end; end; end; var grid: TCellGrid; i:integer; function TCellGrid.SetShip(cell:TCell;ind: integer): boolean; var i,j:integer; a:array of TCell; k:boolean; n:integer; procedure changeCells(i:integer;j:integer); begin if(i>-1)and(j>-1)and(i<10)and(j<10)then if(i<>cell.fVert) or (j<>cell.fHorz)then if isGood(fACells[i,j],1)then a[n]:=fACells[i,j]; end; function change(cell:TCell):boolean; var i,j:integer; i1:integer; bln:boolean; begin k:=boolean(random(2)); if k then begin for i:=cell.fVert to cell.fVert do for j:= cell.fHorz-1 to cell.fHorz+1 do if(i>-1)and(j>-1)and(i<10)and(j<10)then if(i<>cell.fVert) or (j<>cell.fHorz)then begin bln:=true; for i1:=0to n-1do if (fACells[i,j]=a[i1])then bln:=false; if bln then if isGood(fACells[i,j],1)then begin a[n]:=fACells[i,j]; inc(n); if (ind=3)and(n=3) then Result:=true; if (ind=3)and(n=2) then change(fACells[i,j]); end; end; end else begin for i:=cell.fVert-1 to cell.fVert+1 do for j:= cell.fHorz to cell.fHorz do if(i>-1)and(j>-1)and(i<10)and(j<10)then if(i<>cell.fVert) or (j<>cell.fHorz)then begin bln:=true; for i1:=0to n-1do if (fACells[i,j]=a[i1])then bln:=false; if bln then if isGood(fACells[i,j],1)then begin a[n]:=fACells[i,j]; inc(n); if (ind=3)and(n=3)then Result:=true; if (ind=3)and(n=2) then change(fACells[i,j]); end; end; end; end; begin Result:=true; n:=0; case ind of 1:begin for i:=cell.fVert-1 to cell.fVert+1 do for j:= cell.fHorz-1 to cell.fHorz+1 do if(i>-1)and(j>-1)and(i<10)and(j<10)then if(cell.fVert=i)and(cell.fHorz=j)then TKind(grid.fACells[i,j].fKind):=cShip else if TKind(grid.fACells[i,j].fKind)<> cShip then TKind(grid.fACells[i,j].fKind):=cBad; end; 2:begin SetLength(a,sizeOf(cell)*2); k:=boolean(random(2)); if isGood(cell,1) then begin a[n]:=cell; inc(n); if k then for i:=cell.fVert to cell.fVert do for j:= cell.fHorz-1 to cell.fHorz+1 do changeCells(i,j) else for i:=cell.fVert-1 to cell.fVert+1 do for j:= cell.fHorz to cell.fHorz do changeCells(i,j) end; for i:=0to 1 do SetShip(a[i],1); end; 3:begin SetLength(a,sizeOf(cell)*3); if isGood(cell,1) then begin a[n]:=cell; inc(n); change(cell); end; for i:=0to 2 do SetShip(a[i],1); end; end; end; procedure TCellGrid.toFile(fileName: string); var f:TextFile;i,j:integer; begin AssignFile(f,fileName); Rewrite(f); for i:=0to 9do for j:=0to 9do case integer(grid.fACells[i,j].fKind) of 0: Writeln(inttostr(i):3, inttostr(j):3, 'bad':6); 1: Writeln(inttostr(i):3, inttostr(j):3, 'ship':6); 2: Writeln(inttostr(i):3, inttostr(j):3, 'good':6); end; CloseFile(f); end; begin grid:= TCellGrid.Create; for i:=0to 3 do grid.NewShip(1); for i:=0to 2do grid.NewShip(2); for i:=0to 1do grid.NewShip(3); grid.toFile('t.txt'); readln; end. 
  • 3
    Still ship, not sheep. - VladD
  • absolutely agree with you) - teilon
  • 2
    horrible bed sheet. don't write like that. nested loops in cases are beyond good and evil. the whole algorithm consists in adding two matrices and checking the result. - Yura Ivanov