Anda di halaman 1dari 4

Ejemplo

! Las 8 reinas
! Colocar 8 reinas en un tablero de ajedrez sin que se puedan
El problema de las Ocho Reinas comer unas a otras

! Para ilustrar el uso de objetos, cada Reina es un objeto que


Programación Orientada a Objetos puede tener capacidad de descubrir la solución
Facultad de Informática

! Solución de Timothy Budd, en su libro An Introduction to


Juan Pavón Mestras Object-Oriented Programming
Dep. Sistemas Informáticos y Programación
Universidad Complutense Madrid

Juan Pavón Mestras


Facultad de Informática UCM, 2004-05 2

Observaciones Estructuración del problema

! No puede haber dos reinas en la misma columna: ! Para la comunicación entre reinas, se puede organizar de
! Las reinas se pueden asignar a columnas distintas, entonces manera que cada reina tenga la referencia de la de su
el problema se reduce a encontrar las filas donde colocarlas izquierda
! Cada reina conoce las posiciones que puede atacar ! Será a esa reina a la que pueda enviar mensajes
! A cada reina se le puede pedir que proponga una solución, ! Las peticiones en el programa se harán a la reina que esté
y más tarde que proponga otra solución más a la derecha
! Se trata de la estrategia generar y probar
• Primero se genera una solución
• Luego se comprueba si es buena D8
• Si no lo es, volvemos a intentarlo
D3 D5 D7
D2
D1 D4 D6

Juan Pavón Mestras Juan Pavón Mestras


Facultad de Informática UCM, 2004-05 3 Facultad de Informática UCM, 2004-05 4
Diseño de cada Reina Inicialización

! Responsabilidades import java.awt.*;


import java.applet.*;
! Buscar una solución
! Evaluar si una posición es atacable class Reina {
! Avanzar fila // atributos
private int fila;
private int columna;
! Atributos private Reina vecina;
! Columna: la que se le ha asignado a la reina (inmutable para
ella) // constructor
! Fila: irá cambiando en búsqueda de una solución Reina (int c, Reina v) {
! Siguiente reina a la izquierda fila = 1; // empieza a buscar una solución desde la primera fila
columna = c; // la columna que se le ha asignado a esta reina
vecina = v; // referencia a la reina de la izquierda
}
// ...
}

Juan Pavón Mestras Juan Pavón Mestras


Facultad de Informática UCM, 2004-05 5 Facultad de Informática UCM, 2004-05 6

Comprobar si una casilla es atacable Cómo encontrar una solución

! Comprueba si la reina o una a su izquierda puede atacar ! Para encontrar una solución una reina le pregunta a sus
una posición vecinas si pueden atacarla
! Si no pueden atacarla es que se ha alcanzado una solución
private boolean puedeAtacar(int testfila, int testcolumna) { ! Si pueden atacarla, avanza una posición
int diferenciaColumnas = testcolumna - columna;
if ((fila == testfila) || // en la misma fila public boolean buscaSolución() {
(fila + diferenciaColumnas == testfila) || // o en una diagonal // si nadie la puede atacar ya es una solución:
(fila - diferenciaColumnas == testfila)) if ( vecina == null || !vecina.puedeAtacar(fila, columna) )
return true; return true;

if (vecina != null) // mira si es atacable por las reinas a la izda. // si no, intenta avanzar a donde no la puedan atacar:
return vecina.puedeAtacar(testfila, testcolumna); if ( avanzar() ) return true;

return false; // la posición no es atacable return false; // no se ha encontrado una solución


} }
Juan Pavón Mestras Juan Pavón Mestras
Facultad de Informática UCM, 2004-05 7 Facultad de Informática UCM, 2004-05 8
Método avanzar Pintar las reinas

! Hay dos casos public void pintaReinas (Graphics g) {


! Si no está al final, avanza una posición // primero pinta las vecinas
! Si no quedan más posiciones, habrá que preguntarle al vecino que
if (vecina != null) vecina.pintaReinas(g);
busque otra solución y empezar de nuevo en la primera fila

public boolean avanzar() { // y luego a sí misma


if ( fila < 8 ) { // avanzar una posición y mirar si hay solución // x, y es la esquina superior izquierda
fila++; int x = (fila - 1) * 50;
return buscaSolución(); int y = (columna - 1) * 50;
} g.drawLine(x+5, y+45, x+45, y+45);
g.drawLine(x+5, y+45, x+5, y+5);
// si no puede avanzar, intentar que lo hagan las vecinas: g.drawLine(x+45, y+45, x+45, y+5);
if ( vecina != null && !vecina.avanzar() ) return false; g.drawLine(x+5, y+35, x+45, y+35);
g.drawLine(x+5, y+5, x+15, y+20);
// habiendo avanzado la vecina, g.drawLine(x+15, y+20, x+25, y+5);
// vuelve a la primera fila para encontrar una nueva solución: g.drawLine(x+25, y+5, x+35, y+20);
fila = 1; g.drawLine(x+35, y+20, x+45, y+5);
return buscaSolución(); g.drawOval(x+20, y+20, 10, 10);
} }
Juan Pavón Mestras Juan Pavón Mestras
Facultad de Informática UCM, 2004-05 9 Facultad de Informática UCM, 2004-05 10

El applet OchoReinasApplet El applet OchoReinasApplet

public class OchoReinasApplet extends Applet { //...


private Reina últimaReina; public void paint(Graphics g) {
// pinta el tablero
public void init() { for (int i = 0; i <= 8; i++) {
últimaReina = null; g.drawLine(50 * i, 0, 50*i, 400);
for (int i = 1; i <= 8; i++) { g.drawLine(0, 50 * i, 400, 50*i);
// crea una reina }
últimaReina = new Reina(i, últimaReina); // pinta las reinas
// e intenta colocarla sin que nadie le ataque últimaReina.pintaReinas(g);
últimaReina.buscaSolución(); }
}
} public boolean mouseDown(java.awt.Event evt, int x, int y) {
// ... últimaReina.avanzar(); // busca otra solución
repaint();
return true;
}
}

Juan Pavón Mestras Juan Pavón Mestras


Facultad de Informática UCM, 2004-05 11 Facultad de Informática UCM, 2004-05 12
Las Ocho Reinas en C++ Las Ocho Reinas en C++

class Reina { Reina::Reina (int c, Reina* v): columna(c), vecina(v) {


public: fila = 1; // empieza a buscar una solución desde la primera fila
Reina (int c, Reina* v); }

bool buscaSolucion(); void Reina::print() {


bool avanzar(); if (vecina)vecina->print(); // primero lista las vecinas
void print(); cout << "columna " << columna << " fila " << fila << '\n';
}
private:
int fila; bool Reina::puedeAtacar(int testfila, int testcolumna) {
const int columna; int diferenciaColumnas = testcolumna - columna;
Reina* vecina; if ((fila == testfila) || // en la misma fila
(fila + diferenciaColumnas == testfila) || // o en una diagonal
bool puedeAtacar(int testfila, int testcolumna); (fila - diferenciaColumnas == testfila))
}; return true;

// mira si es atacable por las vecinas de la izquierda


return ( vecina && vecina->puedeAtacar(testfila, testcolumna) );
Juan Pavón Mestras
}
Juan Pavón Mestras
Facultad de Informática UCM, 2004-05 13 Facultad de Informática UCM, 2004-05 14

Las Ocho Reinas en C++ Las Ocho Reinas en C++

bool Reina::buscaSolucion() { int main() {


// si está bien colocada (nadie la puede atacar) ya es una solución: int cuenta = 0; // cuenta de todas las posibles soluciones
if ( !vecina || !vecina->puedeAtacar(fila, columna) ) return true; Reina* ultimaReina = 0;
// si no, intenta avanzar a una posición donde no la puedan atacar:
if ( avanzar() ) return true; for (int i = 1; i <= 8; i++) {
return false; // no se ha encontrado una solución // crea una reina
} ultimaReina = new Reina(i, ultimaReina);
// e intenta colocarla sin que nadie le ataque
bool Reina::avanzar() { if ( !ultimaReina->buscaSolucion() )
if ( fila < 8 ) { // avanza una posición y mira si hay solución cout << "No hay solución\n" ;
fila++; }
return buscaSolucion();
} do {
// si no puede avanzar, intenta que lo hagan las vecinas: cout << "\nSolución " << ++cuenta;
if ( !vecina || !vecina->avanzar() ) return false; cout << " ==============" << endl;
// habiendo avanzado la vecina, busca otra solución desde la fila 1: ultimaReina->print();
fila = 1; }
return buscaSolucion(); while ( ultimaReina->avanzar() );
} }
Juan Pavón Mestras Juan Pavón Mestras
Facultad de Informática UCM, 2004-05 15 Facultad de Informática UCM, 2004-05 16

Anda mungkin juga menyukai