[C con Clase] Ayuda[minijuego]
Steven Davidson
srd4121 en njit.edu
Mar Feb 16 00:23:06 CET 2010
Hola Daniel,
Rido wrote:
> ¡¡¡Buaf ya lo hice!!! ---> http://cl1p.net/codigo/ <---
>
> El problema era que había que resetear también las variables punt1 y
> punt2, por lo que hice un procedimiento que lo hiciese y lo puse al
> inicio del case contra la máquina y del case de jugador contra
> jugador.
>
> Si alguno ve algún otro problema por favor comuníquemelo. Muchas
> gracias a todos por vuestra ayuda.
>
> En breve haré que se alternen los turnos para que la máquina no tenga
> tanta ventaja y lo subiré a la dirección de siempre:
> http://cl1p.net/codigo/
>
Como estás terminando el juego, quiero aprovechar para hacerte unos
comentarios acerca del código fuente:
- El nombre correcto del fichero de cabecera en C++ es <ctime>.
- Define las constantes en C++ en lugar de usar el precompilador. Esto es,
const int CARTAS = 12;
const int PALOS = 4;
const int BARAJA = CARTAS*PALOS;
- Elimina 'typedef', ya que no es necesario.
- Existen 13 elementos para los arrays 'jug1' y 'jug2'. Aconsejo que
definas y uses una constante para representar esta cantidad, en lugar de
usar el literal directamente.
- En 'inicializar()', usas 11 y 12 en lugar de la constante 'CARTAS'.
También usas 1 y 0 para el miembro 'cog', cuando deberías acostumbrarte
a usar los valores booleanos 'true' y 'false'.
- Has decidido diseñar el programa usando una baraja de 48 cartas, aun
sabiendo que el juego requiere una de 40. Sugiero que definas una baraja
de 40 cartas y así no tienes que estar eliminando cartas que no te
interesa. Desde el punto de vista del juego, sólo existen 40 cartas, y
por tanto, el programa debería implementar tal diseño.
- En 'intercambiar()', eliges aceptar punteros a las cartas. Creo que
convendría usar referencias. El diseño de 'intercambiar()' es lo
suficientemente claro para entender que se requieren las variables y no
los valores.
- No invoques 'srand()' más de una vez, en un programa. Solamente hazlo
al principio, en 'main()'. Elimina la invocación en 'jugador()'.
- En 'jugador()', usas 'cont' como índice de 'jug', pero de una manera
descontrolada. Ten presente que tienes 13 elementos para cada jugador.
Deberías limitar el valor que 'cont' puede guardar para que no acceda a
elementos fuera del array.
- Usas un bucle para calcular la puntuación total del jugador. Sin
embargo, haces esto en cada iteración del bucle 'do/while'. Esto es
superfluo. Haces algo como esto:
do
{
...
for( j=0; j<=cont; j++ )
punt += jug[j];
...
} while( ... );
Sólo nos interesa acumular los puntos en cada iteración. Al final de
este bucle obtendremos la puntuación total. Simplemente hacemos esto:
do
{
...
punt += jug[cont];
...
} while( ... );
- Usas un 'switch/case' para elegir un mensaje acerca del palo de la
carta. Sugiero crear un array de cadenas constantes estratégicamente
para que coincida con los palos que has diseñado. Por ejemplo,
const char *szPalos[PALOS] = { "copas", "oros", "espadas", "bastos" };
Ahora no tienes más que usar el miembro 'palo' como índice a esta lista
de cadenas constantes. Esto es,
cout << baraja[i].num << " de " << szPalos[ baraja[i].palo ];
Así nos evitamos realizar comprobaciones innecesarias.
- Deberías comprobar mejor la opción introducida por el usuario.
Compruebas si el usuario ha elegido 'D', pero no haces ninguna
distinción para 'P'. El usuario siempre puede escribir otro carácter que
no está permitido por tu programa.
- No se sabe la razón de la terminación del bucle y de la función
'jugador()', porque usas 'vcon' para terminar el bucle y además no
retornas el estado del juego a través de la función.
Aconsejo crear y mantener un sistema por estados. Por ejemplo,
enum estado_t { VICTORIA_JUG1=1, VICTORIA_JUG2=2 };
Ahora podemos usar estas constantes con una variable que represente el
estado del juego para determinar si hay victoria y de quién. Por ejemplo,
// inicialmente
estado_t nEstado = 0;
// Agregamos la NO Victoria del jugador 1
nEstado &= ~VICTORIA_JUG1;
// Agregamos la NO Victoria del jugador 2
nEstado &= ~VICTORIA_JUG2;
// Agregamos la Victoria del jugador 1
nEstado |= VICTORIA_JUG1;
// Agregamos la Victoria del jugador 2
nEstado |= VICTORIA_JUG2;
Después del juego, comprobamos el estado del juego para su resolución:
if( nEstado & (VICTORIA_JUG1 | VICTORIA_JUG2) )
{
// Ambos jugadores son victoriosos <= 7.5
// Resolución: Determinar cuál de los dos jugadores es el ganador
}
else if( nEstado & VICTORIA_JUG1 )
cout << "El jugador 1 se planta" << endl << endl;
else if( nEstado & VICTORIA_JUG2 )
cout << "El jugador 2 se planta" << endl << endl;
else
cout << "No hay ganadores" << endl << endl;
- Lo mismo sucede con 'maq()'.
- Aconsejo rediseñar las funciones 'jugador()' y 'maq()'. A veces estas
funciones implementan las tareas del jugador (o máquina), pero otras
veces tratan las tareas del juego en sí. Esto es incorrecto a mi
parecer. Cada función debe realizar la tarea imputada; ni más ni menos.
Si necesitas más tareas, entonces cada función debe comunicarse con el
exterior pasando la información interesada, para procesarla y
posiblemente para tomar otras decisiones.
Si te fijas, tanto 'jugador()' como 'maq()' son muy parecidas. Desde el
punto de vista de diseño, realmente no existe mucha diferencia entre un
jugador humano y otro automático. La diferencia está en la decisión de
aceptar o no otra carta.
Espero que todo esto te oriente.
Steven
Más información sobre la lista de distribución Cconclase