pascalabcnet/TestSamples/CompilationSamples/Life.pas
Бондарев Иван e6e67c193c initial commit
2015-05-14 21:35:07 +02:00

325 lines
6.5 KiB
ObjectPascal

// Èãðà Æèçíü íà òîðå
// Îïòèìèçàöèÿ õåøèðîâàíèåì ïî ðàâíîìåðíîé ñåòêå
//#apptype console
uses Utils,GraphABC;
const
w=4;
w1=1;
m=300;
n=220;
x0=2;
y0=20;
mm=301;
nn=221;
mk=15;
nk=10;
var
a,b,sosedia,sosedib: array [0..nn,0..mm] of integer;
obnovA,obnovB: array [1..nk,1..mk] of boolean;
count: integer;
obn: boolean;
gen,mil,mil1: integer;
hn,hm: integer;
procedure DrawCell(i,j: integer);
begin
SetBrushColor(clBlack);
SetPenColor(clBlack);
FillRect(x0+(j-1)*w,y0+(i-1)*w,x0+j*w-w1,y0+i*w-w1);
end;
procedure ClearCell(i,j: integer);
begin
SetBrushColor(clWhite);
SetPenColor(clWhite);
FillRect(x0+(j-1)*w,y0+(i-1)*w,x0+j*w-w1,y0+i*w-w1);
end;
procedure DrawConfiguration;
var i,j,bb: integer;
begin
for i:=1 to n do
for j:=1 to m do
begin
bb:=b[i,j];
if a[i,j]<>bb then
if bb=1 then DrawCell(i,j)
else ClearCell(i,j);
end;
end;
procedure DrawConfigurationFull;
var i,j,bb: integer;
begin
for i:=1 to n do
for j:=1 to m do
begin
bb:=b[i,j];
if bb=1 then DrawCell(i,j)
else ClearCell(i,j);
end;
end;
procedure DrawField;
var i: integer;
begin
SetPenColor(clLightGray);
for i:=0 to m do
begin
if i mod hm = 0 then
SetPenColor(clGray)
else SetPenColor(clLightGray);
Line(x0+i*w-1,y0,x0+i*w-1,y0+n*w);
end;
for i:=0 to n do
begin
if i mod hn = 0 then
SetPenColor(clGray)
else SetPenColor(clLightGray);
Line(x0,y0+i*w-1,x0+m*w,y0+i*w-1);
end;
end;
procedure IncSosedi(i,j: integer);
var i1,i2,j1,j2: integer;
begin
if i=1 then i1:=n else i1:=i-1;
if i=n then i2:=1 else i2:=i+1;
if j=1 then j1:=m else j1:=j-1;
if j=m then j2:=1 else j2:=j+1;
Inc(SosediB[i1,j1]);
Inc(SosediB[i1,j]);
Inc(SosediB[i1,j2]);
Inc(SosediB[i,j1]);
Inc(SosediB[i,j2]);
Inc(SosediB[i2,j1]);
Inc(SosediB[i2,j]);
Inc(SosediB[i2,j2]);
end;
procedure DecSosedi(i,j: integer);
var i1,i2,j1,j2: integer;
begin
if i=1 then i1:=n else i1:=i-1;
if i=n then i2:=1 else i2:=i+1;
if j=1 then j1:=m else j1:=j-1;
if j=m then j2:=1 else j2:=j+1;
Dec(SosediB[i1,j1]);
Dec(SosediB[i1,j]);
Dec(SosediB[i1,j2]);
Dec(SosediB[i,j1]);
Dec(SosediB[i,j2]);
Dec(SosediB[i2,j1]);
Dec(SosediB[i2,j]);
Dec(SosediB[i2,j2]);
end;
procedure SetCell(i,j: integer);
begin
if b[i,j]=0 then
begin
b[i,j]:=1;
obn:=true;
IncSosedi(i,j);
end;
Inc(count);
end;
procedure UnSetCell(i,j: integer);
begin
if b[i,j]=1 then
begin
b[i,j]:=0;
obn:=true;
DecSosedi(i,j);
end;
Dec(count);
end;
procedure Init;
var i,j,ik,jk,xc,yc: integer;
begin
xc:=n div 2;
yc:=m div 2;
// xc:=1;
// yc:=1;
for i:=0 to n+1 do
for j:=0 to m+1 do
b[i,j]:=0;
a:=b;
sosedib:=b;
Count:=0;
SetCell(xc,yc);
SetCell(xc,yc+1);
SetCell(xc,yc+2);
SetCell(xc-1,yc+2);
SetCell(xc+1,yc+1);
SosediA:=SosediB;
for ik:=1 to nk do
for jk:=1 to mk do
obnovB[ik,jk]:=true;
obnovA:=obnovB;
end;
procedure OnlyCase(i,j: integer);
begin
case SosediA[i,j] of
0..1,4..9:
if b[i,j]=1 then
begin
b[i,j]:=0;
obn:=true;
DecSosedi(i,j);
ClearCell(i,j);
Dec(count);
end;
3: if b[i,j]=0 then
begin
b[i,j]:=1;
obn:=true;
IncSosedi(i,j);
DrawCell(i,j);
Inc(count);
end;
end; {case}
end;
procedure NextGen;
var
i,j,ik,jk,ik1,jk1,ik2,jk2,ifirst,jfirst,ilast,jlast: integer;
l,r,u,d,lu,ld,ru,rd: boolean;
begin
for ik:=1 to nk do
begin
for jk:=1 to mk do
begin
obn:=false;
ifirst:=(ik-1)*hn+1;
ilast:=(ik-1)*hn+hn;
jfirst:=(jk-1)*hm+1;
jlast:=(jk-1)*hm+hm;
if obnovA[ik,jk] then
begin
for i:=ifirst to ilast do
begin
for j:=jfirst to jlast do
begin
case SosediA[i,j] of
0..1,4..9: if b[i,j]=1 then
begin
b[i,j]:=0;
obn:=true;
DecSosedi(i,j);
ClearCell(i,j);
Dec(count);
end;
3: if b[i,j]=0 then
begin
b[i,j]:=1;
obn:=true;
IncSosedi(i,j);
DrawCell(i,j);
Inc(count);
end;
end; {case}
end;
end
end
else
begin
if ik=1 then ik1:=nk else ik1:=ik-1;
if ik=nk then ik2:=1 else ik2:=ik+1;
if jk=1 then jk1:=mk else jk1:=jk-1;
if jk=mk then jk2:=1 else jk2:=jk+1;
l:=obnovA[ik,jk1];
r:=obnovA[ik,jk2];
u:=obnovA[ik1,jk];
d:=obnovA[ik2,jk];
lu:=obnovA[ik1,jk1];
ld:=obnovA[ik2,jk1];
ru:=obnovA[ik1,jk2];
rd:=obnovA[ik2,jk2];
if u then
begin
i:=ifirst;
for j:=jfirst+1 to jlast-1 do
OnlyCase(i,j);
end;
if d then
begin
i:=ilast;
for j:=jfirst+1 to jlast-1 do
OnlyCase(i,j);
end;
if l then
begin
j:=jfirst;
for i:=ifirst+1 to ilast-1 do
OnlyCase(i,j);
end;
if r then
begin
j:=jlast;
for i:=ifirst+1 to ilast-1 do
OnlyCase(i,j);
end;
if u or l or lu then
OnlyCase(ifirst,jfirst);
if u or r or ru then
OnlyCase(ifirst,jlast);
if d or l or ld then
OnlyCase(ilast,jfirst);
if d or r or rd then
OnlyCase(ilast,jlast);
end;
obnovB[ik,jk]:=obn;
end;
end;
end;
begin
SetWindowCaption('Èãðà "Æèçíü"');
if (m mod mk<>0) or (n mod nk<>0) then
begin
writeln('Ðàçìåð êëàñòåðà íå ñîãëàñîâàí ñ ðàçìåðîì ïîëÿ. Ïðîãðàììà çàâåðøåíà');
exit
end;
hm:=m div mk;
hn:=n div nk;
Cls;
SetWindowSize(x0+m*w,y0+n*w);
CenterWindow;
SetFontName('Arial');
SetFontSize(10);
Init;
TextOut(25,0,'Ïîêîëåíèå '+IntToStr(gen));
TextOut(765,0,'Æèòåëåé: '+IntToStr(count)+' ');
DrawField;
DrawConfiguration;
mil:=Milliseconds;
gen:=0;
while true do
begin
gen:=gen+1;
SetBrushColor(clWhite);
TextOut(25,0,'Ïîêîëåíèå: '+IntToStr(gen));
TextOut(765,0,'Æèòåëåé: '+IntToStr(count)+' ');
a:=b;
SosediA:=SosediB;
obnovA:=obnovB;
NextGen;
if gen mod 1000 = 0 then
begin
mil1:=Milliseconds;
writeln(gen,' ',(mil1-mil)/1000);
mil:=mil1;
end;
end;
end.