/* +-----------------+ | LAS OCHO REINAS | +-----------------+ El problema de las ocho reinas consiste en situar ocho reinas en un tablero de ajedrez, de forma que ninguna reina pueda actuar sobre cualquiera de las otras. El pseudocódigo de la función ensayar() es el siguiente: <PRINCIPIO ensayar> (i: entero) inicializar el conjunto de posiciones de la reina i-ésima +-REPETIR hacer la selección siguiente | +-SI segura ENTONCES | | poner reina | | +-SI i < 8 ENTONCES | | | LLAMAR ensayar (i + 1) | | | +-SI no acertado ENTONCES | | | | quitar reina | | | +-FINSI | | +-FINSI | +-FINSI +-HASTA acertada O no hay más posiciones <FIN> Observaciones sobre el código: 1) Estudiar la función ensayar() a partir de este pseudocódigo. 2) Vectores utilizados: int posiciones_en_columna[8]; RANGO: 1..8 BOOLEAN reina_en_fila[8]; RANGO: 1..8 BOOLEAN reina_en_diagonal_normal[15]; RANGO: -7..7 BOOLEAN reina_en_diagonal_inversa[15]; RANGO: 2..16 En C, el primer elemento de cada vector tiene índice 0, esto es fácil solucionarlo con las siguientes macros: #define c(i) posiciones_en_columna[(i)-1] #define f(i) reina_en_fila[(i)-1] #define dn(i) reina_en_diagonal_normal[(i)+7] #define di(i) reina_en_diagonal_inversa[(i)-2] Significado de los vectores: c(i) : la posición de la reina en la columna i f(j) : indicativo de que no hay reina en la fila j-ésima dn(k): indicativo de que no hay reina en la diagonal normal (\) k-ésima di(k): indicativo de que no hay reina en la diagonal invertida (/) k-ésima Dado que se sabe, por las reglas del ajedrez, que una reina actúa sobre todas las piezas situadas en la misma columna, fila o diagonal del tablero se deduce que cada columna puede contener una y sólo una reina, y que la elección de la situación de la reina i-ésima puede restringirse a los cuadros de la columna i. Por tanto, el parámetro i se convierte en el índice de columna, y por ello el proceso de selección de posiciones queda limitado a los ocho posibles valores del índice de fila j. A partir de estos datos, la línea poner reina del pseudocódigo es: c (i) = j; f (j) = di (i + j) = dn (i - j) = FALSE; y la línea quitar reina del pseudocódigo: f (j) = di (i + j) = dn (i - j) = TRUE; y la condición segura del pseudocódigo: f (i) && di (i + j) && dn (i - j) */ /* Ficheros a incluir: */ #include <stdio.h> /* printf () */ #include <conio.h> /* getch () */ /* Macros: */ #define BOOLEAN int #define TRUE 1 #define FALSE 0 /* Variables globales: */ BOOLEAN acertado; int posiciones_en_columna[8]; BOOLEAN reina_en_fila[8]; BOOLEAN reina_en_diagonal_normal[15]; BOOLEAN reina_en_diagonal_inversa[15]; #define c(i) posiciones_en_columna[(i)-1] /* rango de índice: 1..8 */ #define f(i) reina_en_fila[(i)-1] /* rango de índice: 1..8 */ #define dn(i) reina_en_diagonal_normal[(i)+7] /* rango de índice: -7..7 */ #define di(i) reina_en_diagonal_inversa[(i)-2] /* rango de índice: 2..16 */ /* Prototipos de las funciones: */ void proceso (void); void ensayar (int i); /* Definiciones de las funciones: */ void main (void) { printf ("\n\nPROBLEMA DE LAS OCHO REINAS:\n "); proceso (); printf ("\n\nPulsa cualquier tecla para finalizar. "); getch (); } void proceso (void) { register int i,j; for (i = 1; i <= 8; i++) f (i) = TRUE; for (i = 2; i <= 16; i++) di (i) = TRUE; for (i = -7; i <= 7; i++) dn (i) = TRUE; ensayar (1); if (acertado) for (printf ("\n\nLA SOLUCION ES:\n\n"), i = 1; i <= 8; i++) { for (j = 1; j <= 8; j++) printf ("%2d", c (j) == i ? 1 : 0); printf ("\n"); } else printf ("\n\nNO HAY SOLUCION.\n"); } void ensayar (int i) { int j = 0; do { j++; acertado = FALSE; if (f (j) && di (i + j) && dn (i - j)) { c (i) = j; f (j) = di (i + j) = dn (i - j) = FALSE; if (i < 8) { ensayar (i + 1); if (! acertado) f (j) = di (i + j) = dn (i - j) = TRUE; } else acertado = TRUE; } } while (! acertado && j != 8); }