Download Jugador de dominó

Document related concepts
no text concepts found
Transcript
Jugador de dominó
Alejandro Casas García
Jaime Esquivias Sauras
Daniel Franco Antón
Informe
Objetivos
Nuestro objetivo es implementar un jugador de dominó en Java, programándole una
estrategia de juego lo más perfecta posible, que nos lleve a ganar el mayor número de veces
posibles.
Para alcanzar nuestro objetivo, hemos dividido el trabajo en tres partes:
1. Implementación de un jugador simple.
Primero necesitamos implementar un jugador de dominó que
simplemente siga las reglas del dominó de forma correcta hasta el final de
la partida.
2. Implementación de distintos algoritmos.
Una vez tenemos implementado un jugador de dominó básico,
programamos distintos jugadores que sigan distintas estrategias de juego.
3. Creación de un script para comparar los algoritmos.
Finalmente, puesto que probar las estrategias de juego necesitamos
realizar muchas pruebas de partidas, hemos implementado un script que
realiza una serie de partidas aleatorias y muestra la proporción de partidas
ganadas por cada jugador, permitiéndonos analizar las distintas estrategias.
Descripción del trabajo realizado
El jugador simple: SimplePlayer.java, Ficha.java, Tablero.java
Para la implementación del jugador simple, usamos dos clases auxiliares para modelar el juego
del dominó:
Ficha.java
Representa una ficha del juego.
Incluye métodos para crear una Ficha desde su representación en String, volver a recuperar su
representación en String, comprobar si contiene un número, realizar jugadas con ella…
Tablero.java
Representa un tablero de dominó.
Incluye métodos para introducir fichas en el tablero, pintar el tablero, obtener los siguientes
movimientos posibles, contar cuantas fichas de un número…
El uso de estas clases nos permiten realizar una implementación del jugador más simple,
delegando las reglas que definen el juego del dominó en estás clases y permitiéndonos
concentrarnos en la implementación del jugador. Además, si necesitamos realizar nuevas
operaciones con las fichas de nuestro jugador o las de tablero, para seguir una cierta estrategia,
podemos ampliar los métodos de estas clases, resultando una programación más limpia.
SimplePlayer.java
Para implementar el jugador, esté dispondrá de un Tablero y una lista enlazada (LinkedList) de
Fichas. Mediante el uso de las clases anteriormente explicadas, es bastante sencillo completar
los métodos que se definen en la interfaz Player para realizar el jugador, cuya estrategia no es
otra que elegir la primera ficha que encuentra para juagar en su turno.
Jugadores con estrategia:
Para llevar a cabo las distintas estrategias, extendemos la clase Simpleplayer, reescribiendo el
método nextMove() donde se encuentran nuestra estrategia. De esta forma hemos creado los
siguientes jugadores:
EvilPlayer.java
Su estrategia es intentar que los demás jugadores no tengan ficha que jugar y se vean
obligados a pasar turno. Para ello, siempre pondrá, de entre sus posibles juagadas, la que deje
como siguiente ficha a poner (lado contrario al que jugamos) la que más veces haya salido en
el tablero, disminuyendo la posibilidad de que los adversarios tenga una ficha con ese número.
Por ejemplo, si sus fichas para poner son 2-3, 2-6 y 2-1, y las tiene que jugar por el lado del 2,
contará que número ha salido más veces en el tablero (el 3, el 6 o el 1) y así conocerá que ficha
poner.
DefensePlayer.java
La estrategia ahora es más bien la contraria, evitar tener que pasar turno. Para ello este
jugador pondrá, de entre sus fichas, la que deje el siguiente movimiento con el número que
menos haya salido en el tablero, aumentando la posibilidad de que los demás jugadores (y el
mismo), tengan para poner ficha después.
ProtectPlayer.java
Otra forma de jugar defensivamente, que parece más correcta que la estrategia anterior, es
dejar el siguiente movimiento, con el número del que más fichas tengas para poner, así
intentamos que la próxima tengamos alguna ficha que introducir en el tablero, al mismo
tiempo que aumentamos la posibilidad de que nuestros adversarios no tengan (ya que
nosotros tenemos muchas fichas con ese número).
Por ejemplo, si podemos jugar 2-3 o 2-5 por el lado del 2, y tenemos muchas fichas con el
número 5, elegiremos el 2-5, antes que la otra ficha.
BloqueoPlayer.java
La estrategia de este jugador es la misma que se ha explicado anteriormente, con una
diferencia, da prioridad a las fichas que llevan el tablero a tener una sola posibilidad de juego
y además producir un bloqueo con ella. Estas fichas son las que contienen los números de las
dos jugadas posibles. Es decir, si tenemos para jugar el 2 y el 5 y tenemos la ficha 2-5, podemos
usarla para llevar el juego a que sólo se pueda poner 2 o sólo 5, aumentando la posibilidad de
que nuestros enemigos no tenga que poner. Y si comprobamos que de una de las dos
posibilidades, están todas las fichas posibles en nuestras manos y en el tablero, significará que
ningún jugador excepto nosotros podrá poner después, por lo que debemos priorizar el
movimiento.
ComplexPlayer.java
Con este jugador hemos intentado mejorar los resultados obtenidos con los anteriores,
mezclando sus estrategias. En este caso la estrategia de éste es:
1. Si encontramos un bloqueo perfecto (Nadie excepto nosotros puede continuar) y
además tenemos fichas para continuar poniendo después, lo realizamos.
2. Si no podemos, pero aun así, podemos llevar al juego a que sólo se pueda jugar a un
número, y de éste, entre nuestras manos y el tablero ya hay más de 4 fichas puestas
(Es probable que hagamos pasar a algún jugador), realizamos este movimiento.
3. En otro caso realizamos el movimiento que decida el ProtectPlayer, que es el que
mejor resultado nos ha dado de los anteriores jugadores.
Script de comparación:
Ya que en el juego del dominó existe una gran componente de aleatoriedad, debido a que las
fichas iniciales son repartidas a ciegas, no nos basta con realizar dos o tres partidas con los
distintos jugadores para determinar que estrategias son mejores. Necesitamos construir un
script que los haga competir un gran número de veces y mostrar los resultados.
Hemos implementado un script batch (comparar.bat), ejecutable en Windows, que pone a
jugar 100 veces a los jugadores que elijamos, en 100 partidas con fichas distintas (que han sido
generadas mediante un pequeño programa en java). Tras hacerlos jugar, imprime los
resultados obtenidos, que son analizados mediante un pequeño programa en java al que
hemos llamado Podio.java
Para usar el script, debemos abrirlo mediante un editor de texto plano y editar la línea
“set
jugadores=
Dom_Players.SimplePlayer
Dom_Players.SimplePlayer
(…)”
Para que contenga la lista de jugadores que jugaran las distintas partidas.
Conclusiones:
Con el uso del script hemos puesto a jugar a nuestros jugadores con estrategia con otros tres
jugadores simples, y hemos notado que había mucha diferencia en los resultados entre
colocarlos como jugadores número uno, dos, tres… eso demuestra que existe una gran
dependencia de las fichas que te toquen para jugar. También hemos notado que el jugador
que juega el primer turno, gana un mayor número de veces. Por el hecho de ser el primero en
soltar ficha, dispone de una cierta ventaja.
El algoritmo que hemos visto un poco más potente ha sido el que sigue el jugador
“ProtectedPlayer” que ha llegado a conseguir un 30% de partidas ganadas, pero sigue siendo
un porcentaje muy bajo.
Con el jugador “ComplexPlayer” hemos mejorado su algoritmo hasta conseguir un 35% de
partidas ganadas, en los mejores casos. Pero sigue siendo muy bajo. Nos hubiera gustado
disponer de más tiempo para implementar otros algoritmos, ya que, construida la base, es fácil
crear nuevos algoritmos y probar su eficacia.