Los
simuladores de carreras son un género clásico, habituales desde el mismo
comienzo de los juegos informáticos. En este caso se trata de un pequeño
programa en Turbo Pascal con gráficos generados en modo texto.
Ejemplo de ejecución del programa (carrera hasta la meta) |
El
trazado de la carretera y la posición de los enemigos son aleatorios y el
movimiento del coche se produce sólo cuando se escoge un movimiento. Puedes
permanecer parado, pero entonces el tiempo transcurre en tu contra. El programa
calcula las colisiones con los laterales de la carretera o con los coches
rivales. Asimismo se cronometra el tiempo invertido en llegar hasta la meta,
comparando las marcas de cada partida y guardando el récord.
Ejemplo de ejecución del programa (carreras con colisiones) |
Sencillo
pero entretenido.
El
código del programa completo en lenguaje Turbo PASCAL es el siguiente:
PROGRAM carreras;
{por TDM para Arqui-2.blogspot.com.es (2009)}
USES DOS, CRT;
{Librerias: CRT para CLRSCR, GOTOXY, KEYPRESSED, etc.
DOS
para GETTIME, computo de tiempo para el record.}
CONST
margen_hz = 35;
margen_vt = 15; {Los margenes horizontal y
vertical
marcan el punto de origen
0,0 en pantalla a
partir del cual se
generan los distintos elementos:
carretera, coche,
enemigos, meta y colisiones.}
l_crrt
= 30; {Longitud en tramos de la carretera.}
TYPE
VECTOR =
ARRAY [1..4] OF SHORTINT;
{Se define un tipo de
variable ARRAY de cuatro elementos
para almacenar los valores
de posición de los tramos de
carretera visibles en
pantalla.}
VAR
t_inicial, t_final, t_record :LONGINT;
{RECORD}
tramo :VECTOR; {CARRETERA}
pos_coche, mov :SHORTINT; {COCHE}
p_enemigo_x, p_enemigo_y :SHORTINT; {ENEMIGO}
hay_enemigo :BOOLEAN;
meta, choque, seguir :BOOLEAN; {CONCLUSION/NUEVA PARTIDA}
paso :BYTE;
FUNCTION
tiempo_reloj :LONGINT;
{La función obtiene el tiempo de reloj
en un instante en
horas : minutos : segundos :
centesimas
y convierte el tiempo total en
centésimas para operar con
un único valor.}
VAR
h, m, s, cs
:WORD;
t
:LONGINT;
BEGIN
GETTIME(h,
m, s, cs);
t:= h*60+m;
t:=t*60+s; t:=t*100+cs;
tiempo_reloj:=
t;
END;
FUNCTION tiempo_de_ejecucion (t1_, t2_
:LONGINT):LONGINT;
BEGIN
IF t2_ >= t1_ THEN tiempo_de_ejecucion:=
t2_-t1_
ELSE tiempo_de_ejecucion:= t2_ - t1_ +
24*60*60*100
END;
PROCEDURE presentacion;
VAR i, j :INTEGER;
BEGIN
CLRSCR;
GOTOXY(margen_hz-14, margen_vt-4);
WRITELN('BIENVENIDO AL JUEGO DE LOS AUTOS LOCOS');
GOTOXY(margen_hz-14, margen_vt-2);
WRITELN(' Pulse "a" para mover
a la izquierda');
GOTOXY(margen_hz-14, margen_vt-1);
WRITELN(' Pulse "d" para mover
a la derecha');
GOTOXY(margen_hz-14, margen_vt ); WRITELN('
Pulse "enter" para ir adelante');
GOTOXY(margen_hz-14, margen_vt+2); WRITELN('
(Pulse una tecla para EMPEZAR)');
i:= 1; j:=1;
REPEAT
DELAY(100);
GOTOXY(margen_hz -i, margen_vt -6); WRITELN(' * ');
GOTOXY(margen_hz +i, margen_vt -7); WRITELN(' # ');
GOTOXY(margen_hz+18, margen_vt+2);
i:=
i+j;
IF
ABS(i)=8 THEN j:= -j;
UNTIL
keypressed;
END;
PROCEDURE iniciar_variables (VAR paso_ :BYTE; VAR
meta_, choque_ :BOOLEAN; VAR tramo_:VECTOR;
VAR p_ch,
p_enmg_x, p_enmg_y :SHORTINT; VAR hay_enmg_ :BOOLEAN);
VAR i:INTEGER;
BEGIN
paso_ := 1; {La partida se inicia en el tramo 1 de
carretera.}
meta_
:= FALSE;
choque_:= FALSE; {Se inician las variables booleanas de llegada
y colisión en FALSE.}
{CARRETERA:}
FOR i:= 1 TO 2
DO
tramo_[i]:= 0;
{El primer y segundo
tramos se inician con valor 0, el resto se
genera
aleatoriamente. Los valores serán negativos cuando
los tramos se situen
a la izquierda del origen y positivos
cuando se situen a la
derecha.}
RANDOMIZE;
FOR i:= 3 TO 4
DO
tramo_[i]:= tramo_[i-1] + RANDOM(3) - 1;
{COCHE:}
p_ch:= RANDOM(3) +1; {La variable toma valores iniciales entre
1 y 3
|* |
--> pos_coche = 1
| * | --> pos_coche = 2
| *|
--> pos_coche = 3
Valores menores
que 0 ó superiores a 3 indicarán colisión.}
{ENEMIGO:}
hay_enmg_ := TRUE;
p_enmg_x:=
RANDOM(3) +1;
p_enmg_y:= 4; {La variable X de posición del
enemigo determina,
como en el
coche, su ubicación en el ancho de la carretera.
Varía siempre
entre 1 y 3.
|# |
-->p_enemigo_x = 1
| # | -->p_enemigo_x = 2
| #|
-->p_enemigo_x = 3
La variable Y
de posición determina el tramo de carretera
en que se encuentra, inicialmente, el
tramo 4.}
END;
PROCEDURE
pintar_carretera (tramo_:VECTOR);
VAR i :INTEGER;
BEGIN
FOR i:= 1 TO 4 DO
BEGIN
GOTOXY(margen_hz + tramo_[i],
margen_vt -i +1);
WRITE('| |');
END;
END;
PROCEDURE pintar_coche (tramo_:VECTOR; p_ch
:SHORTINT);
BEGIN
GOTOXY(margen_hz + tramo_[1] + p_ch, margen_vt);
WRITE('*');
END;
PROCEDURE
pintar_enemigo(tramo_:VECTOR; p_enmg_x, p_enmg_y :SHORTINT);
BEGIN
GOTOXY(margen_hz + p_enmg_x +
tramo_[p_enmg_y], margen_vt - p_enmg_y +1);
WRITE('#');
END;
PROCEDURE
pintar_meta (pos_meta_ :BYTE; tramo_:VECTOR);
BEGIN
GOTOXY(margen_hz + tramo_[pos_meta_] +1,
margen_vt - pos_meta_ +1);
WRITE('---');
END;
PROCEDURE
pintar_pantalla (paso_:BYTE; tramo_:VECTOR; p_ch, p_enmg_x, p_enmg_y :SHORTINT;
hay_enmg_ :BOOLEAN);
{El procedimiento limpia la pantalla
y dibuja con los valores
actualizados de las variables cada
uno de los elementos en sus
posiciones.}
BEGIN
CLRSCR;
pintar_carretera(tramo_);
IF paso_ > l_crrt-4 THEN
pintar_meta(l_crrt-paso_+1, tramo_);
pintar_coche(tramo_, p_ch);
IF hay_enmg_ THEN pintar_enemigo(tramo_,
p_enmg_x, p_enmg_y);
END;
PROCEDURE solicitar_movimiento (VAR mov_ :SHORTINT);
{El procedimiento obtiene las instrucciones
del usuario
necesarias para el movimiento del
coche. Aguarda hasta
una entrada válida de teclado:
a, A --> Movimiento a la izquierda --> mov =
-1
d, D --> Movimiento a la derecha --> mov = +1
enter --> Movimiento hacia
delante --> mov = 0 }
CONST
enter =#13; {Se introduce el valor ASCII de la tecla
"enter".}
VAR mv :CHAR;
BEGIN
REPEAT
GOTOXY(margen_hz - 3, margen_vt +1);
WRITE('¿Movimiento? ');
mv:=READKEY;
UNTIL mv
IN[enter, 'a', 'A', 'd', 'D'];
CASE mv OF
enter : mov_ := 0;
'a',
'A': mov_ := -1;
'd',
'D': mov_ := 1;
END;
END;
PROCEDURE
actualizar_variables (VAR paso_:BYTE; VAR meta_ :BOOLEAN; VAR tramo_:VECTOR;
VAR mov_, p_ch,
p_enmg_x, p_enmg_y :SHORTINT; VAR hay_enmg_ :BOOLEAN);
{El procedimiento determina los nuevos
valores de cada variable
en función de la entrada de
movimiento dada por el usuario.}
VAR i:INTEGER;
BEGIN
paso_ := paso_+1;
IF paso_ = l_crrt THEN meta_ := TRUE;
{COCHE:}
p_ch:= p_ch + mov_ + tramo_[1] -
tramo_[2]; {Al avanzar, el coche toma su
nueva posición en función
de la posición anterior, del movimiento introducido por
el usuario y la diferencia de posición entre el tramo de
partida, [1], y el tramo de llegada, [2].}
{CARRETERA:}
FOR i:= 1 TO 3
DO
tramo_[i]:= tramo_[i+1]; {Al avanzar, cada tramo toma el valor del
tramo inmediatamente
posterior. El tramo[4], o nuevo tramo de carretera, se genera
aleatoriamente.}
tramo_[4]:= tramo_[3] + RANDOM(3) -1;
{ENEMIGO:}
IF (p_enmg_y = 1) AND (paso_ <=
l_crrt-4) THEN
BEGIN {Se genera un nuevo
enemigo cuando el anterior ha llegado al
al
primer tramo y aún no ha aparecido la meta en pantalla.}
p_enmg_x:= RANDOM(3)
+1;
p_enmg_y:= 4;
END
ELSE p_enmg_y:= p_enmg_y -1;
{Si no se genera un nuevo enemigo entonces se mueve el actual
{Si no se genera un nuevo enemigo entonces se mueve el actual
al
tramo inmediatamente inferior.}
IF p_enmg_y <= 0 THEN hay_enmg_ :=
FALSE;
{Si la coordenada Y del enemigo toma un valor inferior a 0, entonces:
{Si la coordenada Y del enemigo toma un valor inferior a 0, entonces:
Ya no se generan nuevos enemigos y el enemigo actual ha salido de
pantalla,
por tanto no hay enemigos.}
END;
PROCEDURE comprobar_colisiones (choque_ :BOOLEAN;
p_ch, p_enmg_x, p_enmg_y :SHORTINT);
BEGIN
{COLISION
CON CARRETERA:}
IF (p_ch
< 1) OR (p_ch > 3) THEN choque:= TRUE;
{COLISION
CON ENEMIGO:}
IF (p_ch =
p_enmg_x) AND (p_enmg_y = 1) THEN choque:= TRUE;
END;
PROCEDURE pintar_colision (tramo_:VECTOR; p_ch
:SHORTINT);
BEGIN
GOTOXY(margen_hz + tramo_[1] + p_ch, margen_vt);
WRITE('X');
END;
PROCEDURE seguir_jugando (VAR seguir_ :BOOLEAN);
VAR sgr :CHAR;
BEGIN
REPEAT
GOTOXY(margen_hz - 3, margen_vt +1);
WRITE('¿Jugar otra partida? (S/N): ');
sgr:=READKEY;
UNTIL sgr
IN['s', 'S', 'n', 'N'];
CASE sgr OF
's',
'S': seguir_:= TRUE;
'n',
'N': seguir_:= FALSE;
END;
END;
PROCEDURE
escribir_record (t_ini_, t_fin_ :LONGINT; VAR t_rec_ :LONGINT);
BEGIN
GOTOXY(margen_hz -3, margen_vt +2);
WRITELN('Tiempo empleado: ');
GOTOXY(margen_hz -3, margen_vt +3);
WRITE(tiempo_de_ejecucion(t_ini_, t_fin_)
DIV 100, ' segundos ');
WRITE(tiempo_de_ejecucion(t_ini_, t_fin_)
MOD 100, ' centesimas');
IF tiempo_de_ejecucion(t_ini_, t_fin_)
< t_rec_ THEN
BEGIN
t_rec_:= tiempo_de_ejecucion(t_ini_,
t_fin_);
GOTOXY(margen_hz -3,
margen_vt +4);
WRITELN('¡NUEVO RECORD!')
END
ELSE
BEGIN
GOTOXY(margen_hz -3, margen_vt +4);
WRITELN('El record es: ');
GOTOXY(margen_hz -3, margen_vt
+5);
WRITE(t_rec_ DIV 100, ' segundos
');
WRITE(t_rec_ MOD 100, '
centesimas');
END;
END;
BEGIN {INICIO DEL PROGRAMA PRINCIPAL}
t_record:= 2147483647;
{Limite maximo del tipo LONGINT, cualquier tiempo logrado en la primera
{Limite maximo del tipo LONGINT, cualquier tiempo logrado en la primera
partida mejorará
el record.}
presentacion;
REPEAT {BUCLE DE
PARTIDA}
t_inicial := tiempo_reloj; {Toma de
tiempo del momento de inicio de la partida.}
iniciar_variables(paso, meta, choque,
tramo, pos_coche, p_enemigo_x, p_enemigo_y, hay_enemigo);
REPEAT
{BUCLE DE MOVIMIENTO} {Se repetirá hasta llegada a meta o colisión del
coche.}
pintar_pantalla(paso, tramo,
pos_coche, p_enemigo_x, p_enemigo_y, hay_enemigo);
solicitar_movimiento (mov);
actualizar_variables (paso, meta,
tramo, mov, pos_coche, p_enemigo_x, p_enemigo_y, hay_enemigo);
comprobar_colisiones (choque,
pos_coche, p_enemigo_x, p_enemigo_y);
UNTIL meta OR choque;
t_final:= tiempo_reloj; {Toma de tiempo
del momento de finalización de la partida.}
pintar_pantalla(paso, tramo, pos_coche,
p_enemigo_x, p_enemigo_y, hay_enemigo);
IF choque THEN pintar_colision (tramo,
pos_coche)
ELSE escribir_record(t_inicial, t_final,
t_record);
seguir_jugando(seguir);
UNTIL seguir =
FALSE;
END.
hola quieria saber si me podias ayudar en un juego de maraton
ResponderEliminar