This repository has been archived on 2024-12-25. You can view files and clone it, but cannot push or open issues or pull requests.
OldPascalProjects/NewLife.pas
2023-06-20 21:49:58 +03:00

349 lines
7.5 KiB
ObjectPascal
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Игра Жизнь на торе
// Оптимизация хешированием по равномерной сетке
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;
FiledColor=RGB(0,40,0);
FiledColor2=RGB(0,70,0);{}
{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('Игра "Жизнь"');
if (m mod mk<>0) or (n mod nk<>0) then
begin
writeln('Размер кластера не согласован с размером поля. Программа завершена');
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)+' ');
if gen mod 1000 = 0 then begin
mil1:=Milliseconds;
writeln(gen,' ',(mil1-mil)/1000);
mil:=mil1;
end;
DrawInBuffer := false;
end;
end;
end.