Nadesłany przez Michał Knasiecki, 16 sierpnia 2005 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
tetris_d/Unit1.pas:
//Tetris został pobrany ze strony www.algorytm.org
//(c)2001 Michał Knasiecki
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Menus, ExtCtrls, ComCtrls, StdCtrls, Buttons;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
Gra1: TMenuItem;
Nowa1: TMenuItem;
Halloffame1: TMenuItem;
N1: TMenuItem;
Exit1: TMenuItem;
Help1: TMenuItem;
Index1: TMenuItem;
N2: TMenuItem;
About1: TMenuItem;
Pause1: TMenuItem;
Shape1: TShape;
StatusBar1: TStatusBar;
Timer1: TTimer;
PaintBox1: TPaintBox;
Bevel1: TBevel;
Label1: TLabel;
Label2: TLabel;
Panel1: TPanel;
Label3: TLabel;
Bevel2: TBevel;
Label4: TLabel;
procedure Exit1Click(Sender: TObject);
procedure About1Click(Sender: TObject);
procedure Nowa1Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure Pause1Click(Sender: TObject);
procedure Index1Click(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure FormActivate(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
procedure Halloffame1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
procedure start;
procedure add_to_best;
end;
var
Form1: TForm1;
stat:record
name:string;
level:integer;
points:integer;
time:longint;
end;
data:array[1..11]of record
name:string;
score:integer;
level:byte;
time:longint;
end;
counter:byte;
block:array[1..4,1..4]of boolean;
desk:array[0..18,1..26]of shortint;
block_ID:byte;
block_state:byte;
xpos,ypos:byte;
speed:byte;
velocity:byte;
bl:boolean;
bonus:integer;
implementation
uses Unit2, player, endgame, hall;
{$R *.DFM}
procedure quicksortR_middle(l,r: Integer);
var i,j,v,q1,q2,q3 : Integer;
q:string;
begin
i:=l; j:=r; v:=data[(l+r) div 2].score;
repeat
while (data[i].score<v) do i:=i+1;
while (v<data[j].score) do j:=j-1;
if i<=j then
begin
q1:=data[i].score; data[i].score:=data[j].score; data[j].score:=q1;
q2:=data[i].level; data[i].level:=data[j].level; data[j].level:=q2;
q3:=data[i].time; data[i].time:=data[j].time; data[j].time:=q3;
q:=data[i].name; data[i].name:=data[j].name; data[j].name:=q;
i:=i+1; j:=j-1;
end;
until i>j;
if l<j then quicksortR_middle(l,j);
if i<r then quicksortR_middle(i,r);
end;
procedure Tform1.add_to_best;
var tmp:textfile;
i:byte;
begin
data[11].name:=stat.name;
data[11].score:=stat.points+bonus;
data[11].level:=stat.level;
data[11].time:=stat.time;
quicksortR_middle(1,11);
assignfile(tmp,'Hall.dat');
rewrite(tmp);
for i:=11 downto 2 do
if data[i].name<>'Nobody' then
begin
writeln(tmp,data[i].name);
writeln(tmp,inttostr(data[i].score));
writeln(tmp,inttostr(data[i].level));
writeln(tmp,inttostr(data[i].time));
end;
closefile(tmp);
end;
procedure results;
var tmp:textfile;
i,j:byte;
s:string;
begin
if fileexists('Hall.dat') then
begin
assignfile(tmp,'Hall.dat');
reset(tmp);
i:=0;
while not eof(tmp) do
begin
inc(i);
readln(tmp,s);
data[i].name:=s;
readln(tmp,s);
data[i].score:=strtoint(s);
readln(tmp,s);
data[i].level:=strtoint(s);
readln(tmp,s);
data[i].time:=strtoint(s);
end;
closefile(tmp);
quicksortR_middle(1,i);
for j:=1 to i do
begin
form5.stringgrid1.cells[1,i-j+1]:=data[j].name;
form5.stringgrid1.cells[2,i-j+1]:=inttostr(data[j].score);
form5.stringgrid1.cells[3,i-j+1]:=inttostr(data[j].level);
form5.stringgrid1.cells[4,i-j+1]:=inttostr(data[j].time);
end;
end;
end;
procedure end_of_game;
var i,j:integer;
begin
for j:=25 downto 1 do
begin
sleep(50);
for i:=1 to 17 do
begin
form1.paintbox1.Canvas.Brush.Color:=$800ff;
form1.paintbox1.Canvas.Pen.Color:=clwhite;
form1.paintbox1.canvas.Rectangle(i*15-15,j*15-15,i*15,j*15);
end;
end;
sleep(100);
for j:=1 to 25 do
begin
sleep(50);
for i:=1 to 17 do
begin
form1.paintbox1.Canvas.Brush.Color:=$00FF8000;
form1.paintbox1.Canvas.Pen.Color:=$00FF8000;
form1.paintbox1.canvas.Rectangle(i*15-15,j*15-15,i*15,j*15);
end;
end;
form4.Label8.caption:=stat.name;
form4.Label9.caption:=inttostr(stat.level);
form4.Label10.caption:=inttostr(stat.points);
form4.Label11.caption:=inttostr(stat.time);
form4.Label12.caption:=inttostr(bonus);
form4.Label13.caption:=inttostr(stat.points+bonus);
form4.show;
end;
procedure TForm1.Exit1Click(Sender: TObject);
begin
if MessageDlg('Do You want to exit this program ?',
mtConfirmation,[mbYes, mbNo],0) = mrYes
then
application.terminate
else
end;
procedure get_block(id,state:byte);
var i,j:integer;
begin
for i:=1 to 4 do for j:=1 to 4 do block[i,j]:=false;
case id of
1:
begin
if state=1 then
begin
block[2,1]:=true;
block[2,2]:=true;
block[2,3]:=true;
block[2,4]:=true;
end;
if state=2 then
begin
block[1,2]:=true;
block[2,2]:=true;
block[3,2]:=true;
block[4,2]:=true;
end;
end;
2: begin
block[2,2]:=true;
block[3,3]:=true;
block[2,3]:=true;
block[3,2]:=true;
end;
3:
begin
if state=1 then
begin
block[2,2]:=true;
block[1,3]:=true;
block[2,3]:=true;
block[3,3]:=true;
end;
if state=2 then
begin
block[1,2]:=true;
block[1,3]:=true;
block[2,3]:=true;
block[1,4]:=true;
end;
if state=3 then
begin
block[1,2]:=true;
block[3,2]:=true;
block[2,2]:=true;
block[2,3]:=true;
end;
if state=4 then
begin
block[2,1]:=true;
block[1,2]:=true;
block[2,2]:=true;
block[2,3]:=true;
end;
end;
4:
begin
if state=1 then
begin
block[2,1]:=true;
block[2,2]:=true;
block[2,3]:=true;
block[3,3]:=true;
end;
if state=2 then
begin
block[1,3]:=true;
block[2,3]:=true;
block[3,3]:=true;
block[3,2]:=true;
end;
if state=3 then
begin
block[2,1]:=true;
block[3,1]:=true;
block[3,2]:=true;
block[3,3]:=true;
end;
if state=4 then
begin
block[1,2]:=true;
block[1,3]:=true;
block[2,2]:=true;
block[3,2]:=true;
end;
end;
5:
begin
if state=1 then
begin
block[3,1]:=true;
block[3,2]:=true;
block[3,3]:=true;
block[2,3]:=true;
end;
if state=2 then
begin
block[2,2]:=true;
block[2,3]:=true;
block[3,3]:=true;
block[4,3]:=true;
end;
if state=3 then
begin
block[2,1]:=true;
block[3,1]:=true;
block[2,2]:=true;
block[2,3]:=true;
end;
if state=4 then
begin
block[2,2]:=true;
block[3,2]:=true;
block[4,2]:=true;
block[4,3]:=true;
end;
end;
6:
begin
if state=1 then
begin
block[3,2]:=true;
block[4,2]:=true;
block[3,3]:=true;
block[2,3]:=true;
end;
if state=2 then
begin
block[2,2]:=true;
block[2,3]:=true;
block[3,3]:=true;
block[3,4]:=true;
end;
end;
7:
begin
if state=1 then
begin
block[2,2]:=true;
block[3,2]:=true;
block[3,3]:=true;
block[4,3]:=true;
end;
if state=2 then
begin
block[3,2]:=true;
block[2,3]:=true;
block[3,3]:=true;
block[2,4]:=true;
end;
end;
end;
end;
procedure refresh_desk;forward;
procedure erase(i:byte);
var x,j:byte;
begin
for j:=1 to 17 do desk[j,i]:=0;
for j:=i-1 downto 1 do
begin
sleep(5);
for x:=1 to 17 do
begin
desk[x,j+1]:=desk[x,j];
desk[x,j]:=0;
end;
end;
form1.PaintBox1.refresh;
end;
function line(x:byte):boolean;
var i:byte;
begin
result:=true;
for i:=1 to 17 do if desk[i,x]=0 then result:=false;
end;
procedure stop; forward;
procedure new_block;
var j:byte;
points:byte;
begin
repeat
block_ID:=random(7);
until (block_ID>=1)and(block_ID<=7);
block_state:=1;
get_block(block_ID,block_state);
xpos:=8;
ypos:=0;
bl:=true;
points:=0;
for j:=1 to 25 do
if line(j) then
begin
erase(j);
inc(points);
end;
case points of
1:inc(stat.points,5);
2:inc(stat.points,15);
3:inc(stat.points,40);
4:inc(stat.points,75);
end;
form1.statusbar1.Panels[2].text:='Points:'+inttostr(stat.points);
if (stat.points>=250)and(stat.level=1) then
begin
stat.level:=2;
velocity:=4;
form1.label3.Caption:='Next level: 500';
if 500-stat.time>0 then inc(bonus,500-stat.time);
end;
if (stat.points>=500)and(stat.level=2) then
begin
stat.level:=3;
velocity:=3;
form1.label3.Caption:='Next level: 800';
if 1000-stat.time>0 then inc(bonus,1000-stat.time);
end;
if (stat.points>=800)and(stat.level=3) then
begin
form1.label3.Caption:='Next level: 1500';
stat.level:=4;
velocity:=1;
if 1600-stat.time>0 then inc(bonus,1600-stat.time);
end;
if (stat.points>=1500)and(stat.level=4) then
begin
stat.level:=5;
velocity:=0;
form1.label3.Caption:='Next level:infinity';
if 2200-stat.time>0 then inc(bonus,2200-stat.time);
end;
form1.statusbar1.Panels[1].text:='Level:'+inttostr(stat.level);
for j:=1 to 17 do if desk[j,1]<>0 then
begin
end_of_game;
stop;
break;
end;
end;
procedure Dell_from_desk(x,y:byte);
var i,j:byte;
begin
form1.paintbox1.Canvas.Brush.Color:=$ff8000;
form1.paintbox1.Canvas.Pen.Color:=$ff8000;
for i:=1 to 4 do
for j:=1 to 4 do
if block[i,j]=true then
form1.paintbox1.canvas.Rectangle(i*15+x*15-30,j*15+y*15-30,i*15+x*15-15,j*15+y*15-15);
form1.paintbox1.Canvas.Brush.Color:=clred;
form1.paintbox1.Canvas.Pen.Color:=clwhite;
end;
procedure print_on_desk(x,y:byte);
var i,j:byte;
begin
form1.paintbox1.canvas.Pen.Color:=clwhite;
form1.paintbox1.canvas.Brush.Color:=clred;
for i:=1 to 4 do
for j:=1 to 4 do
if block[i,j]=true then
form1.paintbox1.canvas.Rectangle(i*15+x*15-30,j*15+y*15-30,i*15+x*15-15,j*15+y*15-15);
end;
procedure refresh_desk;
var i,j:byte;
begin
for i:=1 to 17 do for j:=1 to 25 do
if desk[i,j]<>0 then
begin
case desk[i,j]of
1:form1.paintbox1.canvas.brush.color:=clnavy;
2:form1.paintbox1.canvas.brush.color:=clblue;
3:form1.paintbox1.canvas.brush.color:=clpurple;
4:form1.paintbox1.canvas.brush.color:=clgreen;
5:form1.paintbox1.canvas.brush.color:=clteal;
6:form1.paintbox1.canvas.brush.color:=clmaroon;
7:form1.paintbox1.canvas.brush.color:=clfuchsia;
end;
form1.paintbox1.canvas.Rectangle(i*15-15,j*15-15,i*15,j*15);
end;
print_on_desk(xpos,ypos);
end;
function check(x,y,dir:byte):boolean;
var i,j:byte;
begin
result:=true;
//Down
if dir=1 then
begin
for i:=1 to 4 do
for j:=1 to 4 do
if block[i,j]=true then
if desk[i+x-1,j+y-1+1]<>0 then result:=false;
end;
//Left
if dir=2 then
begin
for i:=1 to 4 do
for j:=1 to 4 do
if block[i,j]=true then
if desk[i+x-1-1,j+y-1]<>0 then result:=false;
end;
//Left
if dir=3 then
begin
for i:=1 to 4 do
for j:=1 to 4 do
if block[i,j]=true then
if desk[i+x-1+1,j+y-1]<>0 then result:=false;
end;
end;
procedure dock_block(x,y:byte);
var i,j:integer;
begin
case block_ID of
1:form1.paintbox1.canvas.brush.color:=clnavy;
2:form1.paintbox1.canvas.brush.color:=clblue;
3:form1.paintbox1.canvas.brush.color:=clpurple;
4:form1.paintbox1.canvas.brush.color:=clgreen;
5:form1.paintbox1.canvas.brush.color:=clteal;
6:form1.paintbox1.canvas.brush.color:=clmaroon;
7:form1.paintbox1.canvas.brush.color:=clfuchsia;
end;
for i:=1 to 4 do
for j:=1 to 4 do
if block[i,j]=true then
begin
form1.paintbox1.canvas.Rectangle(i*15+x*15-30,j*15+y*15-30,i*15+x*15-15,j*15+y*15-15);
desk[i+x-1,j+y-1]:=block_ID;
end;
new_block;
end;
procedure TForm1.About1Click(Sender: TObject);
begin
aboutbox.show;
end;
procedure reset;
var i,j:byte;
begin
for i:=1 to 4 do for j:=1 to 4 do block[i,j]:=false;
for i:=1 to 17 do for j:=1 to 25 do desk[i,j]:=0;
for i:=1 to 24 do
begin
desk[0,i]:=-1;
desk[18,i]:=-1;
end;
for i:=1 to 17 do desk[i,26]:=-1;
end;
procedure stop;
begin
form1.timer1.enabled:=false;
form1.statusbar1.panels[0].text:='Game Over';
form1.statusbar1.panels[1].text:='';
form1.statusbar1.panels[2].text:='';
form1.statusbar1.panels[3].text:='';
form1.label3.visible:=false;
form1.label4.visible:=false;
reset;
form1.paintbox1.Refresh;
form1.pause1.caption:='Pause/Resume';
form1.pause1.Enabled:=false;
block_ID:=0;
end;
procedure TForm1.Nowa1Click(Sender: TObject);
begin
if timer1.enabled then
begin
timer1.enabled:=false;
if messagedlg('You are playing now '+stat.name+'. Do You want to quit this game and start New Game?',mtconfirmation,
[mbYes,mbNo],0)=mrYes then
begin
stop;
form3.show;
end
else
timer1.enabled:=true;
end
else form3.show;
end;
procedure Tform1.start;
begin
bonus:=0;
label3.visible:=true;
label3.Caption:='Next level: 250';
label4.visible:=true;
if form5.stringgrid1.cells[1,1]<>'' then label4.Caption:='Best: '+form5.stringgrid1.cells[1,1]+
' ('+form5.stringgrid1.cells[2,1]+')' else
label4.caption:='Best: nobody';
reset;
velocity:=10;
stat.name:=statusbar1.Panels[0].text;
stat.level:=1;
stat.points:=0;
stat.time:=0;
counter:=0;
pause1.enabled:=true;
pause1.caption:='Pause';
new_block;
timer1.enabled:=true;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if counter<20 then inc(counter) else
begin
counter:=0;
inc(stat.time);
statusbar1.panels[3].text:=inttostr(stat.time);
end;
if bl=true then
begin
if speed<velocity then inc(speed) else
begin
if check(xpos,ypos,1)=true
then
begin
dell_from_desk(xpos,ypos);
inc(ypos);
print_on_desk(xpos,ypos);
end else
begin
bl:=false;
dock_block(xpos,ypos);
end;
speed:=0;
end;
end;
end;
procedure TForm1.Pause1Click(Sender: TObject);
begin
timer1.enabled:=not(timer1.enabled);
if timer1.Enabled=false then
begin
statusbar1.panels[3].text:='Pause';
paintbox1.Repaint;
pause1.caption:='Resume';
label1.visible:=true;
label2.visible:=true;
end
else
begin
pause1.caption:='Pause';
label1.visible:=false;
label2.visible:=false;
paintbox1.Repaint;
end;
end;
procedure TForm1.Index1Click(Sender: TObject);
begin
Application.HelpCommand(HELP_FINDER, 0);
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var t:boolean;s:byte;
begin
if key=40 then begin
if check(xpos,ypos,1)=true
then
begin
dell_from_desk(xpos,ypos);
inc(ypos);
print_on_desk(xpos,ypos);
end else dock_block(xpos,ypos);
end;
if key=37 then begin
if check(xpos,ypos,2)=true
then
begin
dell_from_desk(xpos,ypos);
dec(xpos);
print_on_desk(xpos,ypos);
end;
end;
if key=39 then begin
if check(xpos,ypos,3)=true
then
begin
dell_from_desk(xpos,ypos);
inc(xpos);
print_on_desk(xpos,ypos);
end;
end;
if key=32 then
begin
dell_from_desk(xpos,ypos);
t:=false;
case block_ID of
1:
begin
if (block_state=1)and(t=false) then
begin
t:=true;
s:=block_state;
block_state:=2;
get_block(block_ID,block_state);
if check(xpos,ypos,1)=false then block_state:=s;
end;
if (block_state=2)and(t=false) then
begin
s:=block_state;
block_state:=1;
get_block(block_ID,block_state);
if check(xpos,ypos,1)=false then block_state:=s;
end;
end;
3,4,5:
begin
if (block_state<4)and(t=false) then
begin
t:=true;
s:=block_state;
inc(block_state);
get_block(block_ID,block_state);
if check(xpos,ypos,1)=false then block_state:=s;
end;
if (block_state=4)and(t=false) then
begin
s:=block_state;
block_state:=1;
get_block(block_ID,block_state);
if check(xpos,ypos,1)=false then block_state:=s;
end;
end;
6,7:
begin
if (block_state=1)and(t=false) then
begin
t:=true;
s:=block_state;
block_state:=2;
get_block(block_ID,block_state);
if check(xpos,ypos,1)=false then block_state:=s;
end;
if (block_state=2)and(t=false) then
begin
s:=block_state;
block_state:=1;
get_block(block_ID,block_state);
if check(xpos,ypos,1)=false then block_state:=s;
end;
end;
end;
get_block(block_id,block_state);
print_on_desk(xpos,ypos);
end;
end;
procedure TForm1.FormActivate(Sender: TObject);
var i:integer;
begin
randomize;
for i:=1 to 11 do
begin
data[i].name:='Nobody';
data[i].score:=0;
data[i].level:=0;
data[i].time:=0;
end;
results;
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
refresh_desk;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
end_of_game;
end;
procedure TForm1.Halloffame1Click(Sender: TObject);
begin
form5.show;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if MessageDlg('Do You want to exit this program ?',
mtConfirmation,[mbYes, mbNo],0) = mrYes
then
Action := caFree
else
Action := caNone;
end;
end.

