El juego de la serpiente El juego de la serpiente

Transcripción

El juego de la serpiente El juego de la serpiente
E.T.S.I. Telecomunicación. Lab. Prog. 2
El juego de la serpiente
El juego de la serpiente
Laboratorio de Programación 2
(1o de Ingenierı́a de Telecomunicación)
E.T.S.I. TELECOMUNICACIÓN
El juego de la serpiente
Se quiere realizar el clásico juego de la serpiente. En este juego una serpiente se mueve por la pantalla en una
determinada dirección. El objetivo del juego es seguir moviendo la serpiente evitando que la cabeza de la serpiente
choque con algún muro o consigo misma.
La serpiente crece según va avanzando el tiempo. Al crecer se añade un nuevo anillo a la serpiente.
El movimiento de la serpiente puede ser en cuatro direcciones: arriba, abajo, izquierda o derecha. La serpiente
se sigue moviendo en una misma dirección hasta que el jugador la cambia usando el teclado.
La resolución de la práctica se divide en tres aspectos fundamentales:
La representación de la serpiente,
el control del juego: el movimiento de la serpiente, la interacción con el jugador y la comprobación del
posible choque de la cabeza de la serpiente y
la representación gráfica de la situación de la serpiente
La representación de la serpiente
La serpiente se compone de una secuencia de anillos de los que el primer anillo es la cabeza de la serpiente
y el último es la cola. Cuando la serpiente crece, se añade un anillo por la cabeza de la serpiente. Para mover
la serpiente podemos eliminar el elemento de la cola y añadirlo en la cabeza (lo veremos con más detalle en el
siguiente apartado). Los anillos centrales no tienen ningún interés especial.
La serpiente se puede, por tanto, representar con una estructura lineal en la que podamos escribir y leer de
ambos extremos. La Cola Doble cumple esos requisitos. Esta estructura de datos se comporta como la Cola vista
en clase añadiendo la posibilidad de insertar un elemento por la cabeza y de consultar el elemento del final de la
cola.
Su interfaz es el siguiente:
class ColaDoble
{
public:
struct TAnillo{ // Este es el TpElemento
// veremos su definicion un poco mas tarde
};
enum TExtremo {frente, final};
private:
struct NodoCD
{
TAnillo an;
NodoCD *sig;
};
NodoCD *cabeza;
1
E.T.S.I. Telecomunicación. Lab. Prog. 2
El juego de la serpiente
NodoCD *cola;
public:
ColaDoble();
// Crea un cola doble vacia
~ColaDoble();
// libera los recursos usados por el objeto
bool EstaVacia() const;
// devuelve true si no hay elementos en la cola, false en caso
// contrario
void Encolar(const TAnillo a, const TExtremo ext);
// agrega un nuevo elemento a la cola. El segundo parametro
// indica si se hace por el frente o por el final.
void Desencolar(const TExtremo ext);
// borra un elemento de la cola. El parametro
// indica si se hace por el frente o por el final.
// Si la cola esta vacia, no se hace nada
void Valor(TAnillo &a, const TExtremo ext) const;
// permite consultar el valor de un extremo de la cola.
// El segundo parametro indica si se hace por el frente o
// por el final. Si la cola esta vacia, el valor devuelto
// no es util.
};
Como se ve en el interfaz, se ha escogido una representación dinámica para implementar la cola doble. Tenemos
además dos punteros, uno que apunta al primer elemento (cabeza) y otro al último (cola).
La siguiente cuestión es cuál va a ser el tipo de los elementos que guardemos en la cola, el tipo que hemos
llamado TAnillo. Una posible solución es guardar en cada anillo las coordenadas (x,y) de cada anillo1 . Por tanto
el tipo anillo va a ser:
class ColaDoble
{
public:
struct TAnillo{
unsigned int x, y;
};
.....
El bucle de control del juego
En su forma más simple, un juego como el que estamos programando en esta práctica se reduce a un bucle
en el que en cada paso se hacen varias tareas:
Se comprueba si el jugador ha pulsado una tecla y se realizan las acciones que corresponden a la respuesta
a esa acción.
Se ejecutan las acciones propias de cada paso del juego. En este caso esas acciones son mover la serpiente
y comprobar si se ha producido una colisión.
Dibujar en pantalla la situación actual del juego.
1 Otra posible solución es tener las coordenadas (x,y) de la cabeza y especificar cuál es el desplazamiento de un anillo
respecto al anterior
2
E.T.S.I. Telecomunicación. Lab. Prog. 2
El juego de la serpiente
Si dejamos que la serpiente se mueva a toda la velocidad que le permite el ordenador, el jugador no tendrı́a
posibilidad de seguir la velocidad del ordenador. Para evitarlo, se reduce la velocidad de movimiento de la serpiente
haciendo que sólo se mueva una vez cada un número dado de pasos. Para lograrlo, incluimos un contador y la
serpiente se moverá cuando el contador haya llegado al tope2 .
Pulsaciones de tecla
La primera acción de nuestro bucle va a ser comprobar si se ha pulsado una tecla. Hay que averiguar si se ha
pulsado alguna tecla y, en caso afirmativo, cuál es la que se ha pulsado. Para la práctica hacen falta, al menos,
cuatro teclas, para cambiar la dirección de movimiento de la serpiente hacia arriba, abajo, izquierda y derecha,
respectivamente, y otra tecla para acabar la partida.
Colisiones
Para comprobar si ha habido una colisión que mate a la serpiente basta comprobar que la posición a la que
se va a mover la cabeza coincide con la de otra anilla de la serpiente o si corresponde al borde de la pantalla. En
ese caso, acaba la partida.
El movimiento de la serpiente
La primera forma que se nos puede ocurrir para mover la serpiente es dar una nueva posición al nodo de cabeza
según la dirección de movimiento y que cada uno de los demás anillos tome la posición que tenı́a el anterior anillo
antes del movimiento.
Una solución más simple es eliminar el anillo de la cola de la serpiente y añadir uno nuevo por la cabeza. La
posición del nuevo anillo viene dada por la posición de la cabeza actual y la dirección de movimiento.
Tanto eliminar como añadir por un extremo son operaciones disponibles en el interfaz de la cola doble.
El crecimiento de la serpiente
Para aumentar la dificultad y el interés del juego, la serpiente crece según avanza el tiempo. Cuando crece se
añade un nuevo anillo a la cabeza en la dirección en la que se está moviendo la cabeza. Si al crecer se ha producido
una colisión, ya sea con la cola o con un borde, la serpiente se muere.
El intervalo de tiempo entre cada dos estirones de la serpiente se puede hacer en función del número de
movimientos que haya hecho la serpiente, es decir, cada determinado número de movimientos crece un anillo.
Cuanto menor sea ese número, más rápido sube la dificultad del juego.
Uso de los recursos públicos de una clase
Cuando en el programa principal definimos un objeto de una clase y ejecutamos un método sobre esa clase,
basta con poner el identificador:
ColaDoble s;
...
if (s.EstaVacia())
...
2 El inconveniente obvio de esta solución es que la velocidad del juego depende de la velocidad del ordenador. Para
conseguir que sea independiente es necesario tener en cuenta el tiempo que ha pasado entre el inicio de un movimiento y el
momento actual. Eso se puede conseguir con funciones presentes en la biblioteca ctime
3
E.T.S.I. Telecomunicación. Lab. Prog. 2
El juego de la serpiente
Sin embargo, si queremos hacer uso de los demás recursos de la clase, como, en este caso, el tipo TAnillo o
los valores del tipo enumerado TExtremo, tenemos que indicar expresamente a qué clase pertenecen, poniendo
delante el nombre de la clase y el operador de ámbito (::).
ColaDoble s;
ColaDoble::TAnillo a;
...
s.Encolar(a, ColaDoble::frente);
...
4

Documentos relacionados