pascalabcnet/TestSuite/CompilationSamples/NewLife.pas

350 lines
7.5 KiB
ObjectPascal
Raw Permalink Normal View History

2018-07-17 19:12:27 +03:00
// Игра Жизнь на торе
// Оптимизация хешированием по равномерной сетке
2015-05-14 22:35:07 +03:00
uses Utils,GraphABC;
const
w =3;
w1=1;
k=20;
m=300;
n=220;
graphW=0;
mk=m div k;//15;
nk=n div k;//10;
mm=m+1;
nn=n+1;
x0=1;
y0=21;
ClearColor=clBlack;
FillColor=clLimeGreen;
2018-07-17 19:12:27 +03:00
var
FiledColor := RGB(0,40,0);
FiledColor2 := RGB(0,70,0);{}
2015-05-14 22:35:07 +03:00
{ClearColor=clWhite;
FillColor=clBlack;
FiledColor=clLightGray;
FiledColor2=clGray;{}
var
//a,b,sosedia,sosedib: array [0..nn,0..mm] of byte;
a,b,sosedia,sosedib:array of array of byte;
//obnovA,obnovB: array [1..nk,1..mk] of boolean;
obnovA,obnovB: array of array of boolean;
count: integer;
obn: boolean;
mil,mil1: integer;
hn,hm: integer;
procedure AssignArray(var arr:array of array of boolean; n,m:integer);
begin
SetLength(arr,n);
for var i:=0 to n-1 do
SetLength(arr[i],m);
end;
procedure AssignArray(var arr:array of array of byte; n,m:integer);
begin
SetLength(arr,n);
for var i:=0 to n-1 do
SetLength(arr[i],m);
end;
procedure CopyArray(arr1,arr2:array of array of byte);
begin
for var i:=0 to arr1.Length-1 do
arr1[i].CopyTo(arr2[i],0);
end;
procedure CopyArray(arr1,arr2:array of array of boolean);
begin
for var i:=0 to arr1.Length-1 do
arr1[i].CopyTo(arr2[i],0);
end;
procedure DrawCell(i,j: integer);
begin
if BrushColor<>FillColor then begin
SetBrushColor(FillColor);
SetPenColor(FillColor);
end;
FillRect(x0+(j-1)*w,y0+(i-1)*w,x0+j*w-w1,y0+i*w-w1);
end;
procedure ClearCell(i,j: integer);
begin
if BrushColor<>clearColor then begin
SetBrushColor(clearColor);
SetPenColor(clearColor);
end;
FillRect(x0+(j-1)*w,y0+(i-1)*w,x0+j*w-w1,y0+i*w-w1);
end;
procedure DrawConfiguration;
begin
for var i:=1 to n do
for var j:=1 to m do
if a[i,j]=1 then
DrawCell(i,j)
end;
procedure DrawField;
begin
SetBrushColor(ClearColor);
FillRectangle(x0,y0,x0+m*w,y0+n*w);
SetPenColor(FiledColor);
for var i:=0 to m do
Line(x0+i*w-1,y0,x0+i*w-1,y0+n*w);
for var i:=0 to n do
Line(x0,y0+i*w-1,x0+m*w,y0+i*w-1);
SetPenColor(FiledColor2);
for var i:=0 to m div hm do
Line(x0+i*w*hm-1,y0,x0+i*w*hm-1,y0+n*w);
for var i:=0 to n div hn do
Line(x0,y0+i*w*hn-1,x0+m*w,y0+i*w*hn-1);
end;
procedure IncSosedi(i,j: integer);
begin
var i1 := i=1 ? n : i-1;
var i2 := i=n ? 1 : i+1;
var j1 := j=1 ? m : j-1;
var j2 := j=m ? 1 : j+1;
SosediB[i1,j1] += 1;
SosediB[i1,j] += 1;
SosediB[i1,j2] += 1;
SosediB[i,j1] += 1;
SosediB[i,j2] += 1;
SosediB[i2,j1] += 1;
SosediB[i2,j] += 1;
SosediB[i2,j2] += 1;
end;
procedure DecSosedi(i,j: integer);
begin
var i1 := i=1 ? n : i-1;
var i2 := i=n ? 1 : i+1;
var j1 := j=1 ? m : j-1;
var j2 := j=m ? 1 : j+1;
SosediB[i1,j1] -= 1;
SosediB[i1,j] -= 1;
SosediB[i1,j2] -= 1;
SosediB[i,j1] -= 1;
SosediB[i,j2] -= 1;
SosediB[i2,j1] -= 1;
SosediB[i2,j] -= 1;
SosediB[i2,j2] -= 1;
end;
procedure SetCell(i,j: integer);
begin
if b[i,j]=0 then
begin
b[i,j]:=1;
obn:=true;
IncSosedi(i,j);
end;
count += 1;
end;
procedure UnSetCell(i,j: integer);
begin
if b[i,j]=1 then
begin
b[i,j]:=0;
obn:=true;
DecSosedi(i,j);
end;
count -= 1;
end;
type
ColonyType = (Big, LD, RD, LU, RU);
procedure AddColonyType(xc,yc:integer; ctype:ColonyType);
begin
case ctype of
ColonyType.Big:begin
SetCell(xc,yc);
SetCell(xc,yc+1);
SetCell(xc,yc+2);
SetCell(xc-1,yc+2);
SetCell(xc+1,yc+1);
end;
ColonyType.LD:begin
SetCell(xc,yc-1);
SetCell(xc,yc);
SetCell(xc,yc+1);
SetCell(xc-1,yc-1);
SetCell(xc-2,yc);
end;
end;
//SosediA:=SosediB;
CopyArray(sosedib,sosedia);
for var ik:=1 to nk do
for var jk:=1 to mk do
obnovB[ik,jk]:=true;
//obnovA:=obnovB;
CopyArray(obnovB,obnovA);
end;
procedure Init;
begin
Count:=0;
AddColonyType(n div 2,m div 2, ColonyType.Big);
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);
count -= 1;
end;
3: if b[i,j]=0 then
begin
b[i,j]:=1;
obn:=true;
IncSosedi(i,j);
DrawCell(i,j);
count += 1;
end;
end;
end;
procedure NextGen;
var
i,j,ik1,jk1,ik2,jk2,ifirst,jfirst,ilast,jlast: integer;
l,r,u,d,lu,ld,ru,rd: boolean;
begin
for var ik:=1 to nk do
begin
for var jk:=1 to mk do
begin
obn := false;
ifirst := (ik-1)*hn+1;
ilast := ik*hn;
jfirst := (jk-1)*hm+1;
jlast := jk*hm;
if obnovA[ik,jk] then
begin
for i:=ifirst to ilast do
for j:=jfirst to jlast do
OnlyCase(i,j);
end
else
begin
ik1 := ik=1 ? nk : ik-1;
ik2 := ik=nk ? 1 : ik+1;
jk1 := jk=1 ? mk : jk-1;
jk2 := jk=mk ? 1 : 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;
procedure MouseDown(x,y,b:integer);
begin
case b of
1:AddColonyType((y-y0)div w,(x-x0)div w, ColonyType.LD);
end;
end;
begin
SetConsoleIO;
AssignArray(obnovA,nk+1,mk+1);
AssignArray(obnovB,nk+1,mk+1);
AssignArray(a,nn+1,mm+1);
AssignArray(b,nn+1,mm+1);
AssignArray(sosedia,nn+1,mm+1);
AssignArray(sosedib,nn+1,mm+1);
SetWindowCaption('Игра "Жизнь"');
2015-05-14 22:35:07 +03:00
if (m mod mk<>0) or (n mod nk<>0) then
begin
writeln('Размер кластера не согласован с размером поля. Программа завершена');
2015-05-14 22:35:07 +03:00
exit
end;
hm:=m div mk;
hn:=n div nk;
SetBrushColor(ClearColor);
SetWindowSize(x0+m*w,y0+n*w+graphW);
CenterWindow;
ClearWindow(ClearColor);
SetFontName('Courier New');
SetFontSize(10);
Init;
DrawField;
DrawConfiguration;
OnMouseDown:=MouseDown;
mil:=Milliseconds;
var gen:=0;
DrawInBuffer := false;
while true do begin
gen+=1;
//SosediA:=SosediB;
//obnovA:=obnovB;
CopyArray(sosedib,sosedia);
CopyArray(obnovB,obnovA);
NextGen;
if gen mod 10 = 0 then begin
DrawInBuffer := True;
SetBrushColor(ClearColor);
SetFontColor(FillColor);
TextOut(25, 0,'Поколение: '+IntToStr(gen));
TextOut(765,0,'Жителей: '+IntToStr(count)+' ');
2015-05-14 22:35:07 +03:00
if gen mod 1000 = 0 then begin
mil1:=Milliseconds;
writeln(gen,' ',(mil1-mil)/1000);
mil:=mil1;
end;
DrawInBuffer := false;
end;
end;
end.