Iata cel de-al patrulea (si ultimul) articol din seria dedicata programarii jocului Tetris. (Daca nu ai citit ultimele trei articole, atunci te invit s-o faci.)
Fata de data trecuta, am mai adaugat doar eliminarea liniilor completate si rotatia pieselor. Nu pare chiar mult, dar rezultatul e un joc de Tetris minimalist dar la fel de “datator de dependenta”. 🙂
Start la distractie:
// +--------+
// | TETRIS |
// +--------+
// CONSTANTELE:
// Piesele:
var piesa1 = Matrice(4, 4);
piesa1[0][0] = 0; piesa1[0][1] = 0; piesa1[0][2] = 1; piesa1[0][3] = 0;
piesa1[1][0] = 0; piesa1[1][1] = 0; piesa1[1][2] = 1; piesa1[1][3] = 0;
piesa1[2][0] = 0; piesa1[2][1] = 0; piesa1[2][2] = 1; piesa1[2][3] = 0;
piesa1[3][0] = 0; piesa1[3][1] = 0; piesa1[3][2] = 1; piesa1[3][3] = 0;
var piesa2 = Matrice(4, 4);
piesa2[0][0] = 0; piesa2[0][1] = 0; piesa2[0][2] = 0; piesa2[0][3] = 0;
piesa2[1][0] = 0; piesa2[1][1] = 1; piesa2[1][2] = 0; piesa2[1][3] = 0;
piesa2[2][0] = 0; piesa2[2][1] = 1; piesa2[2][2] = 1; piesa2[2][3] = 0;
piesa2[3][0] = 0; piesa2[3][1] = 1; piesa2[3][2] = 0; piesa2[3][3] = 0;
var piesa3 = Matrice(4, 4);
piesa3[0][0] = 0; piesa3[0][1] = 0; piesa3[0][2] = 0; piesa3[0][3] = 0;
piesa3[1][0] = 0; piesa3[1][1] = 0; piesa3[1][2] = 0; piesa3[1][3] = 0;
piesa3[2][0] = 0; piesa3[2][1] = 1; piesa3[2][2] = 1; piesa3[2][3] = 0;
piesa3[3][0] = 0; piesa3[3][1] = 1; piesa3[3][2] = 1; piesa3[3][3] = 0;
var piesa4 = Matrice(4, 4);
piesa4[0][0] = 0; piesa4[0][1] = 0; piesa4[0][2] = 0; piesa4[0][3] = 0;
piesa4[1][0] = 0; piesa4[1][1] = 1; piesa4[1][2] = 0; piesa4[1][3] = 0;
piesa4[2][0] = 0; piesa4[2][1] = 1; piesa4[2][2] = 0; piesa4[2][3] = 0;
piesa4[3][0] = 0; piesa4[3][1] = 1; piesa4[3][2] = 1; piesa4[3][3] = 0;
var piesa5 = Matrice(4, 4);
piesa5[0][0] = 0; piesa5[0][1] = 0; piesa5[0][2] = 0; piesa5[0][3] = 0;
piesa5[1][0] = 0; piesa5[1][1] = 1; piesa5[1][2] = 0; piesa5[1][3] = 0;
piesa5[2][0] = 0; piesa5[2][1] = 1; piesa5[2][2] = 1; piesa5[2][3] = 0;
piesa5[3][0] = 0; piesa5[3][1] = 0; piesa5[3][2] = 1; piesa5[3][3] = 0;
// Starile jocului:
var JOC_OPRIT = 0;
var GENEREAZA_PIESA = 1;
var COBOARA_PIESA = 2;
var JOC_TERMINAT = -1;
// VARIABILELE:
// Variabile ajutatoare:
var l;
var c;
// Tabla de joc:
var t = Matrice(17, 16);
l = 0;
while (l<17)
{
c = 0;
while (c<16)
{
if ( (c<3) || (c>12) || (l>13) )
{
t[l][c] = -1; // unde nu se poate gasi piesa
}
else
{
t[l][c] = 0;
}
c = c+1;
}
l = l+1;
}
// Piesa curenta:
var p = Matrice(4, 4);
p[0][0] = 0; p[0][1] = 0; p[0][2] = 0; p[0][3] = 0;
p[1][0] = 0; p[1][1] = 0; p[1][2] = 0; p[1][3] = 0;
p[2][0] = 0; p[2][1] = 0; p[2][2] = 0; p[2][3] = 0;
p[3][0] = 0; p[3][1] = 0; p[3][2] = 0; p[3][3] = 0;
// Coordonatele piesei:
var pl;
var pc;
// Starea jocului:
var stare_joc;
// FUNCTIILE
function FunctieTaste(ev)
{
var tasta = TastaApasata(ev);
if (tasta == 'a') // deplasare la stanga
{
if (stare_joc == COBOARA_PIESA)
{
LaStanga();
}
}
else if (tasta == 'd') // deplasare la dreapta
{
if (stare_joc == COBOARA_PIESA)
{
LaDreapta();
}
}
else if (tasta == 'o') // rotatie la stanga
{
if (stare_joc == COBOARA_PIESA)
{
RotesteStanga();
}
}
else if (tasta == 'p') //rotatie la dreapta
{
if (stare_joc == COBOARA_PIESA)
{
RotesteDreapta();
}
}
else if (tasta == 'z') // pauza/repornire
{
if (stare_joc == COBOARA_PIESA)
{
Aprinde(0, 0, ALBASTRU);
stare_joc = JOC_OPRIT;
}
else if (stare_joc == JOC_OPRIT)
{
Aprinde(0, 0, ALB);
stare_joc = COBOARA_PIESA;
}
}
}
function FunctieDesenare()
{
if (TimpScurs(1000/4) == 1)
{
if (stare_joc == JOC_TERMINAT)
{
// Incheie programul:
Aprinde(0, 0, ROSU);
AscultaTaste();
StartAnimatie();
}
else if (stare_joc == JOC_OPRIT)
{
// Nu face nimic.
}
else if (stare_joc == COBOARA_PIESA)
{
CoboaraPiesa();
AfiseazaTabla();
}
else if (stare_joc == GENEREAZA_PIESA)
{
GenereazaPiesa();
}
}
Animeaza(FunctieDesenare);
}
function GenereazaPiesa()
{
// Alege aleator o piesa:
var aleator = NrAleator(4);
// Si pune-o in matricea "piesa":
var i = 0;
var j;
while (i<4)
{
j = 0;
while (j<4)
{
if (aleator == 0) p[i][j] = piesa1[i][j];
else if (aleator == 1) p[i][j] = piesa2[i][j];
else if (aleator == 2) p[i][j] = piesa3[i][j];
else if (aleator == 3) p[i][j] = piesa4[i][j];
else p[i][j] = piesa5[i][j];
j = j+1;
}
i = i+1;
}
// Si apoi pozitioneaz-o sus de tot:
pl = 0;
pc = 6;
// Pune piesa "piesa" pe tabla "t" la pozitia ("pl", "pc"):
var ok = PunePiesa();
// Daca se suprapune, termina jocul:
if (ok == 0)
stare_joc = JOC_TERMINAT;
else
stare_joc = COBOARA_PIESA;
}
function PunePiesa()
{
// Intai verifica daca sunt suprapuneri:
var ok = 1;
var i = 0;
var j;
while (i<4)
{
j = 0;
while (j<4)
{
if ( (p[i][j] != 0) && (t[pl+i][pc+j] != 0) )
{
ok = 0;
}
j = j+1;
}
i = i+1;
}
// Daca sunt suprapuneri, returneaza ca e eroare -- 0:
if (ok == 0)
{
return 0;
}
// Altfel, pune piesa si returneaza ca e OK -- 1:
i = 0;
while (i<4)
{
j = 0;
while (j<4)
{
if (p[i][j] != 0)
{
t[pl+i][pc+j] = p[i][j];
}
j = j+1;
}
i = i+1;
}
return 1;
}
function RidicaPiesa()
{
var i = 0;
var j;
while (i<4)
{
j = 0;
while (j<4)
{
if (p[i][j] != 0)
{
t[pl+i][pc+j] = 0;
}
j = j+1;
}
i = i+1;
}
}
function CoboaraPiesa()
{
// Ridica piesa:
RidicaPiesa();
// Coboar-o cu o linie:
pl = pl+1;
var ok = PunePiesa();
// Daca se suprapune sau iese in afara:
if (ok == 0)
{
// Pune-o la loc:
pl = pl-1;
PunePiesa();
// Vezi daca s-au completat linii:
VerificaLinii();
// Si genereaza o noua piesa:
stare_joc = GENEREAZA_PIESA;
}
}
function AfiseazaTabla()
{
var y = 1;
var x;
while (y <= 10)
{
x = 1;
while (x <= 10)
{
AprindeNrCul(x, y, t[14-y][2+x]);
x = x+1;
}
y = y+1;
}
}
function LaStanga()
{
// Ridica piesa:
RidicaPiesa();
// Mut-o la stanga cu o coloana:
pc = pc-1;
var ok = PunePiesa();
// Daca se suprapune sau iese in afara:
if (ok == 0)
{
// Pune-o la loc:
pc = pc+1;
PunePiesa();
}
else
{
AfiseazaTabla();
}
}
function LaDreapta()
{
// Ridica piesa:
RidicaPiesa();
// Mut-o la dreapta cu o coloana:
pc = pc+1;
var ok = PunePiesa();
// Daca se suprapune sau iese in afara:
if (ok == 0)
{
// Pune-o la loc:
pc = pc-1;
PunePiesa();
}
else
{
AfiseazaTabla();
}
}
function VerificaLinii()
{
var nr_linie = PrimaLiniePlina();
while (nr_linie != 0)
{
EvaporaLinie(nr_linie);
nr_linie = PrimaLiniePlina();
}
}
function PrimaLiniePlina()
{
var plina;
var x;
var y = 1;
while (y <= 10)
{
plina = 1;
x = 1;
while (x <= 10)
{
if ( t[4+(10-y)][2+x] == 0 )
{
plina = 0;
}
x = x+1;
}
if (plina == 1)
{
return y;
}
y = y+1;
}
return 0;
}
function EvaporaLinie(nr_linie)
{
// Copiaza mai jos cu o linie toate liniile
// de la nr_linie in sus:
var y;
var x = 1;
while (x <= 10)
{
y = nr_linie;
while (y <= 9)
{
t[4+(10-y)][2+x] = t[4+(10-(y+1))][2+x];
y = y+1;
}
x = x+1;
}
// Si completeaza zerouri pe linia de sus de tot:
x = 1;
while (x <= 10)
{
t[4][2+x] = 0;
x = x+1;
}
}
function RotesteStanga()
{
// Construieste o noua piesa pornind de la
// piesa p si rotind-o cu 90 de grade la stanga:
var piesa_noua = Matrice(4, 4);
var l = 0;
var c;
while (l < 4)
{
c = 0;
while (c < 4)
{
piesa_noua[3-c][l] = p[l][c];
c = c+1;
}
l = l+1;
}
// Schimba piesa curenta cu noua piesa rotita:
RidicaPiesa();
var piesa_salv = p;
p = piesa_noua;
var ok = PunePiesa();
if (ok == 0)
{
p = piesa_salv;
PunePiesa();
}
else
{
AfiseazaTabla();
}
}
function RotesteDreapta()
{
// Construieste o noua piesa pornind de la
// piesa p si rotind-o cu 90 de grade la dreapta:
var piesa_noua = Matrice(4, 4);
var l = 0;
var c;
while (l < 4)
{
c = 0;
while (c < 4)
{
piesa_noua[c][3-l] = p[l][c];
c = c+1;
}
l = l+1;
}
// Schimba piesa curenta cu noua piesa rotita:
RidicaPiesa();
var piesa_salv = p;
p = piesa_noua;
var ok = PunePiesa();
if (ok == 0)
{
p = piesa_salv;
PunePiesa();
}
else
{
AfiseazaTabla();
}
}
// PROGRAMUL:
Aprinde(0, 0, ALB);
stare_joc = GENEREAZA_PIESA;
AscultaTaste(FunctieTaste);
StartAnimatie(FunctieDesenare);
In caz ca nu mai tii minte ce e de facut, incepe prin a apasa butonul “Reseteaza…” si apoi butonul “Executa…”. (In caseta de text din stanga se va incarca automat codul sursa al jocului nostru de Tetris (la care poti face modificari dupa bunul plac), iar in ecranul 10×10 din dreapta vei putea sa te joci — mutand piesele la stanga/dreapta cu tastele ‘a’/’d’, rotindu-le spre stanga/dreapta cu ‘o’/’p’ si punand pauza cu tasta ‘z’.)
Wow, a fost ceva de lucru, nu-i asa? Te-ai fi asteptat ca programul pentru un “simplu” joc de Tetris sa se apropie de 500 de linii de cod?
In orice caz, nu asta e ideea cu care as vrea sa ramai dupa aceasta serie de patru articole. Ci mi-as dori sa ramai cu ideea ca oricat de complicat ar fi lucrul pe care il ai de facut, n-ai de ce sa te descurajezi atata timp cat abordezi problema pas cu pas, de la simplu la complex. 🙂
Acum lasa-mi, te rog, un comentariu in care sa-mi spui care ti s-a parut a fi aspectul cel mai dificil in realizarea jocului de Tetris pe care l-am prezentat aici.
Alatura-te celor peste 2000 de oameni din armata noastra de creiere cu muschi si vei primi testul care iti va spune daca ai sau nu minte de programator:
Cu drag,
Florin