2018-07-17 19:12:27 +03:00
|
|
|
|
// Игра Жизнь на торе
|
2015-12-28 14:25:15 +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);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
SetWindowCaption('Игра "Жизнь"');
|
2015-05-14 22:35:07 +03:00
|
|
|
|
if (m mod mk<>0) or (n mod nk<>0) then
|
|
|
|
|
|
begin
|
2015-12-28 14:25:15 +03:00
|
|
|
|
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);
|
2015-12-28 14:25:15 +03:00
|
|
|
|
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.
|