Dedicado a mis proyectos en Gambas ,un lenguaje de programación parecido al Visual Basic + Java pero ampliamente mejorado y...¡¡para gnu/linux!!.La potencia del gnu/linux sumada a la facilidad del Basic



Consultas, Desarrollo de programas y petición de presupuestos:



martes, 1 de octubre de 2013

Juego Conecta4: Paso a Paso (1) Estructura del Proyecto

Juego Conecta4: Paso a Paso (1)

Estructura del Proyecto


Como dije en la primera entrada de Conecta4 ( enlace ), vamos a desmembrar el código fuente para estudiarlo y explicarlo como funciona.

En primer lugar vamos a ver la estructura del código fuente del proyecto, en la siguiente imagen:
Como veis tenemos:
A) Clases:
ClassJugador (clase "padre") y ClassJugdorHumano y ClassJugadorOrdenador "que heredan de de la clase ClassJugador"
ClassJugador: Es la clase "padre" de las que van a heredar la clase ClassJugadorHumano y ClassJugadorOrdenador.
Estas últimas clases, tiene el método "juega" que se comparta de manera muy diferente si pertenece a una u otra clase. En el caso de ClassJugadorHumano, el método "juega" va a esperar que se el jugador humano pulse sobre una columna del tablero, para realizar el movimiento (si es posible) en el tablero.
Sin embargo en la clase ClassJugadorOrdenador, el método "juega", usa la función negamax del módulo "ia", para elegir la jugada a realizar.

ClassPartida:
En la versión 0.0.3, es una simple clase que se usa para iniciar una nueva partida, usando el formulario FormInicio. En principio preveo en próximas versiones, añadirle la opción de guardar y abrir partidas.

ClassTablero:
Es la clase más importante, ya que contiene:
- Propiedades:
La propiedad "casillas": Posee la información de la situación de las fichas de los jugadores (representados por 1,-1 ó 0 si esta vacía) en el tablero,  es un array integer de 2 dimensiones (7x7).
- Métodos:
New: inicia un tablero y es aprovechado para iniciar las casillas con valor "0"
Muestra: devuelve una copia del array casillas (información de fichas y jugador al que perteneces), para que sea usado en las subrutinas de dibujar el tablero. En versiones anteriores, mostraba en la consola el tablero.
Copia: devuelve una copia del array casillas, que será usado para crear tableros auxiliares.
InsertaFicha: es la función que se usa para modificar el tablero cuando se inserta una ficha. En el caso que devuelva el valor "False", se debe a que no se puede introducir una ficha en la columna que se ha indicado, y si devuelve "True", se ha colocado  correctamente y sin problemas la ficha en el tablero.
GameOver(): Comprueba si se ha producido tablas o ha ganado alguien (con la función ganador).
ganador: Comprueba si un jugador tiene 4 fichas juntas (en fila,columna o diagonal) en el tablero
comprueba_linea: Funcione que devuelve el numero de lineas de fichas que hay en el tablero de un jugador
comprueba_linea_Cuatro(): comprueba si se han formado conjunto de 4 fichas en Filas/Columnas/o Diagonal.
comparaCuaternaElemento(): Compara elementos de una array con otro, para ver si son iguales todos o no.
jugadasPosibles(): devuelve una array de las posibles jugadas que se pueden realizar. Esto significa que devuelve las columnas que no están llenas y por lo tanto podemos insertar una ficha.


B) Formularios:
FormInicio:
Simple formulario que nos muestras los iconos de gambas y conecta4, con un botón que es el que inicia una partida.

FormJugadores:
Este formulario es usado para dar a elegir el tipo de jugadores Humano o Ordenador, y si es Ordenador, indicar el nivel de inteligencia del jugador. Devuelve estos datos elegidos por el usuario, que serán usados para pasárselos al Formulario FmainTablero, para configurar asi el nuevo juego.


FmainTablero: Es el formulario donde mostraremos los datos de la partida: el tablero propiamente dicho, las fichas, el listado de jugadas que se ha realizado e información sobre la clase de jugadores (humano/ordenador / nivel). Además es donde el jugador humano interactua con el dibujo del tablero para indicar en que columna coloca su ficha.




C) Módulos
ia:
Contiene las funciones relacionadas con la Inteligencia Artificial del programa.
- La función negamax es la encargada de analizar el árbol de movimientos y quedarse con la mejor jugada (incluso hace las podas de jugadas no necesarias de calcular), y se usa de un modo "recursivo" (se llama a si misma).
El árbol de movimiento, se genera a partir del tablero inicial, donde se ven que movimientos son posibles, se ejecutan estos movimientos en tableros auxiliares (copias del original) y se vuelve a usar la función negamax de modo recursivo para analizar el nuevo tablero. Este proceso se repite hasta llegar al final de la profundidad a analizar del árbol o se encuentre un tablero donde se termine la partida. Al final devuelve la mejor jugada que puede realizar el jugador.
- La función EvaluaJugadaMov es la encargada de hacer la valoración un tablero según el jugador que se le pase, valorando el numero de veces que se produce en el tablero conjuntos de 2 fichas, 3 fichas o 4 fichas, que estén en el tablero de forma diagonal, horizontal o vertical.

main: 
Es el módulo de inicio del programa (indicado por el triangulo negro, junto a su nombre). Crea una instancia de la clase "ClassPartida", y usa su método ".inicio", con lo cual hace arrancar una partida. Además contiene la variable "maxinteger", que va a ser usada como variable global, (tendrán acceso todos los módulos y clases del programa).

Utilidades: 
Las funciones que incluye este formulario son de tipo "publicas" y de uso común  (osea muy usadas en otras aplicaciones). Pero realmente no se ha usado ninguna de ellas en esta aplicación.

E) Datos:
En esta carpeta tenemos alojados las dos imagenes que usamos en la aplicación, el icono de gambas3 y la imagen del juego conecta4


Nota:
¿seria necesario una clase Jugada o estructura que definiera la Jugada a realizar?
En concreto en este juego de conecta 4, las jugadas simplemente representa la columnas donde podemos insertar una ficha. Básicamente se trata de una información de una dimensión (valor de las columnas). Por lo tanto, una jugada es un número y se puede usar un array integer para contener la lista de jugadas posibles.

Sin embargo en otros juegos más complicados (por ejemplo las damas), las jugadas van a contener más información (coordenada donde empieza y coordenada donde termina, incluso coordenadas intermedias para indicar "saltos"). En este caso si sería necesario usar variables más complicadas (por ejemplo arrays de Variant, o estructuras o directamente clases ), para que pudieran manejar la información del movimiento de la ficha o pieza.

En la próxima entrada, entraremos más profundamente en el código.

Saludos