Programación en Pascal/Ejemplo
De Wikilibros, la colección de libros de texto de contenido libre.
El siguiente ejemplo puede ejecutarse tanto en Linux como en Windows (en modo MS-DOS).
Para ejecutarlo en Linux, es necesario instalar la librería svgalib, y ejecutar el programa con permisos de superusuario:
$ sudo ./Serpiente2
Aunque el ejemplo es antiguo y utiliza librerías desfasadas, es un buen ejemplo de lo que se puede hacer con poquito código en Pascal. En otras partes de este curso iremos poniendo ejemplos más modernos usando Lazarus.
program Serpiente2; (******************************************* * Por Victor Barbero Romero - Oct. 2.001 * * vbarbero@movistar.com o @telefonica.net * * * *******************************************) {v2.0e} uses crt, Graph; const DLY = 2; {Cambiar este valor para hacer el juego más lento.} type Puntuaci = record name : string[15]; punt : integer; end; var MaxPtosPar, PtosPar, PtosTot : integer; PosX, PosY, BolaX, BolaY, IncrmX, IncrmY : shortint; Lab, c, NumArray, Rtraso : shortint; datmem, mejora, basta, Sonido, definal : boolean; ColaX, ColaY : array[1..40] of shortint; Laberinto : array[1..1850] of boolean; marca : array[1..6] of Puntuaci; P : file of Puntuaci; TipoMov : char; procedure IniciaVideo; var Driver, Modo : smallint; begin Driver := VGA; { Modo := VGAHi; } Modo := G640x480x256; { Cambiado debido a problemas con algunas resoluciones gráficas } InitGraph(Driver,Modo,'.BGI'); end; procedure AbreVentana(PX, PY, Anch, Alto : integer; Titulo : string); var contaX, differ, alter, tlitb : integer; tapavent : array[1..12] of integer; begin alter := PX + Anch - (Anch div 5); tlitb := alter + 20; differ := PX - PY; tapavent[1] := PX; tapavent[2] := PY; tapavent[3] := PX; tapavent[4] := PY+Alto; tapavent[5] := PX+Anch; tapavent[6] := PY+Alto; tapavent[7] := PX+Anch; tapavent[8] := PY+(Anch div 5); tapavent[9] := alter; tapavent[10] := PY; tapavent[11] := PX; tapavent[12] := PY; setcolor(0); setfillstyle(1,0); fillpoly(6,tapavent); setcolor(7); line(PX-1, PY, alter, PY); line(PX-1, PY-1, alter, PY-1); for contaX := PX to PX+Anch do begin if contaX-differ < PY+Alto+1 then begin putpixel(PX, contaX-differ, 7); putpixel(PX-1, contaX-differ, 7); end; if contaX-differ < PY+Alto+1 then begin putpixel(alter, contaX-differ, 7); putpixel(alter+1, contaX-differ, 7); end; if alter < PX+Anch then alter := alter + 1; putpixel(contaX, PY+Alto, 7); putpixel(contaX-1, PY+Alto+1, 7); if contaX < tlitb then putpixel(contaX, PY+20, 7); Delay(4*DLY); end; putpixel(PX+Anch+1, PY+Alto+1, 7); putpixel(PX+Anch, PY+Alto+1, 7); setfillstyle(9,8); floodfill(PX+(Anch div 2), PY+3, 7); setfillstyle(10,8); floodfill(PX+(Anch div 2), PY+25, 7); setcolor(15); outtextxy(PX+12, PY+7, Titulo); end; procedure CreaFichero; begin {$I-} rewrite(P); {$I+} for c := 1 to 6 do begin marca[c].name := '- - -'; marca[c].punt := 0; seek(P,c); write(P,marca[c]); end; end; procedure ManejaFichero; var report : integer; begin assign(P,'srp2pnt.fps'); {$I-} reset(P); {$I+} report := IOResult; if report <> 0 then begin CreaFichero; end else begin for c := 1 to 6 do begin seek(P,c); read(P, marca[c]); end; end; close(P); datmem := true; end; procedure GrabaPunts; var reprt : integer; begin assign(P,'srp2pnt.fps'); {$I-} reset(P); {$I+} reprt := IOResult; if reprt <> 0 then begin CreaFichero; end else begin for c := 1 to 6 do begin seek(P,c); write(P, marca[c]); end; end; close(P); end; procedure MuestraPunts; var puntos : string[5]; begin AbreVentana(150,140,300,250,'Mejores puntuaciones'); if datmem = false then ManejaFichero; setcolor(7); outtextxy(175,185,'PUNTOS'); outtextxy(300,185,'NOMBRE'); line(160,198, 420,198); line(236,180, 236,380); setfillstyle(1,0); setcolor(0); for c := 1 to 6 do begin bar(165,175+(30*c), 225,190+(30*c)); bar(250,175+(30*c), 410,190+(30*c)); str(marca[c].punt, puntos); setcolor(11); outtextxy(175,180+(30*c), puntos); setcolor(9); outtextxy(260,180+(30*c), marca[c].name); end; readkey; end; procedure OrdenaPunts; {Utiliza el Algoritmo Bubble Short} var d : shortint; puntcambio : integer; namecambio : string[15]; begin for c:= 1 to 6 do begin for d := c+1 to 6 do begin if marca[d].punt > marca[c].punt then begin puntcambio := marca[c].punt; marca[c].punt := marca[d].punt; marca[d].punt := puntcambio; namecambio := marca[c].name; marca[c].name := marca[d].name; marca[d].name := namecambio; end; end; end; end; procedure CompruebaMejora; var Nombre : string[15]; begin if datmem = false then begin ManejaFichero; end; for c:= 1 to 6 do begin if PtosTot > marca[c].punt then mejora := true; end; if mejora then begin AbreVentana(140,150,250,110,'Enhorabuena!'); setcolor(7); outtextxy(159,193,'Ha superado un record!'); if Sonido then begin Sound(293); Delay(193*DLY); NoSound; Delay(27*DLY); Sound(293); Delay(110*DLY); NoSound; Sound(293); Delay(110*DLY); Sound(440); Delay(330*DLY); Sound(293); Delay(110*DLY); Sound(440); Delay(440*DLY); NoSound; end; outtextxy(160,208,'Introduzca su nombre:'); setfillstyle(1,0); setcolor(0); bar(160,223, 320,237); textcolor(9); gotoxy(22,15); readln(Nombre); marca[6].punt := PtosTot; marca[6].name := Nombre; OrdenaPunts; GrabaPunts; end; MuestraPunts; end; procedure CamSonido; var SonSim : string[1]; begin SonSim := #14; if Sonido then begin setcolor(0); outtextxy(585,5,SonSim); Sonido := false; end else begin setcolor(2); outtextxy(585,5,SonSim); Sonido := true; end; end; procedure FinJuego; begin cleardevice; AbreVentana(175,130,275,150,'FIN'); setcolor(14); outtextxy(235,185,'S E R P I E N T E'); setcolor(7); outtextxy(192,240,'Victor Barbero - Octubre 2.001'); Delay(2000*DLY); basta := true; definal := true; end; procedure CambiaNivel; var Nivel : shortint; c : char; nvl : string[1]; procedure PintaCuad(num,tipo : shortint); begin if tipo = 1 then setfillstyle(1,9); if tipo = 0 then setfillstyle(4,9); str(num,nvl); bar(210+(30*num),210, 230+(30*num),230); if tipo = 1 then begin setcolor(11); outtextxy(215+(30*num), 220, nvl); end; end; procedure TeclaDerecha; begin if Nivel < 5 then begin PintaCuad(Nivel+1,1); Nivel := Nivel + 1; end; c := 'A'; end; procedure TeclaIzquierda; begin if Nivel > 1 then begin PintaCuad(Nivel,0); Nivel := Nivel - 1; end; c := 'A'; end; begin AbreVentana(195,150,240,110,'Nivel'); setcolor(7); outtextxy(240,190,'Mayor dificultad'); outtextxy(375,190,#26); outtextxy(260,240,#27); outtextxy(350,240,#26); setcolor(1); rectangle(239,209, 261,231); rectangle(238,208, 262,232); rectangle(269,209, 291,231); rectangle(268,208, 292,232); rectangle(299,209, 321,231); rectangle(298,208, 322,232); rectangle(329,209, 351,231); rectangle(328,208, 352,232); rectangle(359,209, 381,231); rectangle(358,208, 382,232); PintaCuad(1,1); PintaCuad(2,1); PintaCuad(3,1); PintaCuad(4,0); PintaCuad(5,0); Nivel := 3; repeat if Keypressed then c := readkey; case c of #75 : TeclaIzquierda; #77 : TeclaDerecha; end; until c=#13; case Nivel of 1 : begin MaxPtosPar := 9+Lab; Rtraso := 100; end; 2 : begin MaxPtosPar := 14+Lab; Rtraso := 85; end; 3 : begin MaxPtosPar := 19+Lab; Rtraso := 75; end; 4 : begin MaxPtosPar := 24+Lab; Rtraso := 65; end; 5 : begin MaxPtosPar := 39+Lab; Rtraso := 53; end; end; setfillstyle(1,0); bar(568,4, 578,13); setcolor(15); str(Nivel,nvl); outtextxy(569,5,nvl); end; procedure PintaLabs; var x, y : shortint; begin setfillstyle(11,6); for x := 1 to 50 do begin for y := 1 to 37 do begin if Laberinto[((y-1)*50)+x] = true then begin setcolor(12); rectangle(8+(x*12), 6+(y*12), 20+(x*12), 18+(y*12)); setcolor(6); rectangle(9+(x*12), 7+(y*12), 19+(x*12), 17+(y*12)); floodfill(14+(x*12), 12+(y*12), 6); end; end; end; end; procedure EligeLaberinto; var cn : char; procedure BorraLabAnter; var P : integer; begin for P := 1 to 1850 do begin Laberinto[P] := false; end; end; procedure Lab2; var P : integer; begin for P := 601 to 626 do begin Laberinto[P] := true; end; for P := 1224 to 1250 do begin Laberinto[P] := true; end; for P := 438 to 450 do begin Laberinto[P] := true; end; for P := 1451 to 1463 do begin Laberinto[P] := true; end; end; procedure Lab3; var P : integer; begin P := 260; while P < 1610 do begin P := P + 50; Laberinto[P] := true; Laberinto[P+31] := true; end; for P := 901 to 911 do begin Laberinto[P] := true; end; for P := 990 to 1000 do begin Laberinto[P] := true; end; end; procedure Lab4; var P : integer; begin P := 20; while P < 756 do begin case P of 265 :; 216 :; 167 :; else Laberinto[P] := true; end; P := P + 49; end; Laberinto[19] := true; Laberinto[18] := true; Laberinto[751] := true; Laberinto[754] := true; Laberinto[752] := true; Laberinto[753] := true; P := 1683; while P > 1028 do begin Laberinto[P] := true; P := P - 49; end; Laberinto[68] := true; Laberinto[1046] := true; Laberinto[1050] := true; Laberinto[1047] := true; Laberinto[1048] := true; Laberinto[1049] := true; P := 525; while P < 1000 do begin Laberinto[P] := true; Laberinto[P+245] := true; P := P + 51; end; for P := 1501 to 1513 do begin Laberinto[P] := true; end; end; procedure TAbajo; begin if Lab < 4 then begin setcolor(11); setfillstyle(1,11); bar(225,135+(20*(Lab+1)), 230,140+(20*(Lab+1))); bar(383,135+(20*(Lab+1)), 388,140+(20*(Lab+1))); cn := 'A'; Lab := Lab + 1; end; end; procedure TArriba; begin if Lab > 1 then begin setcolor(0); setfillstyle(1,0); bar(225,135+(20*Lab), 230,140+(20*Lab)); bar(383,135+(20*Lab), 388,140+(20*Lab)); cn := 'A'; Lab := Lab - 1; end; end; begin AbreVentana(215,120,190,114,'Laberinto'); setcolor(9); line(222,149, 232,149); line(221,149, 221,166); line(222,166, 232,166); line(391,149 ,381,149); line(392,149, 392,166); line(381,166, 391,166); line(222,169, 232,169); line(221,169, 221,186); line(222,186, 232,186); line(391,169 ,381,169); line(392,169, 392,186); line(381,186, 391,186); line(222,189, 232,189); line(221,189, 221,206); line(222,206, 232,206); line(391,189 ,381,189); line(392,189, 392,206); line(381,206, 391,206); line(222,209, 232,209); line(221,209, 221,226); line(222,226, 232,226); line(391,209 ,381,209); line(392,209, 392,226); line(381,226, 391,226); setfillstyle(1,0); setcolor(7); Lab := 1; bar(223,150, 390,165); outtextxy(260,155,'Sin laberinto'); bar(223,170, 390,185); outtextxy(260,175,'Laberinto 1'); bar(223,190, 390,205); outtextxy(260,195,'Laberinto 2'); bar(223,210, 390,225); outtextxy(260,215,'Laberinto 3'); outtextxy(395,165,#24); outtextxy(395,204,#25); setcolor(11); setfillstyle(1,11); bar(225,155, 230,160); bar(383,155, 388,160); repeat if Keypressed then cn := readkey; case cn of #72 : TArriba; #80 : TAbajo; end; until cn=#13; BorraLabAnter; case Lab of 2 : Lab2; 3 : Lab3; 4 : Lab4; end; end; procedure BorraMenu; begin setfillstyle(1,0); floodfill(320, 240, 12); setfillstyle(1,10); bar(14+(BolaX*12)-2, 12+(BolaY*12)-2, 14+(BolaX*12)+2, 12+(BolaY*12)+2); if definal = false then PintaLabs; setcolor(14); end; procedure Presentacion; begin cleardevice; AbreVentana(130,100,380,190,'Bienvenido!'); setcolor(14); outtextxy(180,170,'S E R P I E N T E'); setcolor(7); outtextxy(379,170,'v2.0'); outtextxy(180,220,'Presione ESC durante el juego'); outtextxy(235,240,'para entrar en el men£'); outtextxy(155,268,'Pulse cualquier tecla para continuar'); readkey; end; procedure Menu; var c : char; begin AbreVentana(180,125,250,180,'MENU'); setcolor(7); outtextxy(200,180, '1.- Cambiar el nivel.'); case Sonido of true : outtextxy(200,200, '2.- Desactivar sonido.'); false : outtextxy(200,200, '2.- Activar sonido.'); end; outtextxy(200,220, '3.- Volver al juego.'); outtextxy(200,240, '4.- Salir del juego.'); outtextxy(200,260, '5.- Ver las puntuaciones.'); repeat if Keypressed then c := readkey; until ((c > #48) and (c < #54)); case c of #49 : CambiaNivel; #50 : CamSonido; #52 : begin CompruebaMejora; FinJuego; end; #53 : MuestraPunts; end; BorraMenu; end; procedure IniciaCampo; begin cleardevice; setcolor(12); rectangle(20,17,620,462); rectangle(19,18,621,463); rectangle(410,2,600,15); setfillstyle(6,4); floodfill(320,10,12); setcolor(7); outtextxy(415,5,'Puntos:'); outtextxy(520,5,'Nivel:'); for c := 1 to 30 do begin ColaX[c] := 0; ColaY[c] := 0; end; setcolor(14); rectangle(106,68, 114,76); ColaX[3] := 8; ColaY[3] := 5; rectangle(118,68, 126,76); ColaX[2] := 9; ColaY[2] := 5; rectangle(130,68, 138,76); ColaX[1] := 10; ColaY[1] := 5; IncrmX := 1; IncrmY := 0; PosX := 11; PosY := 5; NumArray := 3; BolaX := 15; BolaY := 15; TipoMov := 'D'; basta := false; PtosTot := 0; PtosPar := 0; mejora := false; end; procedure PintaCabeza; begin setcolor(9); rectangle(10+(PosX*12), 8+(PosY*12), 18+(PosX*12), 16+(PosY*12)); setcolor(14); rectangle(10+(ColaX[1]*12), 8+(ColaY[1]*12), 18+(ColaX[1]*12), 16+(ColaY[1]*12)); end; procedure BorraCola; begin setcolor(0); rectangle(10+(ColaX[NumArray-1]*12), 8+(ColaY[NumArray-1]*12), 18+(ColaX[NumArray-1]*12), 16+(ColaY[NumArray-1]*12)); for c := NumArray downto 1 do begin ColaX[c] := ColaX[c-1]; ColaY[c] := ColaY[c-1]; end; ColaX[1] := PosX; ColaY[1] := PosY; end; procedure DetectaColision; procedure AvisoChoque; var t : char; begin AbreVentana(200,140,250,100,'GAME OVER'); setcolor(7); outtextxy(215,190,'Se ha chocado!!'); if Sonido then begin Sound(367); Delay(200*DLY); Sound(352); Delay(200*DLY); Sound(330); Delay(200*DLY); Sound(313); Delay(455*DLY); NoSound; end; outtextxy(215,210,'¨Desea jugar otra vez [S/N]?'); repeat if Keypressed then begin t := readkey; t := upcase(t); end; until (t='S') or (t='N'); CompruebaMejora; if t = 'N' then begin FinJuego; end; if t = 'S' then basta := true; end; var Num : shortint; begin if ((PosX<1) or (PosX>50) or (PosY<1) or (PosY>37)) then begin setcolor(12); circle(14+(ColaX[1]*12), 12+(ColaY[1]*12), 5); AvisoChoque; end; Num := NumArray; repeat if ((ColaX[Num] = PosX) and (ColaY[Num] = PosY)) then begin setcolor(12); circle(14+(PosX*12), 12+(PosY*12), 5); AvisoChoque; break; end; Num := Num - 1; until Num<3; if Laberinto[((PosY-1)*50)+PosX] = true then begin setcolor(12); circle(14+(ColaX[1]*12), 12+(ColaY[1]*12),5); AvisoChoque; end; end; procedure PintaComida; var NA : string[6]; begin setfillstyle(1,0); bar(478,4, 510,12); bar(14+(BolaX*12)-2, 12+(BolaY*12)-2, 14+(BolaX*12)+2, 12+(BolaY*12)+2); PtosTot := PtosPar + PtosTot; PtosPar := MaxPtosPar; str(PtosTot, NA); setcolor(15); outtextxy(479,5,NA); setfillstyle(1,10); repeat BolaX := random(49)+1; BolaY := random(36)+1; until Laberinto[((BolaY-1)*50)+BolaX] = false; bar(14+(BolaX*12)-2, 12+(BolaY*12)-2, 14+(BolaX*12)+2, 12+(BolaY*12)+2); if NumArray < 30 then NumArray := NumArray + 1; if NumArray > 30 then Rtraso := Rtraso - 1; if Sonido then begin Sound(1056); Delay(15*DLY); Sound(938); Delay(15*DLY); Sound(734); Delay(15*DLY); Sound(528); Delay(15*DLY); NoSound; end; end; procedure LeeTecla; procedure TeclaArriba; begin if TipoMov <> 'B' then begin IncrmX := 0; IncrmY := -1; TipoMov := 'A' end else begin if Sonido then begin Sound(83); Delay(10*DLY); NoSound; end; end; if PtosPar > 0 then PtosPar := PtosPar - 1; end; procedure TeclaIzquierda; begin if TipoMov <> 'D' then begin IncrmX := -1; IncrmY := 0; TipoMov := 'I' end else begin if Sonido then begin Sound(83); Delay(10*DLY); NoSound; end; end; if PtosPar > 0 then PtosPar := PtosPar - 1; end; procedure TeclaDerecha; begin if TipoMov <> 'I' then begin IncrmX := 1; IncrmY := 0; TipoMov := 'D' end else begin if Sonido then begin Sound(83); Delay(10*DLY); NoSound; end; end; if PtosPar > 0 then PtosPar := PtosPar - 1; end; procedure TeclaAbajo; begin if TipoMov <> 'A' then begin IncrmX := 0; IncrmY := 1; TipoMov := 'B' end else begin if Sonido then begin Sound(83); Delay(10*DLY); NoSound; end; end; if PtosPar > 0 then PtosPar := PtosPar - 1; end; var t : char; begin if Keypressed then begin t := readkey; case t of #72 : TeclaArriba; #75 : TeclaIzquierda; #77 : TeclaDerecha; #80 : TeclaAbajo; #27 : Menu; end; end; end; procedure Juego; begin PintaCabeza; if (BolaX = PosX) and (BolaY = PosY) then begin PintaComida; end; LeeTecla; BorraCola; PosX := PosX + IncrmX; PosY := PosY + IncrmY; DetectaColision; LeeTecla; Delay(Rtraso*DLY); end; begin clrscr; randomize; IniciaVideo; Presentacion; repeat IniciaCampo; EligeLaberinto; CambiaNivel; BorraMenu; PintaComida; repeat Juego; until basta; until definal; closegraph; end.