Triqui en Qt4

Anuncio
Triqui en Qt4
Andrés Becerra Sandoval
October 2, 2014
1
Triqui
1.1
Idea
Crear un programa para jugar triqui, entre dos jugadores humanos, alternándose.
1.2
Requerimientos
• Proveer una interfaz gráfica para jugar triqui en la que las jugadas se hacen
con el apuntador.
• Registrar el estado del tablero en todo momento.
• Calcular si el juego se termina por empate o victoria de algún jugador.
• Después de terminar un juego, permitir iniciar uno nuevo.
2
Clases y responsabilidades
tableroTriqui: representa el tablero del juego. Responsabilidades:
• reporta y cambia el estado de una casilla del triqui
• averigua si hay empate
• averigua si un jugador gana
• reinicia el tablero
colaboraciones: ninguna
juegoTriqui: representa el juego. Responsabilidades:
• registra una jugada
• reporta el estado de una casilla del triqui
• reporta el estado del juego {jugando, empatado, ganado}
1
• reporta el turno actual
• reinicia el juego
• cambia el turno de un jugador al otro
colaboraciones: tableroTriqui
boton: representa un botón en la interfaz gráfica
• reporta la fila del botón
• reporta la columna del botón
• muestra y actualiza el estado de una casilla del tablero
colaboraciones: ninguna
ventana: representa la interfaz gráfica de la aplicación
• crea los botones para jugar
• cambia el estado del juego cuando se presionan los botones
• actualiza el estado de un botón después de una jugada
• muestra el estado del juego
colaboraciones: boton, juegoTriqui
3
Aspirando al bajo acoplamiento
Para mantener el bajo acoplamiento las clases TableroTriqui y JuegoTriqui no
tienen dependencias de Qt. Representan el «modelo», la lógica del juego triqui
que no depende de la forma de jugarlo (con interfaz gráfica, en la línea de
comandos, etc.).
Ambas utilizan las siguientes enumeraciones para representar el estado de las
casillas en el tablero, del juego, del turno y para saber donde ganó un jugador
en un momento dado:
Listing 1: enums.h
#i f n d e f ENUMS_H
#define ENUMS_H
enum
enum
enum
enum
Turno { uno=1, dos=2 } ;
E s t a d o C a s i l l a { v a c i a =0, juno =1, j d o s =2 } ;
EstadoJuego { jugando , empate , ganado } ;
DondeGano{ f i l a , columna , d i a g o n a l } ;
#endif
2
Observe que los valores de Turno, uno y dos, son iguales a los EstadoCasilla,
juno y jdos.
La clase tablero triqui está definida a continuación:
Listing 2: tableroTriqui.h
class TableroTriqui {
public :
TableroTriqui ( ) ;
E s t a d o C a s i l l a e s t a d o C a s i l l a ( int f i l , int c o l ) const ;
DondeGano dondeGano ( ) const ;
int numeroGano ( ) const ;
bool c a m b i a C a s i l l a ( int f i l , int c o l , Turno t u r n o ) ;
bool hayEmpate ( ) ;
bool gana ( Turno turno , int f i l , int c o l ) ;
void r e i n i c i a r ( ) ;
private :
s t a t i c const int tam = 3 ;
E s t a d o C a s i l l a t a b l e r o [ tam ] [ tam ] ;
DondeGano m_dondeGano ;
int m_numeroGano ;
// d i a g o n a l , f i l a o columna
// que numero de f i l a , c o l o d i a g
bool ganaEnDiagonal1 ( Turno ) ; // d i a g o n a l uno
bool ganaEnDiagonal2 ( Turno ) ; // d i a g o n a l dos
bool ganaEnFila ( int f i l , Turno ) ;
bool ganaEnColumna ( int c o l , Turno ) ;
T a b l e r o T r i q u i ( const T a b l e r o T r i q u i &);
(\)
(/)
};
Al tener toda la lógica del tablero en una clase se espera que este código no
cambie al portarlo a otro tipo de interfaz gráfica.
La lógica del juego está en la clase juegoTriqui, a continuación:
Listing 3: juegoTriqui.h
class TableroTriqui ;
class JuegoTriqui {
public :
JuegoTriqui ( ) ;
~JuegoTriqui ( ) ;
bool j u g a r ( int f i l a , int columna ) ;
E s t a d o C a s i l l a e s t a d o C a s i l l a ( int f i l a , int columna ) ;
void r e i n i c i a r ( ) ;
EstadoJuego e s t a d o ( ) ;
Turno t u r n o ( ) ;
3
DondeGano dondeGano ( ) ;
int numeroGano ( ) ;
private :
void cambio_de_Turno ( ) ;
Turno m_turno ;
EstadoJuego m_estado ;
TableroTriqui ∗ tableroTriqui ;
};
#endif
JuegoTriqui maneja el ciclo de vida de un tableroTriqui y actúa como una
fachada (facade) hacia él.
4
Diagrama de clases
A continuación se representan las relaciones de agregación y herencia entre las
clases
Algunos comentarios:
• La ventana de la aplicación maneja el ciclo de vida de un juegoTriqui, pero
no interactúa directamente con el tableroTriqui
• La «vista», es decir, la representación gráfica del juego, a través de una matriz de botones, es diferente del modelo (tableroTriqui) pero se mantienen
en sincronía.
• Los botones almacenan la fila y columna a la que pertenecen para poder
actualizar su estado de acuerdo a tableroTriqui
4
El slot botonPresionado actúa como controlador sincronizando el modelo (juegoTriqui) con la vista (botonesJuego) que es una matriz de botones:
Listing 4: ventana.cpp
void Ventana : : b o t o n P r e s i o n a d o ( ) {
int f i l a ;
i n t columna ;
EstadoJuego e s t a d o J u e g o ;
int r ;
Boton ∗ b o t o n R e c i e n P r e s i o n a d o = q o b j e c t _ c a s t <Boton ∗>( s e n d e r ( ) ) ;
f i l a = b o t o n R e c i e n P r e s i o n a d o −>o b t e n e r F i l a ( ) ;
columna = b o t o n R e c i e n P r e s i o n a d o −>obtenerColumna ( ) ;
i f ( j u e g o −>j u g a r ( f i l a , columna ) ) {
a c t u a l i z a r ( botonRecienPresionado ) ;
e s t a d o J u e g o = j u e g o −>e s t a d o ( ) ;
i f ( e s t a d o J u e g o==ganado ) {
QString mensajeTriunfo ;
i f ( j u e g o −>t u r n o ( ) == uno )
m e n s a j e T r i u n f o = Q S t r i n g ( "Gana␣ e l ␣ Primer ␣ j u g a d o r , ␣ \n␣ Desean ␣ j u g a r ␣ o t r o ? " ) ;
else
m e n s a j e T r i u n f o = Q S t r i n g ( "Gana␣ e l ␣ Segundo ␣ j u g a d o r , ␣ \n␣ Desean ␣ j u g a r ␣ o t r o ? " ) ;
r = QMessageBox : : q u e s t i o n ( 0 , " Fin ␣ d e l ␣ j u e g o " , m e n s a j e T r i u n f o , QMessageBox : : Yes | QMess
i f ( r == QMessageBox : : No)
close ();
else {
j u e g o −> r e i n i c i a r ( ) ;
reiniciar ();
}
}
e l s e i f ( e s t a d o J u e g o==empate ) {
r = QMessageBox : : q u e s t i o n ( 0 , " Fin ␣ d e l ␣ j u e g o " , "Hay␣ empate , ␣ d e s e a n ␣ j u g a r ␣ o t r a ␣ v e z ? " , QM
i f ( r == QMessageBox : : No)
close ();
else {
j u e g o −> r e i n i c i a r ( ) ;
reiniciar ();
}
}
}
e l s e { // ya s e h a b i a j u g a d o en l a c a s i l l a
Phonon : : MediaObject ∗ mediaObject = Phonon : : c r e a t e P l a y e r ( Phonon : : MusicCategory , Phonon : : M
mediaObject−>p l a y ( ) ;
}
}
5
Código fuente
En https://github.com/abecerra/triqui2/ encuentran la implementación.
5
Descargar