Anda di halaman 1dari 4

Ejercicio de árboles

Encontrar un algoritmo que permita decidir el próximo movimiento a realizar en un juego


competitivo (damas, ajedrez, tres en raya, conecta 4,…). El algoritmo deberá basarse en
los siguientes principios:

1. Deberá encontrar el mejor movimiento a realizar, esto es, el que tiene más
probabilidades de llevarnos a ganar la partida.
2. Deberá ser un algoritmo genérico, válido para cualquier tipo de juego en el que
compitan dos jugadores y no haya elementos de azar (por ejemplo dados)

1
Solución

1. Paso primero: analizar el problema tratando de resolverlo de forma abstracta.

a. ¿Cómo encontrar el mejor movimiento?


b. Pues evaluándolos todos y escogiendo el mejor.
c. Evaluarlos todos en el fondo supone construir un árbol con todas las
posibles opciones sucesivas de movimiento a partir de la posición actual.
d. Las hojas del árbol serán los finales de partida.
e. Habrá que valorar cada final de partida como más o menos adecuado para
mí.
f. Escogeré un final de partida favorable, pero…
g. …¿qué tiene que decir mi rival?
h. En cada capa del árbol…
i. …si muevo yo, escogeré el movimiento más favorable para mí.
ii. …si mueve él, escogerá el movimiento menos favorable para mí.

2. Paso segundo: plantear el pseudocódigo.

a. Si estamos trabajando con un árbol, en principio tenderé a pensar en una


solución recursiva.
b. Esto me facilitará ir construyendo el árbol “sobre la marcha”.
c. ¿Cuáles serán las condiciones de parada de la recursión?
i. Cuando llegue a una situación en que la partida ha finalizado.
d. Pasos a dar en cada llamada recursiva:
i. Comprobar la condición de parada.
1. Si se cumple, evaluar cómo de favorable es ese final de
partida y devolver el resultado de la evaluación.
2. Si no se cumple, continuar.
ii. Hallar todos los movimientos posibles para este turno.
iii. Para cada movimiento posible hacer lo siguiente:
1. Generar la nueva situación de partida que se generaría tras
realizar dicho movimiento.
2. Evaluar cómo de bueno es el movimiento (llamada
recursiva)
iv. Si me toca mover a mí, devolver la evaluación del movimiento
mejor evaluado.
v. Si le toca mover a mi rival, devolver la evaluación del movimiento
peor evaluado.
e. Al método recursivo le pasaré como argumentos:
i. Un estado de la partida.
ii. El jugador al que le toca mover.
f. Devuelve:
i. Evaluación.
ii. Movimiento.
g. Inicialmente, llamaré al método con el estado actual de la partida y mi
jugador.
h. Más formalmente:

2
//”jugador” valdrá 1 para mi jugador y -1 para el contrario
Algoritmo eligeMovimiento (tablero, jugador) Æ entero, movimiento

if (esFinalDePartida(tablero))
return evaluaFinal(tablero)

else
movimientosPosibles [] = dameMovimientosPosibles(tablero)
evaluacionesMovimientos []

for (cada movimiento posible)


nuevoTablero = generarNuevoTablero(tablero,
movimientoPosible[i], jugador)
evaluacionesMovimientos[i] = eligeMovimiento(nuevoTablero,
-jugador);

if (jugador = 1) return (max(evaluacionesMovimientos[]),


movimiento correspondiente)

else return (min(evaluacionesMovimientos[]), movimiento


correspondiente)

i. Habría que escribir en pseudocódigo cada uno de los subalgoritmos utilizados, que
dependen del juego concreto que estemos jugando.

3. Paso tercero: Traducir el pseudocódigo al lenguaje de programación (Java en nuestro caso)

a. ¿Lo hacéis vosotros para, un poner, el Conecta4? ;-)

4. Paso cuarto: refinamientos.

a. La fuerza bruta tiene el problema de los recursos:


i. Lleva demasiado tiempo.
ii. Ocupa demasiada memoria.
b. Dos posibles soluciones:
i. No llegar en el árbol más allá de cierta profundidad máxima.
ii. No tardar en la búsqueda más de un cierto tiempo.
c. ¿Cómo afecta esto al algoritmo?
i. Ahora tendré más condiciones de parada:
1. Parar si he alcanzado la profundidad máxima permitida.
2. Parar si he alcanzado el tiempo máximo permitido.
ii. Argumentos:
1. Tendré que pasar también como argumento la profundidad actual.
iii. Tendré que evaluar situaciones de partida que no son finales:
1. Definir una “función de evaluación” que me diga cuán buena es esa
situación de partida para mí.
2. ¡De lo buena que sea esta función de evaluación depende lo bueno o
malo que será mi algoritmo!!!
3. Conviene prestarle atención a esto…

3
Ejemplo: Conecta4

• Final de partida:
o Cuando uno de los dos jugadores hace 4 en raya.
o Cuando ya no hay más movimientos posibles.
• Evaluación de un final de partida:
o Valor positivo si gano…
o …0 si empato…
o …valor negativo si pierdo.
o Puedo dar un valor mayor absoluto cuanto menos profundo en el árbol esté
este final (quiere decir que gano o me ganan en menos movimientos)
• Movimientos posibles:
o Buscar los huecos libres en la fila superior del tablero.
• Función de evaluación:
o Restar al número de oportunidades (posiciones de 2 y 3 en raya mías
susceptibles de ser culminadas)…
o …el número de amenazas (posiciones de 2 y 3 en raya de mi rival
susceptibles de ser culminadas)

¡¡Esto son sólo algunas ideas, se puede hilar tan fino como se quiera!!
(eso distingue a los mejores jugadores de los no tan buenos ;-)

LO QUE ACABAMOS DE VER ES LO QUE SE DENOMINA


ALGORITMO
MINIMAX

Anda mungkin juga menyukai